GCC/G++ is used to compile and link C/C++ programs, long story short, a compiler. Its history is not described here, so those who are interested can check it out for themselves.
Compilation process of C/C++
Before introducing GCC/G++, let’s briefly explain the process of compiling and linking C/C++ to generate executable files.
Source file preprocessing: c preprocessing (cpp.exe) to process macros in source files, etc.
cpp hello.c > hello.i
Compile: gcc/g++ compiles the preprocessed code into an assembly program, the
-Soption indicates the generation of an assembly program file (.s)
gcc -S hello.i
Generate the target file (.o) from the assembler using as.exe
as -o hello.o hello.s
Finally, use the connector (ld.exe) to link the target file (.o) to generate the executable file (.out/.exe)
ld -o hello.out hello.o ...libraries...
Use of GCC/G++
Let’s take GCC as an example and introduce the basic usage. Create a new
hello.c file and write the following contents.
Compile and link the c file
The default is to generate
a.out(the executable is a.out on linux, a.exe on windows). You can use the
-ooption to specify the name of the generated file.
Separate compilation and linking processes
A file has changed in the actual project and we want to compile it separately and then link its compiled target file (.o) with other target files or library files. The source file can be compiled to the target file (.o) using the
Linking a target file into an executable file executes the same commands as compiling and linking. The linking process is executed when the source file is a target file, and the compiling and linking process is executed when the source file is a C file.
Multi-file compilation link
The gcc command supports multiple source file input if you want to compile source1.c and source2.c together.
More often than not, you may want to compile them separately.
Print all warning messages at compile time
-Walloption prints all warning messages, so it is usually turned on when using gcc.
$ gcc -Wall -o hello hello.c
-goption, you can make the file contain debugging information to be made available to gdb for debugging.
$ gcc -Wall -g -o hello hello.c
Print the complete message at compile time
-vprints the complete compilation process information.
$ gcc -v -o hello hello.c
Static and Shared Libraries
Usually we compile some common methods, variables, classes, into a separate library for the business side to call. A library is essentially a file containing one or more object files (object files) for use in the linking phase.
There are two types of libraries: static library and shared library, which is also called dynamic library. What are the differences in their behavior?
- Static libraries are a collection of target files (.o) with the suffix
.aon linux and mac, and
.libon windows. It is linked with other target files (.o) to form an executable (.out) during the linking phase of the program compilation process. So the static library only works in the compilation phase, it is not needed at runtime.
- Shared libraries are also collections of target files, with the suffix
.so(shared object) in linux,
.dylibin mac, and
.dllin windows, and play a role in both the linking phase and the running phase of program compilation. During the linking phase, the linker verifies that the symbols (variables, methods, etc.) needed for program execution have been linked into the program or exist in one of the shared libraries. But the target file in the shared library is not linked to the final generated executable. In the Run phase, when the program starts, there is a program in the system - dynamic loader that checks which dynamic libraries are linked into the program and loads these dynamic libraries into memory to be executed with the program. So the shared libraries must be present when the program is running.
Static libraries are equivalent to the code contained in them being copied into the executable at compile time, while the code of shared libraries is loaded into memory at runtime, so if you compile with static libraries, the final generated executable will be larger than the one obtained by compiling with shared libraries.
Static library creation and linking
Use the ar tool to create static libraries. ar has the following functions.
- Create static libraries.
- Change the target files in the static library (as said before a static library is a collection of target files).
- View the names of the target files contained in the static library.
You can use
man ar to see the usage of the
ar command in linux.
Create a static library
A static library can be created with the following command.
$ ar -rc libutil.a util_file.o util_net.o util_math.o
The above command packages
util_math.ointo the static library
libutil.a, and if the
libutil.afile already exists, then it will add the
util_math.ofiles to the static library. files to the static library. The
coption creates the library file if it does not exist, and the
roption replaces the target file if the target file to be packaged already exists in the library.
You can also use gcc’s
-staticto generate static libraries.
$ gcc *.o -static -o libname.a
Static file names generally start with the
libprefix and end with the
.asuffix, because the compiler looks for library files based on this feature when linking (explained below).
Using static libraries
After we create the static library, we want to use it in our program. The library file can be linked into an executable file along with the target file by using the following command.
For example, the following example links the target file
main.o with the library
libutil.a into the executable prog.
It is important to note that.
-Loption is used to indicate the library file directory, and
.indicates the current directory, so the library to be linked is in the current directory.
-loption is used to indicate the name of the library file to be linked. Note that we have removed the prefix
liband the suffix
.afrom the library file name, so the library file name starts with
liband ends with
- Note that the library file should be placed after the target file, as detailed below
In the execution of
gcc main.o -L. -lutil -o prog, assuming that
main.o uses a function symbol from
libutil.a, such as the
add method, the linker executes as follows.
- The linker scans the target file and the static library from left to right
- when scanning
main.o, it finds an unresolved symbol
add, remember this unresolved symbol
libutil.aand find the previous unresolved symbol, so extract the relevant code
- Finally, there are no unresolved symbols, the compilation and linking is completed, and the executable
If the static library is placed in front of the target file, for example by executing
gcc -L. -lutil main.o -o prog, then the linker will execute as follows.
- the linker scans the static library and the target file in order from left to right
libutil.awithout extracting any code from the library because there are no unresolved symbols in front of it
- When scanning
main.o, the unresolved symbol exp is found
- At the end of the scan, there are unresolved symbols, so the compilation and linking reports an error
Shared library creation and linking
The process of creating a shared library (dynamic library) is not much different from that of a static library, in that a set of target files are compiled and inserted into a library file. However, when linking a dynamic library, instead of “copying” all the required binary code into the executable, only some relocation and symbolic information is “copied”, with which the real linking process will be completed when the program runs.
Creating shared libraries The
-sharedargument to gcc creates shared libraries
Links to shared libraries
The link shared library is the same as the link dynamic library command. Since gcc uses dynamic linking by default, if there are dynamic and static libraries with the same name, gcc will link the dynamic library, and you can use
-staticto specify the static library to be linked.
$ gcc main.o -L. -lutil -o prog
The above command will link the
Normally, when a program is run, the system dynamic loader will look for shared libraries in some directory specified by the system (e.g. /lib, /usr/x11/lib, etc.). When we create a shared library, we can use the
LD_LIBRARY_PATHenvironment variable to tell the dynamic loader to look in the specified directory.
You can use the ldd command to view the shared libraries on which the executable depends.
$ ldd prog