The compilation process of gcc compiler under Linux

1. What is GCC

GCC is free software released under the GPL license and is also a key part of the GNU project. The original intention of GCC was to write a compiler for the GNU operating system, and it has been adopted as a standard compiler by most Unix-like operating systems (such as Linux, BSD, MacOS X, etc.), and it can even be used on Microsoft Windows GCC. GCC supports a variety of computer architecture chips, such as x86, ARM, MIPS, etc., and has been ported to a variety of other hardware platforms. Here we first mainly explain the use of C language gcc under Linux.

1. How to use gcc

gcc [选项] 文件名
在linux下我们可以使用 gcc --help 查看gcc的各个选项

2. Common options of gcc

Insert picture description here

The compilation process of gcc

The process of gcc compilation can be broken down into 4 major steps:

Preprocessing (Preprocessing)
Compilation (Compilation)
Assembly (Assembly)
Linking (Linking)

Insert picture description here

Let's talk about the specific steps of gcc compilation

1. Pretreatment

Preprocessing is to read the c source program and "replace" the pseudo-instructions and special symbols in it; after this processing, an output file without macro definitions, no conditional compilation instructions, and no special symbols is generated. The meaning of this file is the same as the source file that has not been preprocessed. It is still a C file, but the content is different. The pseudo-instructions mainly include the following three aspects:
(1) Macro definition instructions, such as #define NAME TokenString, #undef and some built-in macros in the compiler, such as __DATE__, FILE, LINE, TIME, __FUNCTION__, etc.
(2) Conditional compilation instructions, such as #ifdef, #ifndef, #else, #elif, #endif, etc.
(3) The header file contains instructions, such as #include "FileName" or #include, etc.

The pretreatment process mainly includes the following processes:

  • Delete all #defines and expand all macro definitions
  • Process all conditional precompilation instructions, such as #if, #ifdef, #elif, #else, #endif, etc.
  • Process the #include precompiled directive and insert the included file into the position of the precompiled directive.
  • Delete all comments "//" and "/* */"
  • Add line numbers and file identifiers so that debugging line numbers and compilation error warning line numbers can be generated during compilation.
  • Keep all #pragma compiler directives, because the compiler needs to use them

The following command is usually used for preprocessing, and the parameter -E means only preprocessing:
gcc -E hello.c -o hello.i
You can also use the following command to complete the preprocessing process, where cpp is the preprocessor:
cpp hello. c> hello.i

The preprocessed result hello.i is still c language source code, we can use cat or vim command to view its code
vim hello.i

2. Compile

The work that the compiler needs to do is to pass lexical analysis and grammatical analysis, after confirming that all instructions comply with the grammatical rules, translate them into equivalent intermediate code representations or assembly codes . If you want to know more about the compilation process, you can refer to other blogs.

We can use the following command to compile and generate an assembly file:
gcc -S hello.i> hello.s
We can use the cat command to view its code:
cat hello.s

3. Compilation

The assembly process actually translates assembly language code into target machine instructions . For each c language source program processed by the translation system, the corresponding target file will be finally obtained through a process.

We can use the following command to assemble:
gcc -c hello.s -o hello.o

4. Link

The object file generated by the assembler cannot be executed immediately , and there may be many unsolved problems. For example, a function in a source file may reference a symbol defined in another source file (such as a variable or function call, etc.); a function in a library file may be called in a program, etc., all These problems need to be linked to be solved. The main job of the linker is to connect the relevant object files with each other, that is, to link the symbols referenced in one file with the definition of the symbol in another file, so that all These object files become a unified whole that can be loaded and executed by the operating system, that is, executable programs. According to the different linking methods of the library functions specified by the developer, the linking process can be divided into two types: ①Static link ②Dynamic link .

For the function call in the executable file, the methods of dynamic linking or static linking can be adopted respectively. Using dynamic linking can make the final executable file shorter and save some memory when the shared object is used by multiple processes, because only one copy of the shared object's code needs to be stored in the memory . However, it is not necessarily that the use of dynamic linking is better than the use of static linking. In some cases, dynamic linking may bring some performance damage .

Guess you like

Origin blog.csdn.net/KingRing_/article/details/115051281