The C Compiler:
In UNIX and Linux operating systems, the compiler that is used to compile a C file is known as “gcc”. Here “gcc” stands for GNU C Compiler.
Compiling program with gcc: ~
You can use your favorite editor to write a C program. Suppose you have write down a simple program and save it as test1.c.Here is the code
#include
void main(void)
{
printf(“hello world”);
}
To compile the program, we type:
$ gcc test1.c
When “gcc” runs with the above usage, it generates a file named “a.out” that contains your program. You can run the program as follow:
$ ./a.out
hello world
In this way we can carry out the compilation and execution of a C program.
The C compiler “gcc” options:
The GNU C compiler provides us lots of options that help you to manage your project. Some of the options are given below:
The “–o” option:
The C compiler generate the same file “a.out” for each and every file of C. To overcome this problem we use the “–o” option of “gcc”, which enables you to change the names of your program after compilation. To use this option, type the following command:
$ gcc –o test1 test1.c
Now you would get file named as “test1.c” instead of “a.out”. Hence, run the program like this:
$ ./test1.c
hello world
The warning options “–w”, “–Wall” & “-Werror”:
When we write down the C programs, some times warnings are generated when we compile the program and we manage them. The “gcc” provide some options to handle these warnings in UNIX and Linux.
Warnings are controlled by the “–w” and “–Wall” options. –Wall option enables all of the most common warnings. Suppose we write down a simple program:
#include
int main ( )
{
printf(“Hello world”);
}
Now compile the program using the –o and –Wall option:
$ gcc –Wall –o test1 test1.c
test1.c: warning: control reaches end of non void functions
Such warning is not generated if you are not using the “–Wall” option of “gcc”. But such option treats warning as a warning not an error. The “gcc” continuously compiled your program. It only abort compilation on errors.
To stop the compilation when a warning is detected, the “gcc” provide a useful option “–Werror”. It force the “gcc” to treat all warnings as errors and stop compilation if any warning is generated. Such option can be used as:
$ gcc –Wall –Werror –o test1 test1.c
Such option is particularly useful when using automated compilation. When “–Werror” is used, “gcc” will not finish the compilation if any warning is detected.
Optimization with gcc:
One of the most important feature of modern C compiler is optimizer. The optimizer is a part of the compiler that is capable of examining your code, identifying those areas that are suboptimal and rewriting them using code that does the same thing in less space or with better performance. Similarly “gcc” has a powerful and highly configurable optimizer that can be applied to your programs.
Optimization options “-01 or -0”, “-02” and “-03”:
“gcc” enable optimizations by using one of the -0 options. You can specify several different levels of optimization for “gcc”. If you simply use -0, this is taken as level one (or -01); -0 is same as -01. In general, you can go up to level three (or -03). Thus the command containing the optimization option is given below:
$ gcc –Wall -01 –o test1 test1.c
We can also use the -02 and -03 options in the above command. These option tells that how aggressive the gcc’s optimizer is. Higher the level of optimization means higher aggressive the gcc’s optimizer is. More aggressive optimization mean that your code runs faster.
Optimization pitfalls:
As we know that optimization give tremendous gain for our programs, but there are some pitfalls or limitations of optimization levels.
First one is, the more aggressive gcc becomes with optimizations, the longer it takes your program to compile. Therefore, some programmer compile program without optimization.
Second one, some option – especially option -03 – can increase the size of the generated program, which can hurt performance more than the gain from the more efficient code.
Finally, the debugging can be difficult when optimization is enabled. Because the optimizer can eliminate code that does not have a use in the final program, or rearrange some statements for better performance. Therefore, some programmer avoid optimization as much as possible when debugging is carried out in the program.
Many people prefer to compile their program with -02. This option often provides the best compromise between optimization strength, compile time and code size.
Debugging options:
“gcc” provide some debugging options that we can use during compilation of the C program. When we compile the C program using the debugging options, “gcc” inserts extra information into the object files (.o) and executable files that it generates. This extra information enables “gdb (GNU Debugger)” to determine the relationship between the compiled code and the lines in your source file. Without that information, gdb would not be able to determine which line of code your program is executing at any given time.
NOTE: These debug symbols or options are not compiled into your programs by default because of one important side effect; they increase the size of the executable.
To generate the debugging symbol, we use the “–g” option of “gcc”. It can be used in command as:
$ gcc –g –Wall –o test1 test1.c
You can also use the more higher option of debugger options. Like:
$ gcc –ggdb3 –Wall –o test1 test1.c
Such command instruct “gcc” to generate the debugging symbols with the “gdb” extensions. The 3 means that it ought to use level – 3 debugging information, the highest level possible.
Advanced gcc options: ~
Till now we are dealing with the options that control basic file generation, “gcc” provides us many other options that enable you to fine tune “gcc” operations. For instances, “gcc” provide us some option by which we can give path to include the files and libraries in our program, speeding up the compilation processes by pipelining, carried out the linking with the libraries, and viewing the hidden files that perform an important role in our project but they are abstract from the user. Let us discuss each of them.
(i) Specifying search path: ~
When building a project, “gcc” has a default search path to use for things like include files and libraries. But sometimes we need to specify the path of the file and library which is not mentioned in the default search path of the “gcc”. For instance:
Suppose you want to adding the search path for files and library in your “gcc’s” command, for this “gcc” provide the option –I, -L (Uppercase I and L). –I option is used to add the search path for the files and –L is used to add the search path for the library.
For example, you have a program “Punit.c” and you wants to include a file named scsi.h, and such file is stored in your system at /usr/include/scsi, which is not default search path of “gcc”. Therefore you might have:
$ gcc –wall –I/usr/include/scsi –o Punit Punit.c
This option (-I) and specified path would help the preprocessor to find the scsi.h file. The same concept will be included for libraries. If your program needs to link to the X11 library, then you may tell this to linker like this:
$ gcc –L/usr/X11r6/lib –wall –o Punit Punit.c –lX11
Note : Here we mention the path of the library using –L option and linking the library using –l option.
(ii) Linking with libraries: ~
When writing many programs, we will need to link with the libraries. These libraries can be anything from that implement mathematical function to ones that provide support for using a graphical interface in the X Window System. They can be either static or shared (dynamic); “gcc” can work with both.
The basic options to link in a library with your current program is -l ( a lowercase L). This option should be specified at the final link stage of your compile process, which brings together all the .o (object) files.
For instance, if you want to include the math library (math.h) in our program. Then, when compiling, you would need to link in the math library, names simply m. Therefore, a command such as the following would be appropriate:
$ gcc –Wall –o Punit Punit.c –lm
(iii) Speeding compilation with pipes: ~
When we build a program, the build process consist many steps- preprocessing, compilation, assembling and linking to the name a few. Normally, gcc handles many aspects of these tasks.
But by default, such performance of “gcc” is too slow before there are many temporary files included. For instance, “gcc” will create a temporary file holding the output of the preprocessor, another one with the output of compiler, and perhaps the output of the assembler. Hence reading and writing takes time.
The other way of communication that can be more efficient is - pipelining. With pipelines, several programs can be invoked at once, with the output from one being input of the other. For speeding up the process of compilation through pipelining, the “gcc” provide us a option called “–pipe”. Such option can be used in “gcc” command as:
$ gcc –pipe –wall -03 –o Punit Punit.c
(iv) Viewing the hidden file option “–v”:
All the interaction between the various build programs are normally hidden from view. Because there details are generally unimportant for the users. However, you can request the “gcc” to give the details of all these interaction between the various build process by using the –v option.
$ gcc –v –Wall -03 –o test2 test2.c
When you run this command, “gcc” displays a lot of details about its build process. “gcc” specifying the its version number and where it retrieved some build information.
NOTE: The UNIX and Linux OS provide the g++ compiler for the C++ programs. g++ is a GNU C++ compiler, perform the same function for C++ programs as gcc does for C programs