动态库编译详解

动态库编译详解:

当前类介绍: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可以解决一切编译运行问题.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容