Running Linux, 5th Edition - Matthias Kalle Dalheimer [382]
To compile and link the program to the executable hello, the programmer would use the command:
papaya$ gcc -o hello hello.c
and (barring any errors), in one fell swoop, gcc compiles the source into an object file, links against the appropriate libraries, and spits out the executable hello, ready to run. In fact, the wary programmer might want to test it:
papaya$ ./hello
Hello, World!
papaya$
As friendly as can be expected.
Obviously, quite a few things took place behind the scenes when executing this single gcc command. First of all, gcc had to compile your source file, hello.c, into an object file, hello.o. Next, it had to link hello.o against the standard libraries and produce an executable.
By default, gcc assumes that you want not only to compile the source files you specify, but also to have them linked together (with each other and with the standard libraries) to produce an executable. First, gcc compiles any source files into object files. Next, it automatically invokes the linker to glue all the object files and libraries into an executable. (That's right, the linker is a separate program, called ld, not part of gcc itself—although it can be said that gcc and ld are close friends.) gcc also knows about the standard libraries used by most programs and tells ld to link against them. You can, of course, override these defaults in various ways.
You can pass multiple filenames in one gcc command, but on large projects you'll find it more natural to compile a few files at a time and keep the .o object files around. If you want only to compile a source file into an object file and forego the linking process, use the -c switch with gcc , as in the following example:
papaya$ gcc -c hello.c
This produces the object file hello.o and nothing else.
By default, the linker produces an executable named, of all things, a.out. This is just a bit of left-over gunk from early implementations of Unix, and nothing to write home about. By using the -o switch with gcc, you can force the resulting executable to be named something different, in this case, hello.
Using Multiple Source Files
The next step on your path to gcc enlightenment is to understand how to compile programs using multiple source files . Let's say you have a program consisting of two source files, foo.c and bar.c. Naturally, you would use one or more header files (such as foo.h) containing function declarations shared between the two programs. In this way, code in foo.c knows about functions in bar.c, and vice versa.
To compile these two source files and link them together (along with the libraries, of course) to produce the executable baz, you'd use the command:
papaya$ gcc -o baz foo.c bar.c
This is roughly equivalent to the following three commands:
papaya$ gcc -c foo.c
papaya$ gcc -c bar.c
papaya$gcc -o baz foo.o bar.o
gcc acts as a nice frontend to the linker and other "hidden" utilities invoked during compilation.
Of course, compiling a program using multiple source files in one command can be time-consuming. If you had, say, five or more source files in your program, the gcc command in the previous example would recompile each source file in turn before linking the executable. This can be a large waste of time, especially if you only made modifications to a single source file since the last compilation. There would be no reason to recompile the other source files, as their up-to-date object files are still intact.
The answer to this problem is to use a project manager such as make. We talk about make later in the chapter, in "Makefiles."
Optimizing
Telling gcc to optimize your code as it compiles is a simple matter; just use the -O switch on the gcc command line:
papaya$ gcc -O -o fishsticks fishsticks.c
As we mentioned not long ago, gcc supports different levels of optimization. Using -O2 instead of -O will turn on several "expensive" optimizations that may cause compilation