As expected, as a UNIX look-alike, Linux includes these traditional UNIX software-development tools:
A text editor, such as vi or emacs, for editing the source code (described in Chapter 11)
A C compiler for compiling and linking programs written in C-the programming language of choice for writing UNIX applications (although nowadays, many programmers are turning to C++). Linux includes the GNU C and C++ compilers. Originally, the GNU C Compiler was known as GCC. The acronym GCC now stands for GNU Compiler Collection (see description in http://gcc .gnu.org/).
The GNU make utility for automating the software build process-the process of combining object modules into an executable or a library
A debugger for debugging programs. Linux includes the GNU debugger gdb.
A version-control system to keep track of various revisions of a source file. Linux comes with RCS (Revision Control System) and CVS (Concurrent Versions System). Nowadays, most open-source projects use CVS as the version-control system.
These tools are installed automatically if you select the Development Tools package group when you install Red Hat Linux from this book's companion CD-ROMs, following the steps outlined in Chapter 2. The next few sections briefly describe how to use these tools to write applications for Linux.
You may have noticed that most of the Linux software-development tools are from the Free Software Foundation's GNU project. The online documentation for all these tools comes as info files. The info program is GNU's hypertext help system.
To see info in action, type info at the shell prompt, or type Esc-x followed by info in GNU Emacs. Typically, I access info from GNU Emacs; doing so enables me to use online help while editing a program. However, you can always type info in a separate terminal window. Figure 23-1 shows the terminal window after I type info at the shell prompt.
In info, the online help text is organized in nodes; each node represents information on a specific topic. The first line shows the header for that node.
Figure 23-1 shows the initial info screen, with a directory of topics. This directory is an info file: /usr/share/info/dir, a text file that contains embedded special characters. The following are a few lines from the /usr/share/info/dir file that correspond to the screen shown in Figure 23-1:
$Id: dir,v 1.2 1996/09/24 18:43:01 karl Exp $ This is the file .../info/dir, which contains the topmost node of the Info hierarchy. The first time you invoke Info you start off looking at that node, which is (dir)Top. ^_ (This is the Ctrl+_ character) File: dir Node: Top This is the top of the INFO tree This (the Directory node) gives a menu of major topics. Typing "q" exits, "?" lists all Info commands, "d" returns here, "h" gives a primer for first-timers, "mEmacs<Return>" visits the Emacs topic, etc. In Emacs, you can click mouse button 2 on a menu item or cross reference to select it. * Menu: Texinfo documentation system * Standalone info program: (info-stnd). Standalone Info-reading program. * Texinfo: (texinfo). The GNU documentation format. * install-info: (texinfo)Invoking install-info. Update info/dir entries. * makeinfo: (texinfo)makeinfo Preferred. Translate Texinfo source. (...Lines deleted...)
A comparison of this listing with the screen shown in Figure 23-1 shows that info displays only the lines that follow the Ctrl+_ character. In your system, the /usr/share/info directory contains this info file, as well as others, with the text for each topic. Usually, these info files are stored in compressed format. You really don't have to know these details to use the info files.
Insider Insight |
You have to use several single-letter commands to navigate info files. The best way to learn the commands is to type h from the initial info directory, shown in Figure 23-1. Type d after reading the help screens to return to the initial directory of topics. |
From the directory screen of Figure 23-1, type m, followed by the name of a menu item (shown with an asterisk prefix). For example, to view the online help for GCC, type m; then type gcc, and press Enter. The info system, in turn, displays the top-level menu of items for GCC, as shown in Figure 23-2.
You can explore further by typing m, followed by one of the menu items shown in Figure 23-2.
While you're at it, you may want to type m, then copy; then press Enter in the screen shown in Figure 23-2. That action displays the GNU General Public License (GPL), shown in Figure 23-3.
GPL covers Linux and the gcc compiler. GPL requires distribution of the source code (that's why all Linux distributions come with source code). In the 'Implications of GNU Licenses' section, you learn that you can still use GNU tools to develop commercial applications and to distribute applications in binary form (without source code), as long as they link with selected GNU libraries only.
At any time in info, you can type d to return to the info topic directory shown in Figure 23-1. From that screen, you can view help on other GNU tools, such as make and the GNU debugger.
To quit info, type q. If you access info from the Emacs editor, press Ctrl+X, followed by Ctrl+C, to quit the Emacs editor.
The most important software-development tool in Linux is GCC, which is the GNU C and C++ compiler. In fact, GCC can compile three languages: C, C++, and Objective-C (a language that adds object-oriented extensions to C). You use the same gcc command to compile and link both C and C++ source files. The GCC compiler supports ANSI standard C, making it easy to port any ANSI C program to Linux. In addition, if you've ever used a C compiler on other UNIX systems, you are right at home with GCC.
Use the gcc command to run GCC. By default, when you use the gcc command on a source file, GCC preprocesses, compiles, and links the executable. However, you can use GCC options to stop this process at an intermediate stage. For example, you might invoke gcc by using the -c option to compile a source file and to generate an object file, but not to perform the link step.
Using GCC to compile and link a few C source files is very simple. Suppose you want to compile and link a simple program made up of two source files. The following listing shows the file area.c (the main program that computes the area of a circle whose radius is specified through the command line):
#include <stdio.h> #include <stdlib.h> /* Function prototype */ double area_of_circle(double r); int main(int argc, char **argv) { if(argc < 2) { printf("Usage: %s radius\n", argv[0]); exit(1); } else { double radius = atof(argv[1]); double area = area_of_circle(radius); printf("Area of circle with radius %f = %f\n", radius, area); } return 0; }
The following listing shows the file circle.c, which provides a function that computes the area of a circle.
#include <math.h> #define SQUARE(x) ((x)*(x)) double area_of_circle(double r) { return 4.0 * M_PI * SQUARE(r); }
For such a simple program, of course, I can place everything in a single file, but this contrived example lets me show you how to handle multiple files.
To compile these two programs and to create an executable file named area, you might use this command:
gcc -o area area.c circle.c
This invocation of GCC uses the -o option to specify the name of the executable file. (If you do not specify the name of an output file, GCC creates a file named a.out.)
If there are too many source files to compile and link, compile the files individually, and generate object files (that have the .o extension). That way, when you change a source file, you need to compile only that file and to link all the object files. The following example shows how to separate the compile and link steps for the example program:
gcc -c area.c gcc -c circle.c gcc -o area area.o circle.o
The first two invocations of gcc with the -c option compile the source files. The third invocation links the object files into an executable named area.
In case you are curious, here's how you run the sample program (to compute the area of a circle with a radius of 1):
./area 1 Area of circle with radius 1.000000 = 12.566371
Insider Insight |
Incidentally, you have to add the ./ prefix to the program's name (area) only if the current directory is not in the PATH environment variable. There is no harm in adding the prefix, even if your PATH contains the current directory. |
GNU CC is a combined C and C++ compiler, so the gcc command also can compile C++ source files. GCC uses the file extension to determine whether a file is C or C++. C files have a lowercase .c extension, whereas C++ files end with .C or .cpp.
Although the gcc command can compile a C++ file, that command does not automatically link with various class libraries that C++ programs typically require. That's why it's easier to compile and link a C++ program by using the g++ command, which invokes gcc with appropriate options.
Suppose you want to compile the following simple C++ program stored in a file named hello.C (it's customary to use an uppercase C extension for C++ source files):
#include <iostream> int main() { using namespace std; cout << "Hello from Red Hat Linux!" << endl; }
To compile and link this program into an executable program named hello, use this command:
g++ -o hello hello.C
This command creates the hello executable, which you can run as follows:
./hello Hello from Red Hat Linux!
As you see in the following section, a host of GCC options controls various aspects of compiling C++ programs.
Following is the basic syntax of the gcc command:
gcc options filenames
Each option starts with a hyphen (-) and usually has a long name, such as -funsigned-char or -finline-functions. Many commonly used options are short, however, such as -c, to compile only, and -g, to generate debugging information, (needed to debug the program by using the GNU debugger).
You can view a summary of all GCC options by using info. Type info at the shell prompt, and press m, followed by gcc. Then follow the menu items: Invoking GCC>Option Summary. Usually, you do not have to specify GCC options explicitly; the default settings are fine for most applications. Table 23-1 lists some of the GCC options you might use.
Option |
Meaning |
---|---|
-ansi |
Support ANSI standard C syntax only. (This option disables some GNU C-specific features, such as the asm and typeof keywords.) |
-c |
Compile and generate object file only |
-DMACRO |
Define the macro with the string '1' as its value |
-DMACRO=DEFN |
Define the macro as DEFN where DEFN is some text |
-E |
Run only the C preprocessor |
-fallow-single-precision |
Perform all math operations in single precision |
-fpack-struct |
Pack all structure members without any padding |
-fpcc-struct-return |
Return all struct and union values in memory, rather than in registers. (Returning values this way is less efficient, but is compatible with other compilers.) |
-fPIC |
Generate position-independent code (PIC) suitable for use in a shared library |
-freg-struct-return |
When possible, return struct and union values in registers |
-g |
Generate debugging information. (The GNU debugger can use this information.) |
-IDIRECTORY |
Search the specified directory for files you include by using the #include preprocessor directive |
-LDIRECTORY |
Search the specified directory for libraries |
-lLIBRARY |
Search the specified library when linking |
-mcpu=cputype |
Optimize code for a specific processor (cputype can take many different values-some common ones are i386, i486, i586, i686, pentium2, pentium3, and pentium4). |
-o FILE |
Generate the specified output file (used to designate the name of an executable file) |
-O0 |
Do not optimize |
-O or -O1 |
Optimize the generated code |
-O2 |
Optimize even more |
-O3 |
Perform optimizations beyond those done for -O2 |
-pedantic |
Generate errors if any non-ANSI standard extensions are used |
-pg |
Add extra code to the program so that, when run, it generates information the gprof program can use to display timing details for various parts of the program |
-shared |
Generate a shared object file (typically used to create a shared library) |
-UMACRO |
Undefine the specified macro (MACRO) |
-v |
Display the version number of GCC |
-w |
Don't generate any warning messages |
-Wl,OPTION |
Pass the OPTION string (containing multiple comma-separated options) to the linker. To create a shared library named libXXX.so.1, for example, use the following flag: -Wl,-soname,libXXX.so.1 |
When an application is made up of more than a few source files, compiling and linking the files by manually typing the gcc command is inconvenient. Also, you do not want to compile every file whenever you change something in a single source file. The GNU make utility is helpful in this situation because make can compile only those files that really must be compiled.
The make utility works by reading and interpreting a makefile: a text file you have to prepare according to a specified syntax. The makefile describes which files constitute a program and explains how to compile and link the files to build the program. Whenever you change one or more files, make determines which files should be recompiled and issues the appropriate commands for compiling those files and rebuilding the program.
The make utility is, in fact, specified in Section 6.2 of the POSIX.2 standard (IEEE Standard 1003.2-1992) for shells and tools. GNU make conforms to the POSIX.2 standard.
By default, GNU make looks for a makefile that has one of the following names, in the order shown:
GNUmakefile
makefile
Makefile
In UNIX systems, using Makefile as the name of the makefile is customary because it appears near the beginning of directory listings where the uppercase names appear before the lowercase names.
When you download software from the Internet, you usually find a Makefile, together with the source files. To build the software, you have only to type make at the shell prompt; make takes care of all the steps necessary to build the software.
If your makefile does not have a standard name, such as Makefile, you have to use the -f option to specify the makefile's name. If your makefile is called webprog.mak, for example, you have to run make using the following command line:
make -f webprog.mak
GNU make also accepts several other command-line options, which are summarized in the 'How to Run make' section of this chapter.
For a program that consists of several source and header files, the makefile specifies the following:
The items make will create-usually the object files and the executable. The term target is used for an item to be created.
The files or other actions required to create the target.
Which commands should be executed to create each target.
Suppose you have a C++ source file named form.C that contains the following preprocessor directive:
#include "form.h" // Include header file
The object file form.o clearly depends on the source file form.C and the header file form.h. In addition to these dependencies, you must specify how make should convert the form.C file to the object file form.o. Suppose you want make to run g++ (because the source file is in C++) with these options:
-c (compile only)
-g (generate debugging information)
-O2 (optimize some)
In the makefile, you can express this with the following rule:
# This a comment in the makefile # The following lines indicate how form.o depends # form.C and form.h and how to create form.o. form.o: form.C form.h g++ -c -g -O2 form.C
In this example, the first noncomment line shows form.o as the target and form.C and form.h as the dependent files.
Insider Insight |
The line following the dependency indicates how to build the target from its dependents. This line must start with a Tab; otherwise make will not work. |
In addition to the basic service of building targets from dependents, GNU make includes many nice features that make it easy for you to express the dependencies and rules for building a target from its dependents. If you need to compile a large number of C++ files by using GCC with the same options, for example, typing the options for each file is tedious. You can avoid this task by defining a variable or macro in make as follows:
# Define macros for name of compiler CXX= g++ # Define a macro for the GCC flags CXXFLAGS= -O2 -g -mcpu=i686 # A rule for building an object file form.o: form.C form.h $(CXX) -c $(CXXFLAGS) form.C
In this example, CXX and CXXFLAGS are make variables. GNU make prefers to call them variables, but most UNIX make utilities call them macros.
To use a variable anywhere in the makefile, start with a dollar sign ($) followed by the variable within parentheses. GNU make replaces all occurrences of a variable with its definition; thus, it replaces all occurrences of $(CXXFLAGS) with the string -O2 -g -mcpu=i686.
GNU make has several predefined variables that have special meanings. Table 23-2 lists these variables. In addition to the variables listed in Table 23-2, GNU make considers all environment variables predefined.
Variable |
Meaning |
---|---|
$% |
Member name for targets that are archives. If the target is libDisp.a(image.o), for example, $% is image.o, and $@ is libDisp.a. |
$* |
Name of the target file without the extension |
$+ |
Names of all dependent files with duplicate dependencies, listed in their order of occurrence |
$< |
The name of the first dependent file |
$? |
Names of all dependent files (with spaces between the names) that are newer than the target |
$@ |
Complete name of the target |
$^ |
Names of all dependent files, with spaces between the names. Duplicates are removed from the dependent filenames. |
AR |
Name of the archive-maintaining program (Default value: ar) |
ARFLAGS |
Flags for the archive-maintaining program (Default value: rv) |
AS |
Name of the assembler program that converts the assembly language to object code (Default value: as) |
ASFLAGS |
Flags for the assembler |
CC |
Name of the C compiler. (Default value: cc) |
CFLAGS |
Flags to be passed to the C compiler |
CO |
Name of the program that extracts a file from RCS (Default value: co) |
COFLAGS |
Flags for the RCS co program |
CPP |
Name of the C preprocessor (Default value: $(CC) -E) |
CPPFLAGS |
Flags for the C preprocessor. |
CXX |
Name of the C++ compiler (Default value: g++) |
CXXFLAGS |
Flags to be passed to the C++ compiler |
FC |
Name of the FORTRAN compiler (Default value: f77) |
FFLAGS |
Flags for the FORTRAN compiler |
GET |
Name of the program to extract a file from SCCS (Default value: get) |
GFLAGS |
Flags for the SCCS get program |
LDFLAGS |
Flags for the compiler when it is supposed to invoke the linker ld |
LEX |
Name of the program to convert Lex grammar to C program (Default value: lex) |
LFLAGS |
Flags for Lex |
MAKEINFO |
Name of the program that converts Texinfo source files to info files (Default value: makeinfo) |
RM |
Name of the command to delete a file (Default value: rm -f) |
TEX |
Name of the program to generate TeX DVI files from TeX source files (Default value: tex) |
TEXI2DVI |
Name of the program to generate TeX DVI files from the Texinfo source (Default value: texi2dvi) |
YACC |
Name of the program to convert YACC grammars to C programs (Default value: yacc -r) |
YFLAGS |
Flags for yacc |
GNU make also includes built-in, or implicit, rules that define how to create specific types of targets from various dependencies. An example of an implicit rule is the command that make should execute to generate an object file from a C source file.
GNU make supports two types of implicit rules:
Suffix rules -Suffix rules define implicit rules for make. A suffix rule defines how to convert a file that has one extension to a file that has another extension. Each suffix rule is defined with the target showing a pair of suffixes (file extensions). The suffix rule for converting a .c (C source) file to a .o (object) file, for example, might be written as follows:
.c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
This rule uses the predefined variables CC, CFLAGS and CPPFLAGS. For filenames, the rule uses the variables $@ (the complete name of the target) and $< (the name of the first dependent file).
Pattern rules-These rules are more versatile because you can specify more complex dependency rules by using pattern rules. A pattern rule looks just like a regular rule, except that a single percent sign (%) appears in the target's name. The dependencies also use % to indicate how the dependency names relate to the target's name. The following pattern rule specifies how to convert any file X.c to a file X.o:
%.o: %.c $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
GNU make has a large set of implicit rules, defined as both suffix and pattern rules. To see a list of all known variables and rules, run make by using the following command:
make -p -f/dev/null
The output includes the names of variables, as well as implicit rules.
You can write a makefile easily if you use GNU make's predefined variables and its built-in rules. Consider, for example, a makefile that creates the executable xdraw from three C source files (xdraw.c, xviewobj.c, and shapes.c) and two header files (xdraw.h and
shapes.h). Assume that each source file includes one of the header files. Given these facts, here is what a sample makefile might look like:
######################################################### # Sample makefile # Comments start with '#' # ######################################################### # Use standard variables to define compile and link flags CFLAGS= -g -O2 # Define the target "all" all: xdraw OBJS=xdraw.o xviewobj.o shapes.o xdraw: $(OBJS) # Object files xdraw.o: Makefile xdraw.c xdraw.h xviewobj.o: Makefile xviewobj.c xdraw.h shapes.o: Makefile shapes.c shapes.h
This makefile relies on GNU make's implicit rules. The conversion of .c files to .o files uses the built-in rule. Defining the variable CFLAGS passes the flags to the C compiler.
If you have a directory that contains the appropriate source files and header files, you can try the makefile. Here's what happens when I try the sample makefile:
make cc -g -O2 -c xdraw.c -o xdraw.o cc -g -O2 -c xviewobj.c -o xviewobj.o cc -g -O2 -c shapes.c -o shapes.o cc xdraw.o xviewobj.o shapes.o -o xdraw
As the output of make shows, make uses the cc command (which happens to be a symbolic link to GCC in your Red Hat Linux system) with appropriate options to compile the source files and, finally, to link the objects to create the xdraw executable.
Typically, you run make with a single command in the command line; that is, you run make by typing make. When run this way, GNU make looks for a file named GNUmakefile, makefile, or Makefile-in that order. If make finds one of these makefiles, it builds the first target specified in that makefile. However, if make does not find an appropriate makefile, it displays the following error message and exits:
make: *** No targets. Stop.
If your makefile happens to have a different name from the default names, you have to use the -f option to specify the makefile. The syntax of this make option is the following:
make -f filename
where filename is the name of the makefile.
Even when you have a makefile with a default name such as Makefile, you may want to build a specific target out of several targets defined in the makefile. In that case, you have to run make by using this syntax:
make target
If the makefile contains the target named clean, you can build that target with this command:
make clean
Another special syntax overrides the value of a make variable. For example, GNU make uses the CFLAGS variable to hold the flags used when compiling C files. You can override the value of this variable when you invoke make. Here is an example of how you can define CFLAGS to be the option -g -O2:
make CFLAGS="-g -O2"
In addition to these options, GNU make accepts several other command-line options. Table 23-3 lists the GNU make options.
Option |
Meaning |
---|---|
-b |
Ignore but accept for compatibility with other versions of make |
-C DIR |
Change to the specified directory before reading the makefile |
-d |
Print debugging information |
-e |
Allow environment variables to override definitions of similarly named variables in the makefile |
-f FILE |
Read FILE as the makefile |
-h |
Display the list of make options |
-i |
Ignore all errors in commands executed when building a target |
-I DIR |
Search specified directory for included makefiles (the capability to include a file in a makefile is unique to GNU make) |
-j NUM |
Specify the number of commands that make can run simultaneously |
-k |
Continue to build unrelated targets, even if an error occurs when building one of the targets |
-l LOAD |
Don't start a new job if load average is at least LOAD (a floating-point number) |
-m |
Ignore but accept for compatibility with other versions of make |
-n |
Print the commands to be executed, but do not execute them |
-o FILE |
Do not rebuild the file named FILE, even if it is older than its dependents |
-p |
Display the make database of variables and implicit rules |
-q |
Do not run anything, but return zero if all targets are up to date; return 1 if anything needs updating and 2 if an error occurs |
-r |
Get rid of all built-in rules |
-R |
Get rid of all built-in variables and rules |
-s |
Work silently (without displaying the commands as they are executed) |
-t |
Change the timestamp of the files |
-v |
Display the version number of make and a copyright notice |
-w |
Display the name of the working directory before and after processing the makefile |
-W FILE |
Assume that the specified file has been modified (used with -n to see what happens if you modify that file) |