The gcc Compiler


gcc is the “GNU Compiler Collection.” gcc started out as a C compiler but now supports languages such as C++, Java, Fortran, and Ada as well. gcc runs C and C++ source code through a preprocessor, syntactic analyzer, compiler, optimizer, assembler, and linker to generate an executable that you can run on your machine.

Compiling C Programs Using gcc

We’ll start off with an example of how to use gcc to compile a simple C program. Using your favorite text editor, create a file called hello.c with the following contents:

 #include <stdio.h> int main() {   printf ("Hello, world.\n");   return 0; }

You can then create an executable program with the gcc command by typing

 $ gcc hello.c

This will compile hello.c as a C file and will link in the standard C libraries to create an executable called a.out. You can run the program by typing

 $ ./a.out Hello, world.

The name a.out (for assembler output) is a historical convention. You can specify a name with the -o option. The command

 $ gcc -o hello hello.c

will create an executable program called hello.

Most programs have code spread over many source files. gcc can compile multiple files at once. The command

 $ gcc -o hello hello.c file2.c file3.c

will compile the three source files (hello.c, file2.c, and file3.c) and produce an executable called hello.

You can call gcc with the -c argument to compile source files into object files. An object file is an intermediate file format that stores a compiled form of your source. gcc’s linker can then combine these object files together with source files to form your executable. Using object files allows you to compile your program in stages, via multiple calls to gcc. These stages allow you to recompile only those files that you have changed. In large projects, not having to recompiling everything can save you a great deal of time. However, if you modify a source file and forget to update the corresponding object file, the code changes will not take effect. make, which is described later in this chapter, can help you with this problem.

The command

 $ gcc -c file2.c file3.c

will generate two binary files called file2.o and file3.o. You can now generate the same hello executable using these object files instead of the source files. The gcc command

 $ gcc -o hello hello.c file2.o file3.o

will compile hello.c, link it along with the object files file2.o and file3.o, and generate an executable called hello.

Compiling C++ Programs Using gcc and g++

gcc will compile files with the extensions .C, .cc, .cpp, .c++, or .cxx as C++ files. However, if you create a file called hello.cpp with the contents

 #include <iostream> int main() {   std::cout << "Hello, world.\n";   return 0; }

and run the command

 $ gcc -o helloc++ hello.cpp

then you will get a series of link errors. This is because gcc doesn’t link against the standard C++ library by default. You can tell gcc that you would like to link against the C++ library by including the argument -lstdc++. You will be able to successfully build the program using the command

 $ gcc -o helloc++ -lstdc++ hello.cpp

Running helloc++ will give you the expected output:

 $ ./helloc++ Hello, world.

Though this will work for most C++ programs, the GCC installation also has a C++-specific compiler called g++. You could also generate helloc++ with the command

 $ g++ -o helloc++ hello.cpp

While you can use either gcc or g++ to compile C++ programs, g++ is recommended because it sets the default environment to C++ and automatically links against the standard C++ library.

Useful gcc Options

gcc and g++ support over a thousand command-line options. You can customize your settings for the programming language, warnings, debug information, code generation and optimization, preprocessor, assembler, linker, directories, target binary, and target machine. There is a list of the options in the GNU online documentation at http://gcc.gnu.org/onlinedocs/gcc/Option-Index.html, and in the gcc man page. You can also get an abbreviated list with the command

 $ gcc --help

Table 24–1 lists some of the most useful command line options. The -Wall command line option is strongly recommended. By default, gcc will suppress compiler warnings.

Table 24–1: gcc Command Line Options

Option

Description

-c

Compile/assemble source files, but do not link. This generates object files

-D

#define a macro with a default value of 1.

-E

Stop after preprocessing, do not compile. The output goes to standard output.

-g

Generate debug information.

-l

Include a directory to the header file search path.

-l

Include a library when linking.

-L

Add a directory to the library search path.

-o

Specify output file-name, regardless of the type of output.

0

Generate optimized code. There are several levels, from the default 00 to 03.

-S

Stop after compiling but do not assemble. This generates assembly files.

-v

Shows verbose information on standard error.

-Wall

Generate all compile warnings.

Creating and Including Libraries

All UNIX platforms support statically linked libraries, and most support dynamically linked libraries. When you generate a program, the linker copies the code out of static libraries and puts them into your program’s binary The contents of dynamically linked libraries, on the other hand, are loaded when your binary is run.

Statically Linked Libraries

Statically linked libraries are also called archives (.a). Most of the libraries that you generate for your programs will be static libraries. The ar command allows you to group multiple object files (.o) into an archive. For example, you can generate an archive called libRoutine.a that contains two object files called routine1.o and routine2.o with the command

 $ ar crs libRoutine.a routine1.o routine2.o

The c parameter tells ar to create the archive if it doesn’t exist, the r parameter tells ar to replace existing members, and the s parameter tells ar to regenerate the symbol table. (On some systems you may have to use ranlib to generate the symbols.)

Once you create an archive, you can link the library on the gcc or g++ command line in the same way that you would include a object file (.o). For example, you could use the command

 $ g++ -Wall -o BinaryName main.o libRoutine.a

More often, however, you will include libraries from other directories using the -L and -l command-line options. In order for -l to work, the library name must start with the prefix lib. If you had libRoutine.a in a subdirectory called routineDir, you could replace the preceding example with

 $ g++ -Wall -o BinaryName main.o -LroutineDir -IRoutine

Dynamically Linked Libraries

Dynamically linked libraries are also called shared objects (.so). gcc will by default build your application using dynamically linked libraries for the standard C/C++ libraries, since they can be shared by many processes. This is recommended because it saves considerable disk space and memory However, you can override the use of shared libraries in gcc with the -static command-line argument. You can view an executable’s shared library dependencies using the Idd command followed by the executable name.

In order to generate a dynamically linked library, you must first compile your object files (.o) with the -fPIC flag. This tells the compiler to generate position-independent code for dynamic linking. You can then generate the shared objects (.so) with the -shared option. For example,

 $ gcc -shared -fPIC -Wall -o libRoutine.so routine1.o routine2.o

will generate a shared library called libRoutine.so. You then generate an executable in the same manner as you would for a static library by using the (.so) shared object on the command line, or using the -l and -L compile options.

When you run the executable, you will likely see

 $ ./BinaryName ./BinaryName: error while loading shared libraries: libRoutine.so: cannot open shared object file: No such file or directory

This is because the system doesn’t know where to find the shared library. You have to add the directory that contains your shared object to the LD_LIBRARY_PATH environment variable. To add /path/to/so, you would run the following command in csh or tcsh:

 % setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/path/to/so

If you are running ksh or bash, then the commands would be

 $ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/path/to/so

Inside gcc

As we mentioned earlier, the gcc command runs the source code through a preprocessor, syntactic analyzer, compiler, optimizer, assembler, and linker to generate your program. This section describes each of these steps in a little more detail.

Preprocessor

The preprocessor strips out comments, reads in files specified in #include directives, and substitutes and evaluates #define and -D macros. cpp is a stand-alone preprocessor command that you can run on your source files. It should give you the same output as running gcc with the -E argument. While gcc and cpp share the same preprocessor source code, currently gcc doesn’t directly invoke cpp.

Syntactic Analyzer

The syntactic analyzer parses and evaluates the source code. Early UNIX C compilers weren’t nearly as robust as gcc is today They missed function type mismatches and didn’t provide warnings. In order to check their source code, developers often had to run a separate command called lint before compiling. Because gcc provides much of the same functionality, lint is now largely obsolete.

By default, the compiler mainly displays errors. To turn on compiler warnings, use the -Wall command-line option. Alternatively, specific warnings can be enabled individually gcc has support for some warnings that are not included in -Wall. These warnings are excluded because they may flag valid code.

Compiler

gcc next compiles the syntactic analyzer’s output into assembly language. You can make gcc generate assembly language files and exit with the -S option. Assembly language files have the .s suffix. This is not likely to be useful unless you need to port your code to a hardware device that isn’t supported by gcc.

Optimizer

gcc supports four levels of optimization. By default, it runs with no optimization, which is equivalent to -O0. When given the -O or -O1 option, gcc invokes an optimizer that makes the resulting executable run faster and more efficiently -O2 and -O3 provide higher levels of optimization. -Os will optimize for size. There are also individual command-line arguments that allow you to pick and choose your optimizations. Turning on optimization may make debugging more difficult.

Assembler

The next step is for gcc to convert the assembly language into machine language by calling as, the assembler. The result of the as step is an object file whose filename is based on the original source file, but with the .o suffix. For example, the source file hello.c results in an object file hello.o. The -c argument can be used to make gcc stop after this step.

Linker

gcc completes the final step by using the linker, Id. The linker, which can also be invoked separately, creates a single executable that combines the code from all the object files (.o) and libraries (.a). It edits the object code, replacing external function references with their actual addresses in the executable program. If you find that you’re having trouble tracking down link errors, you can view the symbols in an object file or library by using the nm command.




UNIX. The Complete Reference
UNIX: The Complete Reference, Second Edition (Complete Reference Series)
ISBN: 0072263369
EAN: 2147483647
Year: 2006
Pages: 316

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net