Introduction to gcc compilation

1. Compilation steps

Compilation steps: preprocessing, compiling, assembling, linking
1. Precompiling: gcc -E hello.c -o hello.i
2. Compiling: gcc -S hello.i -o hello.s
3. Assembling: gcc -c hello .s -o hello.o
4. Link: gcc hello.o -o hello
-o is the file name of the specified generated file

1.1 Preprocessing

The first preprocessing is to expand all macro definitions in the code, expand the header files used in the code, replace all conditional compilation in the code, and delete all comments, blank lines, and blanks in the code.

1.2 compile

Compilation is to check the grammatical specification in the code. This stage consumes the longest time and consumes the most system resources.

1.3 Assembly

Translate the assembly file generated by the above compilation into machine instructions

1.4 Links

Data segment merge address backfill, generate executable file

2. Common compilation parameters

-I specifies the location of the directory where the header file is located, for example: create a hello.c and a hello.h, create an inc folder, and put hello.h in the inc folder, this time to compile hello.c You need to specify the location of the header file. If you don't specify it, the following error will occur:

vtlk:cc$gcc demo.c -o hello
demo.c:2:10: fatal error: demo.h: 没有那个文件或目录
 #include <demo.h>
          ^~~~~~~~
compilation terminated.

Use the command:

gcc -I ./inc demo.c -o hello

-c only compiles, does not link into executable files. The compiler only generates object files suffixed with .o from input source code files such as .c, and is usually used to compile subroutine files that do not contain the main program

-O compiles and links the program with optimization. With this option, the entire source code will be optimized during compilation and linking, so that the execution efficiency of the executable file generated in this way can be improved, but the speed of compilation and linking will be correspondingly slower, and the debugging of the executable file will be slower. It has a certain impact, causing some "confusing" situations such as the inconsistency between the execution effect and the corresponding source file code. Therefore, this option is generally used when compiling the output software distribution.
-O2 optimizes compilation and linking better than -O. Of course, the entire compilation and linking process will be slower

-pedantic option, when gcc compiles source code that does not conform to the ANSI/ISO C language standard, it will generate a corresponding warning message

-Wall option, in addition to -pedantic, gcc has some other compilation options that can also generate useful warning messages. Most of these options start with -W. The most valuable one is -Wall, which can make gcc generate as many warning messages as possible.

-Werror option, which requires gcc to treat all warnings as errors, which is very useful when using automatic compilation tools (such as Make, etc.). If you compile with the -Werror option, gcc will stop compiling at all places where warnings are generated, forcing programmers to modify their own code. Only when the corresponding warning message is eliminated is it possible to continue the compilation process forward.

-g and -ggdb By default, gcc will not insert debugging symbols into the generated binary code when compiling, because this will increase the size of the executable file. If you need to generate debug symbol information when compiling, you can use the -g or -ggdb option of gcc.
When gcc generates debugging symbols, it also adopts a hierarchical idea. Developers can specify how much debugging information to add to the code by adding numbers 1, 2, and 3 after the -g option. The default level is 2 (-g2), and the debugging information generated at this time includes: extended symbol table, line number, local or external variable information.
Level 3 (-g3) contains all the debug information in level 2 plus macros defined in the source code.
Level 1 (-g1) does not contain local variables and debug information related to line numbers, so it can only be used for backtraces and stack dumps.
Backtracking: refers to the function call history of the monitoring program during operation.
Stack dump: It is a method of saving the program execution environment in raw hexadecimal format.

The -l (lowercase l) parameter is used to specify the library to be linked by the program, and the -l parameter is followed by the library name; the library placed in /lib and /usr/lib and /usr/local/lib is directly used -l The parameter can be linked
-L The parameter is followed by the directory name where the library file is located. For example, if we put libtest.so in the /aaa/bbb/ccc directory, the link parameter is -L/aaa/bbb/ccc -ltest
for example:

gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld

/*
 -I /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录,寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include 
-L /home/hello/lib表示将/home/hello/lib目录作为第一个寻找库文件的目录,寻找的顺序是:/home/hello/lib-->/lib-->/usr/lib-->/usr/local/lib
 -lworld表示在上面的lib的路径中寻找libworld.so动态库文件(如果gcc编译选项中加入了“-static”表示寻找libworld.a静态库文件),程序链接的库名是world
*/

The -shared parameter is used when compiling a dynamic library, such as gcc -shared test.c -o libtest.so

-fPIC generates position-independent code, the code has no absolute jumps, and the jumps are all relative jumps,

  • For the dynamic library generated without -fPIC, "When generating the dynamic library, it is assumed that it is loaded at address 0. When loading, it will be loaded to an address (base), and a relocation (relocation) is required at this time, and the code , All addresses in the data segment plus the value of this base. This way the correct address can be used when the code is running."
  • Add the fPIC option, and the dynamic library generated by the fPIC option is obviously position-independent. Such code itself can be placed in any position in the linear address space and can be executed correctly without modification. The usual method is to get the value of the instruction pointer, plus an offset to get the address of the global variable/function. The source file with the fPIC option has a very loose standard for writing the function header file it refers to. For example, it only needs to include the header file of a declared function, even if there is no corresponding C file to implement it, it can still be compiled into an so library.
  • In terms of memory reference, there are similarities and differences between adding fPIC and not adding fPIC; adding fPIC realizes multiple processes sharing so files in the true sense. When multiple processes refer to the same PIC dynamic library, memory can be shared. The virtual address of this library is different in different processes, but the operating system will obviously map them to the same piece of physical memory. If fPIC is not added, when the so file is loaded, the data object referenced by the code segment needs to be relocated, and the relocation will modify the content of the code segment, which causes each process using the code segment of the .so file to be Generate a copy of the code segment of this .so file. Each copy is different, depending on the location of the .so file code segment and data segment memory mapping. It can be seen that this method consumes more memory. But the advantage of the so file compiled without fPIC is that the loading speed is faster

Guess you like

Origin blog.csdn.net/weixin_68294039/article/details/126940843