Table of contents
1. Understand dynamic and static libraries
1.1 Features of static libraries
1.2 Features of dynamic library
2. Packaging and use of static libraries
2.1 Packaging of static libraries
3. Packaging and use of dynamic libraries
3.1 Packaging of dynamic library
1. Understand dynamic and static libraries
A bunch of source files and header files finally become an executable program needs to go through the following four steps:
- Preprocessing: Complete header file expansion, comment removal, macro replacement, conditional compilation, etc., and finally form xxx.i file
- Compilation: Complete lexical analysis, syntax analysis, semantic analysis, symbol summary, etc., and translate the code into assembly instructions after checking, and finally form the xxx.s file
- Assembly: Convert assembly instructions into binary instructions, and finally form xxx.o files
- Link: link the generated xxx.o files to finally form an executable program
In fact, all libraries are essentially a collection of object files (xxx.o). The library files do not contain the main function but only contain a large number of methods for calling. It can be considered that the essence of the dynamic and static library is an executable program." Semi-finished products"
- In Linux
.so
, the suffix is a dynamic library,.a
and the suffix is a static library - In Windows
.dll
, the suffix is a dynamic library,.lib
and the suffix is a static library
Let's take a look at the dynamic and static library through a simple code
#include <stdio.h>
int main()
{
printf("hello lib\n");//printf()为库函数
return 0;
}
Through the ldd command, you can view the library files that the executable program depends on
It can be seen from the above figure that the test executable program depends on /lib64/libc.so.6 , but it is a soft link, and the linked source file is /lib64/libc-2.17.so . This libc-2.17.so is actually a C dynamic library, remove a library prefix lib
, and then remove the suffix, and the rest is the name of the library.
However, gcc/g++ performs dynamic linking by default. If you want to use static linking, you need to add the -static option, and the executable program generated by static linking does not depend on other library files.
And the size of the executable program using the static library is significantly larger than the size of the executable program using the dynamic library
1.1 Features of static libraries
A static library is a program that copies the code of the library into an executable file when compiling and linking. The generated executable program will no longer need a static library when it is running. Therefore, the size of an executable program generated using a static library is generally relatively small. big
- Advantages: After using the static library to generate an executable program, the executable program can run independently without relying on the library
- Disadvantages: Using static libraries to generate executable programs will take up a lot of space, especially when multiple static programs are loaded at the same time and these static programs use the same library, then there will be a lot of duplicate code in memory
1.2 Features of dynamic library
The dynamic library is to link the corresponding dynamic library code when the program is running. It is not necessary to copy the code of the library to the executable file, so that the size of the executable program is smaller than that of the static library, saving disk space. An executable file linked with a dynamic library only contains a table of the entry addresses of the functions it uses, rather than the entire machine code of the object file where the external function is located.
Before the executable file starts running, the machine code of the external function is copied from the dynamic library on the disk to the memory by the operating system. This process is called dynamic linking. The operating system adopts the virtual memory mechanism so that a dynamic library in the physical memory is shared by all processes that want to use the library, saving memory space.
- Advantages: Save memory and disk space. When multiple programs that use the same dynamic library are running at the same time, the library files will be shared through the process address space, and there will be no duplicate code in the memory.
- Disadvantage: must rely on dynamic library, otherwise it cannot run
2. Packaging and use of static libraries
In the following demonstration, these files are used as examples. Source files main.c, test1.c and test2.c, header files test1.h and test2.h
main.c file
#include "test1.h"
#include "test2.h"
int main()
{
test1();
test2();
return 0;
}
test1.c file
#include "test1.h"
void test1(){
printf("This is test1!!!\n");
}
test1.h file
#pragma once
#include <stdio.h>
void test1();
test2.c file
#include "test2.h"
void test2(){
printf("This is test2!!!\n");
}
test2.h file
#pragma once
#include <stdio.h>
void test2();
2.1 Packaging of static libraries
The first step: Generate the corresponding target file from the source file to be packaged
test1.o:test1.c
gcc -c tets1.c -o test1.o
test2.o:test2.c
gcc -c test2.c -o test2.o
Step 2: Use the ar command to package all object files as a static library
The ar command is an archive tool for gnu. The following uses ar
the command -r
and -c
options to package
- -r (replace): If the target file in the static library file is updated, replace the old target file with the new target file
- (create): Create a static library file
libtest.a:test1.o test2.o
ar -rc libtest.a test1.o test2.o
In addition, we can use the -t and -v options of the ar command to view the files in the static library.
- -t: list the files in the static library
- -v(verbose): Display detailed information
Step 3: Organize header files and generated static libraries
mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include
cp ./*.a ./my_lib/lib
When you want to publish the library for others to use, just publish this folder
makefile full version
libtest.a:test1.o test2.o
ar -rc $@ $^
test1.o:test1.c
gcc -c $^ -o $@
test2.o:test2.c
gcc -c $^ -o $@
.PHONY:output
output:
mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include
cp ./*.a ./my_lib/lib
.PHONY:clean
clean:
rm -rf ./my_lib ./*.o ./*.a
2.2 Use of static libraries
Option 1: Use options
-I
: Specify the header file search path-L
: Specify the library file search path-l
: Indicate which specific library under the library file path needs to be linked
Solution 2: Copy the header files and library files to the system path
[bjy@VM-8-2-centos usedir]$ sudo cp output/include/* /usr/include/
[bjy@VM-8-2-centos usedir]$ sudo cp output/lib/libtest.a /lib64/
Note: Although the header files and library files have been copied to the system path, when using gcc to generate an executable program, it is necessary to specify which library to link
In fact, the process of copying the header files and library files to the system path is the process of installing the library. However, it is not recommended to copy the header files and library files written by individuals to the system path, which will pollute the system files.
3. Packaging and use of dynamic libraries
3.1 Packaging of dynamic library
The first step: Generate the corresponding target file from the source file to be packaged
At this time, you need to add the -fPIC option, that is, generate position-independent code
test1.o:test1.c
gcc -fPIC -c test1.c -o test1.o
test2.o:test2.c
gcc -fPIC -c test2.c -o test2.o
-fPIC acts on the compilation stage and tells the compiler to generate position-independent code. At this time, there is no absolute address in the generated code, and all use relative addresses, so that the code can be loaded by the loader to any location in the memory and can be executed correctly. (Establish a mapping relationship with the shared area through the page table). So when the shared library is loaded, its location in memory is not fixed.
Step 2: Use the -shared option to package all object files as dynamic libraries
libtest.so:test1.o test2.o
gcc -shared $^ -o $@
Step 3: Organize header files and generated dynamic libraries
mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include
cp ./*.so ./my_lib/lib
makefile full version
libtest.so:test1.o test2.o
gcc -shared $^ -o $@
test1.o:test1.c
gcc -fPIC -c test1.c -o test1.o
test2.o:test2.c
gcc -fPIC -c test2.c -o test2.o
.PHONY:output
output:
mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include
cp ./*.so ./my_lib/lib
.PHONY:clean
clean:
rm -rf *.so *.o my_lib
3.2 Use of dynamic library
Next, use the same method as the static library, use -I
the option to specify the header file search path, use -L
the option to specify the library file search path, and finally use -l
the option to specify the name of the library. But it can be found that the executable program does not seem to be able to find the location of this dynamic library.
Because the above three options are passed to the gcc compiler, but after the executable program is generated, it has nothing to do with the compiler, so when the program runs, the operating system cannot find the dependent dynamic library.
Solution 1: Copy the .so file to the system shared library path
[bjy@VM-8-2-centos uselib]$ sudo cp ./my_lib/lib/libtest.so /lib64
Solution Two: Change LD_LIBRARY_PATH
LD_LIBRARY_PATH
It is the path to be searched when the program runs to dynamically find the library, just add the directory path LD_LIBRARY_PATH
where the dynamic library is located to the environment variable.
But this solution can only solve the problem temporarily. When the terminal is closed and then reopened, the imported environment variables will be lost.
Solution 3: Configure /ect/ld.so.conf.d/
All the configuration files with the suffix .conf are stored under the /etc/ld.so.conf.d/ path, and all the configuration files are stored in the path, and the system will automatically store them in /etc/ld.so.conf. Find the paths in all configuration files under the d/ path, and then find the libraries required by the user under each path. If the path of the third-party library file is also placed in this path, then when the executable program runs, the system can find the third-party library file.
First save the path of the directory where the library file is located in a file with a suffix of .conf, then copy the file to the /etc/ld.so.conf.d/
directory, and finally use the ldconfig command to update the configuration.