美文网首页
动态库编译详解

动态库编译详解

作者: 放纵的卡尔 | 来源:发表于2022-02-21 01:27 被阅读0次

    动态库编译详解:

    当前类介绍:upper.c ( upper) 依赖于 bottom.c(play)

    1.生成一个动态库

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c upper.c bottom.c -I ./include/
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./ -lplay -Wl,-rpath ./,ypa
    gcc: error: ./,ypa: 没有那个文件或目录
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./ -lplay -Wl,-rpath ./mypath
    

    2.运行程序并且链接动态库

    说明:当执行可执行程序的时候,需要去/lib. /user/lib下和LD_LIBRARY_PATH下寻找so.并不会在当前目录下寻找.

    所以执行./main.out会报错.如下:

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    ./main.out: error while loading shared libraries: libplay.so: cannot open shared object file: No such file or directory
    
    

    解决方案:指定.so运行搜寻路径

    1.-Wl,-rpath ./mypath 加入参数,并且将libplay.so copy到./mypath目录下.

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ cp libplay.so ./mypath/
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    

    2.设置LD_LIBRARY_PATH,指定目录.

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ cd mypath/ && rm libplay.so 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    
    

    说明:指定了-Wl,-rpath, 设置LD_LIBRARY_PATH也是可以生效的.并不是说只会去-Wl,-rpath下寻找.

    3.动态库链接静态库

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c upper.c bottom.c -I ./include/  
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ar rcs -o libbottom.a bottom.o
    
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared  upper.o   -o libplay.so -L ./ -lbottom 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./ -lplay  -I ./include/  -Wl,-rpath ./
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    
    

    4.动态库依赖传递的情况

    首先生成一个bottom.so,然后用upper.so去依赖bottom.so, 然后main.c 再去依赖upper.so.

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c *.c -I ./include/ &&rm main.o 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libbottom.so bottom.o 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so upper.o -L ./ -lbottom 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
    /usr/bin/ld: warning: libbottom.so, needed by libplay.so, not found (try using -rpath or -rpath-link)
    /usr/bin/ld: libplay.so: undefined reference to `play'
    collect2: error: ld returned 1 exit status
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    
    

    说明:这里编译的时候直接出错,是因为没有指定搜寻路径,所以无法通过编译.

    解决编译问题方案.

    1.我们依然采用LD_LIBRARY_PATH的方式可以解决编译和运行的问题.

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    

    2.生成libplay的时候,直接指定-Wl,-rpath 给libbottom.可以解决编译不通过的问题.

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so upper.o -L ./  -Wl,-rpath ./  -lbottom  
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ldd libbottom.so 
        linux-vdso.so.1 (0x00007fff45ae3000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd501ef3000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fd502102000)
    
    指定了rpath,在去执行./main.out,此时还需要设置libplay.so 的运行路径,加入rpath=./
    
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    ./main.out: error while loading shared libraries: libplay.so: cannot open shared object file: No such file or directory
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  -Wl,-rpath ./
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    

    3.依赖所有库

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  libbottom.so
    
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c *.c -I ./include/
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libbottom.so bottom.o 
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so  upper.o   -L ./ -lbottom 
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./   libplay.so  libbottom.so 
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    ./main.out: error while loading shared libraries: libplay.so: cannot open shared object file: No such file or directory
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./   libplay.so  libbottom.so  -Wl,-rpath=./
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    ./main.out: error while loading shared libraries: libbottom.so: cannot open shared object file: No such file or directory
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
    yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    
    

    依赖所有库只能解决编译问题,无法处理运行的路径.

    另一种思路:我们在执行main.out的时候 执行-Wl,-rpath.并不在生成libplay的时候指定,看下是否正常.

    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so upper.o -L ./  libbottom.so 
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  
    /usr/bin/ld: warning: libbottom.so, needed by libplay.so, not found (try using -rpath or -rpath-link)
    /usr/bin/ld: libplay.so: undefined reference to `play'
    collect2: error: ld returned 1 exit status
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  -Wl,-rpath ./
    yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    ./main.out: error while loading shared libraries: libbottom.so: cannot open shared object file: No such file or directory
    

    由此可见,-Wl,-rpath 只能针对直接依赖的libplay.so指定了路径,但是libbottom还是无法查找到 .但是LD_LIBRARY是可以的.

    rpath只能对直接依赖的so设置搜寻目录,并且可以设置所有依赖的编译路径.

    总结: 解决编译问题,在生成libplay的时候指定-Wl,-rpath运行路径,或者设置LD_LIBRARAY_PATH,都可以解决这个问题.

          或者直接依赖所有的.so,但是这样是不合理的,我们不需要去依赖间接的依赖.
    

    5.动态库依赖

    当我们现在拥有的so包含一个直接依赖的so和很多间接依赖的so,但是没有设置rpath.所以是不能直接依赖主so进行编译和运行的.

    为了通过编译:

    1.在只链接主so的情况下可以去设置rpath或者LD_LIBRARY_PATH.

    2.或者链接所有so.

    为了通过运行:

    为了正常运行可以设置LD_LIBRARY_PATH.

    6.如果我们想只去依赖一个直接so,并且不让使用方主动去设置LD_LIBRARY_PATH就可以直接运行程序,还有一种方式:

    --disable-new-dtags,--copy-dt-needed-entries

    yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=
    yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -Wl,-rpath=./,--disable-new-dtags,--copy-dt-needed-entries -L ./ -lplay
    yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
    Hello, World!
    Bottom--->底层的播放功能
    Upper---->上层的封装能力
    yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ 
    
    

    结论概述:

    1.我们在生成间接依赖的库的时候,为了保证其他库可以直接依赖,需要加入-Wl,-rpath.保证编译通过.

    2.LD_LIBRARY_PATH可以解决一切编译运行问题.

    相关文章

      网友评论

          本文标题:动态库编译详解

          本文链接:https://www.haomeiwen.com/subject/yjsblrtx.html