zoukankan      html  css  js  c++  java
  • linux动态库与静态库混合连接

     

    1, 在应用程序需要连接外部库的情况下,linux默认对库的连接是使用动态库,在找不到动态库的情况下再选择静态库。使用方式为:

    gcc test.cpp -L. -ltestlib

    如果当前目录有两个库libtestlib.so libtestlib.a 则肯定是连接libtestlib.so。如果要指定为连接静态库则使用:

    gcc test.cpp -L. -static -ltestlib

    使用静态库进行连接。

    2, 当对动态库与静态库混合连接的时候,使用-static会导致所有的库都使用静态连接的方式。这时需要作用-Wl的方式:

    gcc test.cpp -L. -Wl,-Bstatic -ltestlib  -Wl,-Bdynamic -ltestlib 

    3, 另外还要注意系统的运行库使用动态连接的方式,所以当动态库在静态库前面连接时,必须在命令行最后使用动态连接的命令才能正常连接

    ,如:

    gcc test.cpp -L. -Wl,-Bdynamic -ltestlib -Wl,-Bstatic -ltestlib  -Wl,-Bdynamic 


    1、使用GCC创建和使用静态库 

    (1)gcc –o mylib.o –c mylib.c  //生成o文件
    (2)ar -rcs libmylib.a mylib.o   //生成a文件
        -c create的意思
        -r replace的意思,表示当插入的模块名已经在库中存在,则替换同名的模块。
    (3)cp libmylib.a /usr/lib/       //拷贝到默认目录
    (4)编写程序使用库中的函数,需要包含相关的头文件,即可用下面的方式进行编译连接。
        gcc –o test test.c -L. -lmylib
        -L指定静态函数库的位置供查找,注意L后面还有'.',表示静态函数库在本目录下查找。
        -l则指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略。

    2、使用GCC创建和使用动态库

    (1)gcc –fPIC –o mylib.o –c mylib.c
        gcc –shared –o libtt.so mylib.o
        -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
        -shared 作用于链接阶段,实际传递给链接器ld,让其添加作为共享库所需要的额外描述信息,去除共享库所不需的信息。
    (2)也可以直接使用下面一条命令:
        gcc –fPIC –shared –o libtt.so mylib.c
    (3)将动态库拷贝到linux 的标准库中,usr/local/lib 或者/usr/lib 或者/lib,使用ldconfig命令加载
        cp libttt.so /usr/local/lib
    (4) 编译src 程序使用动态库,隐式调用方法: 在编译调用库函数代码时指明动态库的位置及名字
        gcc –o test test.c  ./usr/lib/libttt.so
    (5)编译src程序使用动态库,显示调用方法
         显式调用动态库需要四个函数的支持, 函数 dlopen 打开动态库, 函数 dlsym 获取动态库中对象基址, 函数 dlerror 获取显式动态库操作中的错误信息, 函数 doclose 关闭动态库.

    #include <dlfcn.h> 
    int main() 

                    void *pHandle; 
                    void (*pFunc)(); // 指向函数的指针 
                    int *p; 
                    pHandle = dlopen("./d1.so", RTLD_NOW); // 打开动态库 
                    if(!pHandle){ 
                                    printf("Can't find d1.so "); 
                                    exit(1); 
                    } 
                    pFunc = (void (*)())dlsym(pHandle, "print"); // 获取库函数 print 的地址 
                    if(pFunc) 
                                    pFunc(); 
                    else 
                                    printf("Can't find function print "); 
                    dlclose(pHandle); // 关闭动态库 
                    return 0; 

        gcc –o test test.c -lttt -L
        此时会到系统目录下去搜素libttt.so文件,具体搜索方法见下一节。

    3、shell 搜索动态库路径位置的两种方法
        (1) 使用命令导入动态库的路径,命令如下:
        export LD_LIBRARY_PATH=dir (如/usr/local/lib)
        (2) 在/etc/ld.so.conf 文件中更增加一条,修改后用ldconfig 命令载入修改。

    4、其他

    (1)ldd命令可以查看一个可执行程序依赖的共享库,
        # ldd /bin/ln
        => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
        => /lib/ld- linux.so.2 (0×40000000)
        可以看到ln命令依赖于libc库和ld-linux库

    (2)看动态库包含哪些定义用:
         nm -D lib*.so

     (3)当生成动态库时,源文件又引用其他静态库,需要一起写。这时源文件里面不用用extern f();,这样就不能引入静态库。需要直接#include 头文件。

         比如,gcc -fexceptions -O2 -o hello.node ./build/Release/obj.target/hello/hello.o ./libpanda.a /usr/local/lib/libnfc.a  -shared -fPIC

    参考:

    gcc生成静态库和动态库: http://blog.csdn.net/ast_224/article/details/3988244

    动态库(.so)链接静态库(.a)的情况总结

     http://www.cnblogs.com/nobugtodebug/archive/2012/11/07/e6cd72c67b3dd843f40d7ce919f7336a.html

    http://www.cppblog.com/deane/archive/2014/05/23/165216.html

    gcc链接选项 链接静态库和动态库 

    qlee
      qlee 发布于 2017/03/09 00:01
     
    字数 1124
     
    阅读 7.1K
     
     收藏 1
       

    链接库

    链接指定的库有两种方式

    • -llibrary
    • -l library

    如链接LuaJIT库,可以用-lluajit-5.1,此时gcc会在库路径中查找libluajit-5.1.so或者libluajit-5.1.a。 也可以用-l llibluajit-5.1.a,第二种只能用在POXIS上,推荐使用第一种方式。而且第二种方式只会在特定的目录进行搜索,会发生找不到库的情况。

    通过-llibrary链接库时,可能既有静态库如libluajit-5.1.a,也有动态库如libluajit-5.1.so,这是链接器会优先链接动态库。

    指定库路径

    如果需要的库不在系统的库搜索路径下,就需要通过-L指定库的搜索路径。 如lua解释器安装时会把libluajit-5.1.a,和libluajit-5.1.so等放在/usr/local/lib下,而gcc进行链接时默认不会在这个路径下搜索库,导致链接失败。通过-L/usr/local/lib指定库路径就可以解决这个问题。

    ~$ gcc main.c -lluajit-5.1             
    /usr/bin/ld: 找不到 -lluajit-5.1
    collect2: error: ld returned 1 exit status
    
    ~$ gcc main.c -L/usr/local/lib -lluajit-5.1
    

    指定运行时库搜索路径

    有时通过-L指定库路径可以正常链接,运行程序时却因为找不到库报错

    ~ $ ./a.out 
    ./a.out: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
    ~ $ ldd ./a.out 
    	linux-vdso.so.1 =>  (0x00007ffc1638e000)
    	libluajit-5.1.so.2 => not found
    	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c23d48000)
    	/lib64/ld-linux-x86-64.so.2 (0x000055713bf16000)
    
    

    使用ldd命令可以看到运行时找不到libluajit-5.1.so.2,无法运行,对此可以通过-Wl,-rpath指定运行时库的搜索路径

    kenan@kenan-desktop ~ $ gcc test.c -I/usr/local/include/luajit-2.1 -Wl,-rpath=/usr/local/lib/ -lluajit-5.1
    kenan@kenan-desktop ~ $ ./a.out 
    Hello, Lua!
    ~ $ 
    ~ $ ldd ./a.out 
    	linux-vdso.so.1 =>  (0x00007ffd6c5d7000)
    	libluajit-5.1.so.2 => /usr/local/lib/libluajit-5.1.so.2 (0x00007f5ea238c000)
    	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5ea1fa5000)
    	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5ea1c9b000)
    	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5ea1a97000)
    	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5ea1881000)
    	/lib64/ld-linux-x86-64.so.2 (0x0000565491551000)
    
    

    再使用ldd命令查看,libluajit-5.1.so.2在/sur/local/lib下。

    使用静态链接

    对于运行时找不到动态库的问题,除了通过-Wl,-rpath指定路径外,还可以通过静态链接库的方式来解决。实际生产环境中通常只在一台机器上编译二进制程序,再将二进制程序分发到线上运行环境。程序需要的库可能实际线上环境中根本没有,也需要将库静态链接。

    静态链接库有下面几种方式。

    只保留静态库

    如安装luajit后,在/usr/local/lib下既有静态库,也有动态库。链接时优先链接动态库。如果将动态库删除,只保留静态库,这时链接器就会链接静态库.

    通过-Wl,-Bstatic对指定的库使用静态链接

    gcc会对-Wl,-Bstatic 后面的库使用静态链接。对-Wl,-Bdynamic后面跟的库使用动态链接。 如果需要对指定的库使用静态链接,其他的库使用默认的动态链接,可以这样用

    gcc test  -Wl,-Bstatic -lluajit-5.1 -Wl,-Bdynamic -lxxx -lxxx
    

    这样gcc会链接libluajit-5.1.a,而对其他库使用动态链接。

    使用 -static 避免动态链接

    gcc编译时使用-static参数,会阻止使用动态链接的方式。与之前两个方法不同,-static参数会导致gcc对所有的库使用静态链接,一般不推荐使用这种方式。

    ~ $ gcc test.c -I/usr/local/include/luajit-2.1 -Wl,-rpath=/usr/local/lib/ -L/usr/local/lib -lluajit-5.1 -ldl -lm -static
    ~ $ ldd ./a.out 
    	不是动态可执行文件
    

    对程序使用ldd命令提示不是动态可执行文件

    没有使用-static时ldd可以看到程序需要的动态库,以及库的路径。

    ~ $ gcc test.c -I/usr/local/include/luajit-2.1 -Wl,-rpath=/usr/local/lib/ -L/usr/local/lib -lluajit-5.1 -ldl -lm     
    ~ $ ldd ./a.out 
    	linux-vdso.so.1 =>  (0x00007ffd057f1000)
    	libluajit-5.1.so.2 => /usr/local/lib/libluajit-5.1.so.2 (0x00007f1e72a48000)
    	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1e7267f000)
    	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1e72375000)
    	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1e72171000)
    	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1e71f5b000)
    	/lib64/ld-linux-x86-64.so.2 (0x000055875c7a0000)
    

    使用 -static-libxxx对某些系统库进行静态链接

    gcc本身提供了参数可以只对libgcc,libstdc++等库进行静态链接 主要有下面这些

    -static-libgcc
    
    -static-libasan
    
    -static-libtsan
    
    -static-liblsan
    
    -static-libubsan
    
    -static-libmpx
    
    -static-libmpxwrappers
    
    -static-libstdc++
    

    更详细的介绍可以参见官方文档

  • 相关阅读:
    python的dict和set
    python基础之dict和set
    python基础之条件判断和循环
    mongodb安装和配置,遇到问题和解决方法
    mybatis12--一级缓存
    mybatis11--多对多关联查询
    mybatis10--自连接多对一查询
    mybatis09--自连接一对多查询
    mybatis08--关联查询多对一
    mybatis07--关联查询一对多
  • 原文地址:https://www.cnblogs.com/bigben0123/p/3304863.html
Copyright © 2011-2022 走看看