linux编译链接注意事项

一、两个动态库函数重名问题

参考:gcc链接动态库时,两个动态库中符号重名的问题_山中岁月的博客-CSDN博客_动态库 重名

1、liba.so和libb.so中均定义了func()

gcc main.c -L. -la -lb -o main,则调用的是liba.so中的函数实现

gcc main.c -L. -lb -la -o main,则调用的是libb.so中的函数实现

总结:gcc在链接时,如果有一个动态库模块定义了某个符号,那么后面其他动态库中同名符号都会被忽略!

2、将func()函数改成static,那么两个库中的func()也不会冲突,因为静态函数只能被本模块引用

3、将liba和libb制作成静态库,那么在链接时就会报符号重定义的错误

二、依赖动态库的动态库链接问题

参考:动态库依赖动态库是的链接方式_eRemember的博客-CSDN博客_动态库依赖动态库方法

1、libfun.so依赖动态库libtest.so(libfun.so动态库里的函数intnothing()调用了libtest.so里的intmytest()函数),而main.exe又调用了libfun.so的函数int nothing()。

下面两种方式都能工作:

(1) 常用的方式

g++ -shared -fPIC -o libtest.so test.cpp

g++ -shared -fPIC -o libfun.so function.cpp  -L./ -I./ -ltest ---这里ldd能看到libfun.so依赖libtest.so(用ldd时可能要先在libfun.so所在目录执行下export LD_LIBRARY_PATH=./)

g++ -o main.exe main.cpp -L./ -I./ -lfun    ---编译libfun.so的时候已经指定了依赖libtest.so,这里就不需要再指定了(main.exe运行时需要将libfun.so和libtest.so均导入到设备)

(2) 不常用的方式

g++ -shared -fPIC -o libtest.so test.cpp

g++ -shared -fPIC -o libfun.so function.cpp    ---这里ldd可知,libfun.so没有依赖libtest.so

g++ -o main.exe main.cpp -L./ -I./ -lfun -ltest ---因为编译libfun.so的时候没有指定它依赖libtest.so,所以要加上-ltest

从(2)可知,linux下面生成动态库的时候,即使动态库里有没有定义的函数,在编译链接的时候,默认不会提示错误,是能通过的。但是,当可执行文件在链接这个有未定义函数的动态库的时候则会报错。

注意:经过测试发现,无论是在静态库或是动态库中,都可以只声明一个函数而不定义此函数,但是在库中可以调用此未定义的函数,生成库的时候都能成功。然后在用到此静态库或是动态库的可执行程序里定义此函数,编译链接好此可执行程序后运行,发现运行时库中调用的此函数的实现正是可执行程序中定义的函数体(类似回调函数的特性),若主程序代码里也未定义该函数,则编译时找不到该符号的定义链接器ld就会报undefined reference to 'xxx_function'错误。

2、静态库下的链接

a.o依赖b.o中的函数定义,下面两种方式都能工作:

(1) a.o和b.o生成一个静态库(常用)

gcc -c a.c b.c

ar -r liba.a a.o b.o

gcc main.c -L. -la -o main

(2) a.o和b.o分别生成两个静态库(不常用)

gcc -c a.c b.c

ar -r liba.a a.o

ar -r libb.a b.o

gcc main.c -L. -la -lb -o main

三、依赖库链接顺序

1、依赖的库放在后面,如libssl.a依赖libcrypto.a,则编译应用程序时要把libssl.a放在libcrypto.a前面

LIB += ******* -L./lib -lssl -lcrypto -ldl

四、动态链接和静态链接的个人理解

参考:https://blog.csdn.net/nodeathphoenix/article/details/9982209?spm=1001.2014.3001.5506

1、动态链接

阶段一:动态函数库在编译的时候并没有被编译进目标代码中,在编译链接生成可执行文件阶段通过-l指令告诉编译器所依赖的动态库,即指定了目标文件对需要的动态库的依赖关系(通过ldd目标文件可查看依赖关系),如果在动态库和目标程序代码中都找不到某个函数符号的定义,则链接器ld会报undefined reference to 'xxx_function'错误

阶段二:当可执行文件加载(可执行文件复制到内存)完成后,在程序开始运行之前,操作系统就会查找可执行文件依赖的动态库信息,即依据第一阶段给的链接信息进行动态库的查找以及符号决议(这阶段需要export LD_LIBRARY_PATH修改查找目录)。 找到该动态库后就将该动态库从磁盘加载到内存,如果这个过程没有问题,那么程序开始运行。参考:https://blog.csdn.net/qq_33726635/article/details/111440595

2、静态链接

静态库只是一堆object对象的集合,使用ar命令可以将编译产生的.o文件打包成.a静态库。
生成静态库只有编译,而没有链接;而动态库在生成的时候时既有编译的动作也有链接的动作。

静态库在被别的程序(可执行程序或是动态库)链接的时候,链接器会将程序中使用到函数的代码从静态库文件中拷贝到应用程序中的。

静态库生成时是没有链接的,所以生成它的时候不需要指定它所依赖的外部库(即可以只声明不定义函数,当然在编译最终的可执行文件调用此静态库时需要链接该静态库所依赖的库?);动态库生成时是有链接动作的,故需要指定它依赖哪些外部库

3、动态库和静态库相互依赖

如1中所述,如果一个动态库依赖一个动态库,则该动态库是会知道它所依赖的动态库的。那么,如果一个动态库依赖一个静态库呢?这时,在生成这个动态库时,它就会将静态库的代码拷贝到动态库程序中的。例如, liba.so 依赖 libb.a, 则在生成liba.so时必须要在makefile中指定依赖静态库libb.a,且要指定libb.a为查找目录。同时如果可执行程序c.out依赖liba.so,则a.out只需要指出它依赖动态库liba.so就可以了,a.out不需要再去链接静态库libb.a了。

还有,一个静态库依赖一个静态库 / 动态库呢? 因为如上所述,生成静态库的时候它是没有链接动作的,所以不需要指定它所依赖的外部静态库或是动态库。那么你也许要问了,没有指定依赖,那静态库引用的外部库中的函数怎么办呢? 在程序链接静态库的时候,它会去扫描该静态库中哪些未解析符号,然后会在其它的指定静态库或目标文件(动态库或是main函数所对应.o文件)中去扫描看是否有此未解析的符号,如果有,则链接到此对应的定义。所以,只要在链接静态库的地方再去指定链接该静态库的依赖库就可以了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值