In the Linux environment, we usually use GCC to compile C code into an executable file, as follows is a simple example:
Small experiment: HELLO.C
#include <stdlib.h>#include <stdio.h>void main(void){ printf("hello world!\r\n");}
An executable file can be compiled with the following instructions:
gcc hello.c
After executing the command, you will get a a.out executable file.
The process of compiling
The previous example is just a brief introduction of the use of GCC, familiar with C programming friends will know that the step actually contains the preprocessing –> compiled –> assembly –> Link Four steps, the four steps to achieve the following functions:
- Preprocessing phase: Mainly handles #ifdef in source files, #include和 # define commands, expand macros, read defined symbols, etc. (. i)
- Compile phase: Check the normative code, translate the code into assembly language (. s)
- Assembly stage: is to convert the files generated during the compilation phase into binary target code (. O)
- Link stage: Assemble the machine code generated during the assembly phase into an executable binary code file
It can be seen that each phase of the output is actually the next stage of input, with GCC is able to perform these four steps alone:
gcc -E hello.c -o hello.igcc -S hello.i -o hello.sgcc -c hello.s -o hello.ogcc hello.o -o hello
In fact, because these four steps are too complex, they can often be executed in one command, as I did above:
gcc hello.c -o hello
Here I add an-o parameter to specify the output name instead of the default a.out.
-O optimization option, this option is not a standard
- -O and-o1 specify 1-level optimizations
- -o2 Specifying Level 2 optimization
- -o3 Specifying Level 3 optimization
-o0 specify not to optimize
GCC Hello.c-o3-o0 Hello when there are multiple optimizations, whichever is the last!!
If you have multiple files, you can centralize them all in the following ways.
gcc -o test first.c second.c third.c
This full-build approach is simple, but one problem is that when the project is large, if you change only one file, you still need to recompile the index file.
To solve this problem, we tend to split the compilation process into two steps:
This way, when the third.c file changes, only the THIRD.C and links need to be recompiled, eliminating the compile time of the unchanged file, which is what we typically call incremental compilation.
gcc –c third.cgcc -o test first.o second.o third.o
From the above methods we can also see:
- When you use the-c parameter, if you enter a file. C executes the preprocessing, compiling, and assembling three stages, directly generating the. o file.
- The link operation can be performed directly when the input file is. o
Since programmers often do not care about the output files generated by the previous two phases, we usually combine the preprocessing, compilation, and assembly three phases together, collectively known as compilation, input. c, generate. O.
Common parameters:
In fact, I have already demonstrated the use of several parameters such as-E, –S, –c, –o and so on, where-e and-s are seldom used, and-C is used for compiling the generated. o file,-O for specifying the output file name. In addition to these several generation control parameters, there are many parameter settings, here is the main introduction of several commonly used:
Include header files and libraries:
- -idir: Specifies the directory where the lookup header files are compiled, often used to find header files for third-party libraries, for example: GCC test.c–i. /inc-o test.
- -ldir: Specifies a directory to find Lib when linking, and is commonly used to find third-party libraries.
- -llibrary: Specify the Lib Library for additional links
Macro definition:
- -dmacro: Defines macro macros as the string "1" (the default value).
- -DMACRO=DEFN: Define macro Macros with the string "DEFN", noting that there can be no spaces in the middle.
- -umacro: Cancels the definition of macro macros.
Debug and executable file forms:
- -G: Instructs the compiler to generate debug information at compile time.
- -GGDB: Generate as much debug information as GDB can use (more information than-G generates).
- -static: Disable the use of dynamic libraries, compiled programs will be larger, but can run freely.
- -share: Use dynamic libraries as much as possible, so the resulting file is smaller, but requires the system to be a dynamic library.
Alarm options:
- -wall: Generate as many warning messages as possible, always suggest
- -werror: Treat all warnings as errors
GCC and g++
In addition to the GCC compiler, there is another compiler g++, many people often do not know the difference between the two compilers, many people words too literally that GCC can only compile C code, g++ can only compile C + + code. In fact, the main differences between the two compilers are as follows:
- The suffix is. C, GCC treats it as a C program, and g++ as a C + + program to compile, with the suffix. cpp, both of which are considered C + + programs, note that although C + + is a superset of C, there are differences between the two requirements for syntax. C + + syntax rules are more rigorous.
- When linking, GCC does not add the-lstdc++ option by default, and g++ will, so when GCC compiles C + + code, the link fails when the STL library is used.
- GCC does not define __cplusplus macros, and g++, the macro simply signifies that the compiler will interpret the code in C or C + + syntax, if the suffix is. c, and the GCC compiler is used, the macro is undefined, otherwise it is defined.
Static link library
Sometimes we need to weave a set of code into a library to facilitate its reuse. For example, the STL and system functions we call are provided in this way. In addition, when the project is large, it is sometimes necessary to create its own link library in order to make its modularity easier to work with.
Code Demo:
// stack.c#include <stdio.h>char stack[512];int top = -1;char pop(void){ return stack[top--];}void push(char c){ stack[++top] = c;}
The following two steps are required to make STACK.C a lib:
- STACK.C is compiled by gcc–c command STACK.O
gcc -c stack.c
- STACK.O encapsulated into libstack.a via AR command
ar cr libstack.a stack.o
Create a test file
// main.c#include <stdio.h>char pop();void push(char c);void main(void){ push(‘a‘); push(‘b‘); printf("%c\n", pop());}
Link compilation:
gcc -o run main.c -L. -lstack
In the above process, a command AR was used that was not seen before. AR is the abbreviation of archive, that is, the meaning of archiving, usually we use more is another archive command tar. The AR and tar functions are quite similar, but the AR command does some extra processing, which indexes the symbols in the archived target file, and when linked to the application, these indexes will recycle the linking process
The parameters of the AR command are more, if just create Lib library, usually only use the CR these two combination parameters. The command is capable of accepting multiple input files, consolidated into one library.
ar cr libtest.a first.o second.o third.o
After creating lib through AR, you can view the AR-T command to package those. o files in the lib.
ar -t libstack.astack.o
In addition, you can view more information, such as symbol tables, by using the NM command.
nm libstack.astack.o:0000000000000000 T pop0000000000000021 T push0000000000000200 C stack0000000000000000 D top
Dynamic Link Library
In the traditional way, the link to the library function is done by the compiler, and all related objects are consolidated into an executable file at compile time. In contrast, we can also load the link of a library function into a period of time when the program is running, which is what we call a dynamic link.
Advantages of dynamic linking
In addition to the static link library all the modularity and code reuse, the dynamic link library has the following advantages:
- You can implement library sharing between processes: When multiple processes share a library (such as STL libraries and some system libraries that are mostly used by most programs), dynamic linking can save memory by keeping only one copy in memory.
- The upgrade is simple: Users only need to upgrade the dynamic link library, without recompiling the link to other legacy code to complete the entire program upgrade (many Windows patches are published this way).
- Can be loaded dynamically: when the software is relatively large, you can dynamically load/unload the corresponding link library as needed, without having to load it all at once as a static link
The way to create a dynamic-link library is simple, or as an example of a static-link library, we only need to create a libstack.so dynamic library with the gcc-shared directive (static libraries generally use. A as the extension, and dynamic libraries generally use. So as the extension).
gcc -c -fpic stack.cgcc -shared -o libstack.so stack.o
The-fpic must be brought here so that the output object module is generated according to the Relocatable address method.
Using dynamic libraries in the link phase is essentially consistent with static libraries.
gcc -o run main.c -L. -lstack
After compiling and playing this program, we found that it reported that the dynamic link library could not find the error prompt.
./run./run: error while loading shared libraries: libstack.so: cannot open shared object file: No such file or directory
We can also view the current dependency of a program on a dynamic-link library through the LDD command:
ldd runlinux-vdso.so.1 => (0x00007fff366fe000)libstack.so => not foundlibc.so.6 => /lib64/libc.so.6 (0x00002ba53ad1f000)/lib64/ld-linux-x86-64.so.2 (0x00002ba53ac03000)
The results of the LDD show that the libstack.so we generated was not found. Because a dynamic-link library is a file that can be shared, it is often stored in a common location, and the rules for a program to find a dynamic-link library in a Linux system are as follows:
- This is first found in the path recorded by the environment variable Ld_library_path.
- Then find it from the cache file/etc/ld.so.cache.
- If none of the above steps are found, then look in the default system path, first/lib and then/usr/lib.
It is clear that these paths do not contain the current path. A simple way to solve the above problem is to add the current path to the environment variable:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
Then use the LDD name test again to find our link library now.
ldd runlinux-vdso.so.1 => (0x00007fff581ff000)libstack.so (0x00002ad148cf0000)libc.so.6 => /lib64/libc.so.6 (0x00002ad148e0b000)/lib64/ld-linux-x86-64.so.2 (0x00002ad148bd4000)
However, many Daniel does not recommend modifying Ld_library_path this way
LD_LIBRARY_PATH is not the answer http://prefetch.net/articles/linkers.badldlibrary.htmlWhy LD_LIBRARY_PATH is bad http://xahlee.org/UnixResource_dir/_/ldpath.htmlLD_LIBRARY_PATH - just say no http://blogs.sun.com/rie/date/20040710
From for notes (Wiz)
Linux Advanced Programming--02.GCC and dynamic libraries