Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

https://www.cnblogs.com/ishen/p/11993957.html

库文件介绍

包含静态库文件(.a)和动态库文件(.so)。

静态库就是在链接的时候加入到执行代码中,成为了代码的一部分,所以生成的可执行文件就比较大,以后和静态库没瓜葛了,自己随便用了;
动态库是指运行的时候会链接到库文件,如果没找到就运行。

overview

img

1.目标文件、静态库、动态库文件的生成

目标文件xxx.o的生成,使用 -c 选项,指定只生成而不链接

gcc -c xxx.c -o xxx.o

静态库的生成,需先生成目标文件,使用**ar rcs**命令对其做转换

gcc -c xx1.c -o xx1.o
gcc -c xx2.c -o xx2.o
ar rsc libxxx.a xx1.o xx2.o

动态库的生成,使用**-shared要求生成动态库,通常还加上-fpic**要求生成的代码地址无关,就是要动态库内部的使用相对偏移寻址,防止安全攻击

gcc xxx.c -fPIC -shared -o libxxx.so

2. 头文件的查找顺序

  1. 先搜索当前目录

  2. 然后搜索**-I**指定的目录

    gcc xxx.c -o xxx -lopenssl // 链接openssl.so
    
  3. 环境变量**CPLUS_INCLUDE_PATH(c使用的是C_INCLUDE_PATH**)

  4. 最后搜索gcc/g++的内定目录
    /usr/include
    /usr/local/include
    /usr/lib/gcc/x86_64-redhat-linux/4.1.1/include

-v -H可以打印查找使用的头文件和过程

3.库的查找顺序

运行时动态库的查找顺序:

1.环境变量**LD_LIBRARY_PATH**(注意不是LIBRARY_PATH)

2./etc/ld.so.conf下所包含的路径

其中,关于ld.so.conf中,参见此文:

Linux的动态链接库绝大多数都在`/lib`和`/usr/lib`下,操作系统也会默认去这两个路径下搜索动态链接库。另外,`/etc/ld.so.conf`文件里可以配置路径,`/etc/ld.so.conf`文件会告诉操作系统去哪些路径下搜索动态链接库。这些位置的动态链接库很多,如果链接器每次都去这些路径遍历一遍,非常耗时,Linux提供了`ldconfig`工具,这个工具会对这些路径的动态链接库按照SONAME规则创建软连接,同时也会生成一个缓存Cache到`/etc/ld.so.cache`文件里,链接器根据缓存可以更快地查找到各个`.so`文件。每次在`/lib`和`/usr/lib`这些路径下安装了新的库,或者更改了`/etc/ld.so.conf`文件,都需要调用`ldconfig`命令来做一次更新,重新生成软连接和Cache。但是`/etc/ld.so.conf`文件和`ldconfig`命令最好使用root账户操作。非root用户可以在某个路径下安装库文件,并将这个路径添加到`/etc/ld.so.conf`文件下,再由root用户调用一下`ldconfig`。

编译链接时,库查找顺序:

1.-L或 -Wl, rpath指定的路径

2.查找环境变量**LIBRARY_PATH**下的路径(注意不是LD_LIBRARY_PATH)

3.查找 /etc/ld.so.conf 下包含的路径

4 /lib 和 /usr/lib

其中,-L和-Wl, rpath都能够显示的指定库所在的目录,但它们存在区别,参见此文:

-L指定的库路径,在动态链接的时候,库的路径信息不会被存到到目标文件中,运行时目标文件只能通过LD_LIBRARY_PATH以及ld.so.conf提供的路径查找,
如果使用-Wl, rpath则库的路径会存到目标文件中,运行时目标文件会先去这个路径查找,找不到了,再去LD_LIBRARY_PATH和ld.so.conf中找

查看动态库的路径

.so文件的

ldconfig -p

4. 链接静态库和动态库的优先级

直接使用**-l查找路径的时候,gcc/g++默认优先链接动态库,找不到动态库后,才去找静态**库

gcc xxx.c -o xxx -lopenssl // 链接openssl.so

要明确指明链接静态库就需要使用或者 -static 进行显示指定全都使用静态库

gcc xxx.c -o xxx -static -lopenssl // 链接libopenssl.a

也可以使用 -Wl,-Bstatic, 这个选项使用后,后续的-l都是去找静态库,但可以通过Wl,-Bdynamic 再指定后面的都是动态库

//连接 libxx1.a libxx2.a libxx3.so
gcc xxx.c -o xxx -WL,-Bstatic -lxx1 -lxx2 -WL,-Bdynamic -lxx3

修改环境变量

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:XXXX

相较于g++原始编译,推荐CMake

上面的路径搜索顺序、动态库静态库顺序、给编译器的flags还是适用的。

指明要链接库gflags

add_executable(main main.cpp)
target_link_libraries(main gflags)

可以用绝对路径指明库文件

add_executable(main main.cpp)
target_link_libraries(main /home/yuanzhiqiu/project/gpstore/tools/rocksdb-v8.0.0/librocksdb.a)

举例:

代码是https://github.com/TuGraph-family/gdbms-microbenchmark/tree/master/kv_test中的`rocksdb_lmdb.cpp`

cmake_minimum_required(VERSION 3.15)
project(rksdb_lmdb)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS
        "${CMAKE_CXX_FLAGS} -std=c++17 -I/home/yuanzhiqiu/project/gpstore/tools/rocksdb-v8.0.0/include -pthread")
        # for debug: -Wl,--verbose: argument to ld
        # -Idir: Add the directory dir to the list of directories to be searched for header files during preprocessing. 
        # -pthread: Define additional macros required for using the POSIX threads library.  

add_executable(rocksdb_lmdb rocksdb_lmdb.cpp)
target_link_libraries(rocksdb_lmdb lmdb /home/yuanzhiqiu/project/gpstore/tools/rocksdb-v8.0.0/librocksdb.a z dl gflags stdc++fs)
# z dl: needed for rocksdb
# gflags stdc++fs: needed in rocksdb_lmdb.cpp

评论