Tutorial Example
Before beginning an in-depth look at GCC, a short example will help you start using GCC productively right away. For the purposes of this tutorial, we will use the program in Listing 3.1.
Listing 3.1 Program to Demonstrate GCC Usage
/* * hello.c Canonical "Hello, world!" program */ #include <stdio.h> int main(void) { printf("Hello, Linux programming world!\n"); return 0;}
To compile and run this program, type
$ gcc hello.c -o hello $ ./hello Hello, Linux programming world!
The first command tells GCC to compile and link the source file hello.c, and create an executable name hello, specified using the -o argument. The second command executes the program, resulting in the output shown on the third line.
The whole process is straightforward, but a lot took place under the hood that you did not see. GCC first ran hello.c through the preprocessor, cpp, to expand any macros and insert the contents of #included files. Next, it compiled the preprocessed source code to object code. Finally, the linker, ld, created the hello binary. Figure 3.1 depicts the compilation process graphically.
You can re-create these steps manually, stepping through the compilation process. The first step is to run the preprocessor. To tell GCC to stop compilation after preprocessing, use GCC's -E option:
$ gcc -E hello.c -o hello.cpp
Examine hello.cpp and you will see that the contents of stdio.h have indeed been inserted into the file, along with other preprocessing tokens. Figure 3.2 shows some of the contents of hello.cpp, starting at line 894.
Note - The exact location of this text may vary slightly on your system.
The next step is to compile hello.cpp to object code. Use GCC's -c option to accomplish this:
$ gcc -x cpp-output -c hello.cpp -o hello.o
In this case, you do not need to specify the name of the output file because the compiler creates an object filename by replacing .c with .o. The -x option tells GCC to begin compilation at the indicated step, in this case, with cpp-output, the preprocessed source code.
How does GCC know how to deal with a particular kind of file? It relies upon file extensions to determine how to process a file correctly. The most common extensions and their interpretation are listed in Table 3.1.
Table 3.1 How GCC Interprets Filename Extensions
Extension |
Type |
.c |
C language source code |
.C, .cc |
C++ language source code |
.i |
Preprocessed C source code |
.ii |
Preprocessed C++ source code |
.S, .s |
Assembly language source code |
.o |
Compiled object code |
.a, .so |
Compiled library code |
Linking the object file, finally, creates a binary:
$ gcc hello.o -o hello
Hopefully, you will see that it is far simpler to use the abbreviated syntax I used above, gcc hello.c -o hello. The point of the step-by-step example was to demonstrate how to stop and start compilation at any step, should the need arise. One situation in which you would not want to complete the compilation process is when you are creating libraries. In this case, you only want to create object files, so the final link step is unnecessary. Another circumstance in which you would want to walk through the compilation process is when an #included file introduces conflicts with your own code or another #included file. Stepping through the process allows you to identify where the problem occurs and then to fix it. Being able to step through the process will make it clearer which file is introducing the conflict.
Most C programs consist of multiple source code files, so each source file must be compiled to object code before the final link step. This requirement is easily met. Suppose, for example, that hello.c uses code from helper.c (see Listings 3.2 and 3.3). Listing 3.4 shows the source code for the modified hello program, howdy.c.
Listing 3.2 Helper Code for howdy.c
/* * helper.c Helper code for howdy.c */ #include <stdio.h> void msg(void) { printf("This message sent from Jupiter.\n");}
Listing 3.3 Header File for helper.c
/* * helper.h Header for helper.c */void msg(void)
Listing 3.4 The Modified hello Program
/* * howdy.c Modifed "Hello, World!" program */ #include <stdio.h> #include "helper.h" int main(void) { printf("Hello, Linux programming world!\n"); msg(); return 0;}
To compile howdy.c properly, use the following command line:
$ gcc howdy.c helper.c -o howdy
GCC goes through the same preprocess-compile-link steps as before. This time it creates object files for each source file, howdy.c and helper.c, before creating the binary, howdy, in the link stage. Typing long commands like this does become tedious. In Chapter 4, "Project Management Using GNU make," you learn how to solve this problem. The next section will begin introducing you to the multitude of GCC's command-line options.