最近在编译工程时遇到一些,动态库链接依赖的问题,现总结出来,以作备忘。
1、自己编写的动态库依赖系统库(如pthread库),可执行程序链接自己的库后找不到系统库(pthread)中的函数:
自己动态库的编译命令如下:
(1)g++ -fPIC -g -O0 -Wall -I//usr/include -L//usr/lib -L//lib -lpthread -lrt-shared -o libhmlpmanager_service.so hmlp_IF.o hmlp_device.o hmlp_manager.o hmlp_noticeData.o hmlp_package.o hmlp_socket.o-L ../../../../mw/hmlp/build/lib -lcommon
可执行程序编译命令如下:
(2)g++ -g -O0 -Wall -I//usr/include -o ../../mw/hmlp/build/bin/Hmlp_client -L//usr/lib -L//lib -L../../mw/hmlp/build/lib -lhmlptest -lhmlpmanager_service -lcommon
编译可执行程序时报错:../../mw/hmlp/build/lib/libhmlpmanager_service.so: undefined reference to `pthread_create'
在动态库编译过程中明明已经添加了pthread库,并且动态库也编译成功了,为什么在使用动态库的时候会报找不到`pthread_create'的错误呢?
使用ldd命令查看编译的动态库对其他库的依赖:
(3)ldd libhmlpmanager_service.so
linux-gate.so.1 => (0xb7784000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb7677000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7659000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb74ad000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7481000)
/lib/ld-linux.so.2 (0xb7785000)
发现里面没有pthread库。
将上面(1)中的编译命令改为:g++ -fPIC -g -O0 -Wall -I//usr/include -shared -olibhmlpmanager_service.sohmlp_IF.o hmlp_device.o hmlp_manager.o hmlp_noticeData.o hmlp_package.o hmlp_socket.o-L ../../../../mw/hmlp/build/lib -lcommon-L//usr/lib -L//lib -lpthread -lrt
即红色字体部分移到后面,再次进行编译,竟然编译通过了!
原来在(1)中指明了依赖的pthread库的地址,在编译libhmlpmanager_service.so库时使用到的pthread函数都可以在pthread中找到,所以并不报错,但是pthread库中的类容并没有编译进libhmlpmanager_service.so库中(ldd命令查看结果可以证明),所以在编译可执行程序的链接过程中,找不到libhmlpmanager_service.so库中所要使用的pthread中的函数。
将(1)中的编译命令进行修改后,将pthread的类容也编译进了libhmlpmanager_service.so中,所以就不会报错,此时使用ldd得到的结果如下:
ldd libhmlpmanager_service.so
linux-gate.so.1 => (0xb77ae000)
libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb776b000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb7686000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7667000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb74bc000)
/lib/ld-linux.so.2 (0xb77af000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7490000)
2、自己编写的动态库A依赖自己编写的动态库B,可执行程序C依赖动态库A:
在编译A时使用:-L $(动态库B的路径) lB,指明连接的动态库B,编译OK
在编译C时使用:-L $(动态库A的路径) lA,指明连接的动态库A,编译NG,报错找不到动态库B中的函数;
使用ldd查看动态库A的依赖时,动态库B的后面没有地址,而是not found。
原来,因为-L选项指定的路径只在编译时有效,编译出来的动态库A不知道-L选项后面的值,当然找不到。
既然找到了原因那么如何解决呢?解决方法是通过-Wl,rpath=<your_lib_dir>,使得编译出的库记住链接库的位置。
-Wl选项告诉编译器将后面的参数传递给链接器。