One, -I header file path
1.1 Simple project structure does not require -I option
If the number of source code and header files in the project is small, the -I option is not needed at all. Put them in the same level directory, and the source files can find the header files normally:
//ttt.cpp
#include <stdio.h>
#include "data.h"
int main()
{
printf("Hello world\n");
printf("Data in header is %lf\n",pi);
}
// data.h
double pi=3.1415;
Type in the terminal:
gcc ttt.cpp
Then you can compile and link normally to form an executable file.
1.2 The project structure is more complex
With the progress of the project, in order to have a clearer structure, people often separate the header files, source files, and compiled results in different folders. Just for demonstration, put the ttt.cpp
and data,h
into the two folders src and include respectively. If you still use the (1.1) method, an error will occur:
junwuli@ubuntu:~/Desktop/gcctest/build$ gcc ../src/ttt.c
../src/ttt.c:2:10: fatal error: data.h: No such file or directory
#include "data.h"
^~~~~~~~
compilation terminated.
At this time, you need to use the -I option:
junwuli@ubuntu:~/Desktop/gcctest/build$ gcc ../src/ttt.c -I ../include/
junwuli@ubuntu:~/Desktop/gcctest/build$ ./a.out
Hello world
Data in header is 3.141500
Assuming that our main program does not want to write a relative path, but only wants to write a concise "head.h" instead of "./include/", we need to use this parameter.
gcc hello.c -Iinclude -o app
or
gcc hello.c -I include -o app
Second, the production and use of the library
Whether it is a static library or a dynamic library, it is necessary to compile the source files into object files, and then integrate the object files to form a library. The library here is similar to the warehouse in life, but the content stored is the target file, and what is in the warehouse depends on the header file.
Probably this is the process:
graph LR
源文件-->目标文件
目标文件-->库的打包
2.1 Library naming rules
Like variable naming, Linux library naming also reveals the attributes and names of the library.
libxxx.so.x.y.z
libxxx.a.x.y.z
section | meaning |
---|---|
lib |
File attributes |
xxx |
Library name |
.so /.a |
Library type |
.x.y.z |
Version number [2] |
2.2 The production and use of static libraries
2.2.1 Making a static library
Take ac bc as an example to generate the target file :
gcc a.c b.c -c
The target file ao bo with the same name is generated by default
According to the ao bo material generated in the previous step, package the target file
ar rcs libtest.a a.o b.o
Note: rcs stands for inserting target files to create archive files and indexing.
2.2.2 Use static libraries
libtest.a + header file, header file plus library use static library
gcc main.c -I ./include/ -L ./lib/ -ltest -o app
Note: nm(name) can view the content in lib
2.3 Dynamic library production and use
2.3.1 Making a dynamic library
Take ac bc as an example, the -fPIC option generates the target file[3] :
gcc a.c b.c -c -fPIC(-fpic)
According to the ao bo material generated in the previous step, the --shared option is used to package the target file
gcc -shared a.o b.o -o libxxx.so
in
2.3.2 Use dynamic libraries
Header file plus library settings use dynamic library
gcc main.c -I ./include/ -L ./lib/ -lxxx -o app
Just like the static library, specify the path of the library and the name of the library. If it is in the same level directory as the source file, OK, there is no problem at all, but if it is in the next level of lib, it will be prompted that it cannot be found!
ldd 用静态库编译的可执行文件
The above one can check the dependent library and whether it is found.
2.4 Dynamic library search path
The format of dynamic libraries, executable programs, and .o files are all ELF, and the system uses ld-linux.so.X[1] to complete. In order, they are:
- DT_PRATH section of ELF file
- Environment variable LD_LIBRARY_PATH
- File list /etc/ld.so.cache
- If /lib usr/lib is
found at any step, it will be loaded into the memory for normal use, otherwise an error that the library cannot be found is reported.
Notes:
[1] One of the libraries installed by Glibc is ld-linux.so.X, where X is a number, and the name will be different on different platforms. For example, ubuntu18.04 is ld-linux-x86-64.so .2
[2] x
indicates the major version number, different major versions are generally incompatible; y
minor version number, incremental upgrade of the library, the original interface remains unchanged but some new interfaces are added, and the old version is compatible at the same time; the z
release version number, some library functions are wrong, The performance is improved, and the interface does not increase or change.
[3] In order to be compatible with various systems, the -fPIC parameter should be used when generating position-independent code.
Reference article:
[1] "- fpic and -fPIC the difference between" Author: zhang_dawei666 (https://blog.csdn.net/xiangguiwang/article/details/81939237)
Expansion:
The difference between dynamic and static libraries: https://www.cnblogs.com/mhscn/p/4264357.html