Compilation in C
Juan Duque
Ethical Hacker | ?Malware Dev | ?Cybersecurity Analyst | ?RTDC | ?BCSP | ?RTDO | ?Auditor interno ISO 27001:2022 | ? C Dev |
Here we will go into more detail about how the complete compilation process works, from the moment we write a file in code which we can understand, until the moment this code is compiled and an executable binary is obtained that it will be understandable for our computer in C language.
All the commands that I will show will be executed in a GNU / Linux environment of one of the most stable distributions which is Debian 10, do not worry about the process since it is the same for any type of Operating System and compiler.
What is compilation in C?
This is a process in which the compiler is in charge of converting one or more files in source code to a binary code that is executable for our computer or specific hardware / software architecture.
This is a process that involves several stages, but before all this we must understand what source code and executable binary code are about or what it means.
source code: This is the code or program that we as programmers write, the plain text that tells the computer how to do things.
Executable binary code: This in general for any compiled language and in particular to our C language, is binary code (It is not a text) which in turn can be executed on the computer.
However, to reach the complete compilation process, we must go through some intermediate steps to become an executable binary file. As we see in the following flow charts.
Compilation Process C
Now that we understand how the compilation process works, we are going to see exactly what phases it consists of translating our source code to until we get our program that is understood by the machine language.
Source Program: This is the Program that we write at a high level where we enter the sentences of our program which must be translated into machine language.
Compiler: This is the program that is in charge of translating our source files or programs into machine language and together with it, checking that all the calls to the library functions are carried out.
Program or Object Code: this is the source program translated by the compiler into machine code, which is not yet directly executable.
Executable Program: This is the complete translation into machine code, which is carried out by the linker, of the source program and this is already directly executable.
Link (Assembler or linker): this is in charge of inserting into the object program the machine code of the functions of the libraries (library files) that are used by the program and carrying out the assembly process, which will produce our executable program.
If our source program is syntactically correct, it will generate an object code, otherwise it will show us a list with the errors found within our code and our object program will not be generated so that we can proceed with the correct debugging.
Compilers issue error or warning messages during the compile, bind, or run phases of a program:
Compilation time errors: These occur before the execution of the program, that is, during the compilation process.
Execution-time errors: These, on the contrary, occur during the execution of the program and are the most difficult to find, since they are not detected by the compiler and are logic errors, not syntax errors.
The GCC Compiler GCC is a built-in compiler from the GNU project for C, C ++, Objective C, and Fortran; it is capable of receiving a source program in any of these languages and generating a binary executable program in the language of the machine where it has to run.
The acronym GCC stands for "GNU Compiler Collection". Originally it stood for "GNU C Compiler"; GCC is still used to designate a C build. G ++ refers to a C ++ build.
Syntax.
gcc [option | file] ...
g ++ [option | file] ...
Options are preceded by a hyphen, as is common in UNIX, but the options themselves can be multiple letters; multiple options cannot be grouped after the same script. Some options then require a file or directory name, others do not. Finally, several file names can be given to include in the compilation process.
Gcc examples gcc main.c: compile the C program hello.c, generate an executable file a.out.
gcc -o main main.c: compile the C program hello.c, generate an executable hello.
gcc -E main.c -o main: This generates a preprocessed file and does not compile or link the file.
gcc -S main.c: Nothing else compiles our file but does not assemble or link it.
gcc -c main.c: does not generate the executable, but the object code, in the hello.o file. If no name is given for the object file, use the filename in C and change the extension to .o.
gcc -c -o object.o main.c: generates the object code indicating the file name.
Options. - c: performs preprocessing and compilation, obtaining the file in object code; does not perform binding.
- E: performs preprocessing only, sending the result to standard output.
-o file: indicates the name of the output file, whatever the stages are completed.
-Routes: pecifies the path to the directory where the files marked for inclusion in the source program are located. There is no space between the I and the path, like this: -I / usr / include
-L: specifies the path to the directory where the library files with the object code of the referenced functions in the source program are located. There is no space between the L and the path, like this: -L / usr / lib
-Wall: displays all compiler error and warning messages, even some questionable but ultimately easy to avoid by writing your code carefully.
-g: It includes in the generated executable the necessary information to be able to trace the errors using a debugger, such as GDB (GNU Debugger).
-v: shows the commands executed at each compilation stage and the compiler version. It is a very detailed report.
Resume. To produce a single-file source executable: $ gcc -o circle circle.c
To create an object module, with the same source name and .o extension: $ gcc -c circle.c
To link an object modules: $ gcc -o circle circle.o
To link the object modules green.o, blue.o, red.o, already compiled separately, in the executable file colors $ gcc -o colors green.o blue.o red.o