文章目录
前言
在学习muduo库的时候,想单独编译twisted的例子,发现尽然编译不通过,尝试确认库中已包括调用关系后,归档到文章链接: 动态库和静态库那些事中链接顺序问题。
编译
1. 头文件位置和muduo库位置。
root@ubuntu:/opt/muduo/examples/twisted/finger# ls -l ../../../include/
total 4
drwxr-xr-x 5 root root 4096 May 28 17:00 muduo
root@ubuntu:/opt/muduo/examples/twisted/finger# ls -l ../../../lib/*
-rw-r--r-- 1 root root 3201952 May 28 17:00 ../../../lib/libmuduo_base.a
-rw-r--r-- 1 root root 629644 May 28 17:00 ../../../lib/libmuduo_curl.a
-rw-r--r-- 1 root root 1462478 May 28 17:00 ../../../lib/libmuduo_http.a
-rw-r--r-- 1 root root 3180350 May 28 17:00 ../../../lib/libmuduo_inspect.a
-rw-r--r-- 1 root root 8347124 May 28 17:00 ../../../lib/libmuduo_net.a
-rw-r--r-- 1 root root 439544 May 28 17:00 ../../../lib/libmuduo_protobuf_codec.a
-rw-r--r-- 1 root root 1720140 May 28 17:00 ../../../lib/libmuduo_protorpc.a
-rw-r--r-- 1 root root 694410 May 28 17:00 ../../../lib/libmuduo_protorpc_wire.a
2.编译失败,篇幅有限,截取部分。
当前静态库链接顺序为:libmuduo_base.a
在前, libmuduo_net.a
在后
root@ubuntu:/opt/muduo/examples/twisted/finger# g++ -std=c++11 -o twisted_finger01 finger01.cc -I ../../../include/ ../../../lib/libmuduo_base.a ../../../lib/libmuduo_net.a -lpthread
../../../lib/libmuduo_net.a(EventLoop.cc.o): In function `muduo::net::EventLoop::handleRead()':
/opt/muduo-master/muduo/net/EventLoop.cc:250: undefined reference to `muduo::Logger::Logger(muduo::Logger::SourceFile, int, muduo::Logger::LogLevel)'
/opt/muduo-master/muduo/net/EventLoop.cc:250: undefined reference to `muduo::LogStream::operator<<(long)'
/opt/muduo-master/muduo/net/EventLoop.cc:250: undefined reference to `muduo::Logger::~Logger()'
3. 确认库中是否包含链接问题。
确认对应的库中包含了Logger符号,参考链接: nm和ldd用法,可以将nm使用strings替代更准确,确认库中含有Logger
符号
root@ubuntu:/opt/muduo/examples/twisted/finger# nm ../../../lib/libmuduo_base.a |grep Logger
00000000000008c0 T _ZN5muduo6Logger11setLogLevelENS0_8LogLevelE
00000000000008f0 T _ZN5muduo6Logger11setTimeZoneERKNS_8TimeZoneE
0000000000000090 T _ZN5muduo6Logger4Impl10formatTimeEv
00000000000005e0 T _ZN5muduo6Logger4Impl6finishEv
0000000000000360 T _ZN5muduo6Logger4ImplC1ENS0_8LogLevelEiRKNS0_10SourceFileEi
0000000000000360 T _ZN5muduo6Logger4ImplC2ENS0_8LogLevelEiRKNS0_10SourceFileEi
00000000000008e0 T _ZN5muduo6Logger8setFlushEPFvvE
00000000000008d0 T _ZN5muduo6Logger9setOutputEPFvPKciE
00000000000006e0 T _ZN5muduo6LoggerC1ENS0_10SourceFileEi
0000000000000830 T _ZN5muduo6LoggerC1ENS0_10SourceFileEib
0000000000000800 T _ZN5muduo6LoggerC1ENS0_10SourceFileEiNS0_8LogLevelE
0000000000000710 T _ZN5muduo6LoggerC1ENS0_10SourceFileEiNS0_8LogLevelEPKc
00000000000006e0 T _ZN5muduo6LoggerC2ENS0_10SourceFileEi
0000000000000830 T _ZN5muduo6LoggerC2ENS0_10SourceFileEib
0000000000000800 T _ZN5muduo6LoggerC2ENS0_10SourceFileEiNS0_8LogLevelE
0000000000000710 T _ZN5muduo6LoggerC2ENS0_10SourceFileEiNS0_8LogLevelEPKc
0000000000000880 T _ZN5muduo6LoggerD1Ev
0000000000000880 T _ZN5muduo6LoggerD2Ev
U _ZN5muduo6LoggerC1ENS0_10SourceFileEib
U _ZN5muduo6LoggerD1Ev
解决
1. 更换静态库链接顺序的位置。
即将libmuduo_base.a
放在libmuduo_net.a
之后。确认编译通过。
root@ubuntu:/opt/muduo/examples/twisted/finger# g++ -std=c++11 -o twisted_finger01 finger01.cc -I ../../../include/ ../../../lib/libmuduo_net.a ../../../lib/libmuduo_base.a -lpthread
root@ubuntu:/opt/muduo/examples/twisted/finger#
2. 使用Xlinker工具(推荐)
之所以推荐,是因为项目实际中使用的库比较多,这个时候如果更换位置尝试,会发现组合太多,效率低下。
g++ -std=c++11 -o twisted_finger01 finger01.cc -I ../../../include/ -Xlinker "-(" ../../../lib/libmuduo_base.a ../../../lib/libmuduo_net.a -Xlinker "-)" -lpthread
root@ubuntu:/opt/muduo/examples/twisted/finger#
注意:-Xlinker "-("
前缀和后缀和库有空格
思考和总结
- 链接顺序,做到A依赖B, 那么A放到前面,被依赖的B放到后面,很明显libmuduo_base.a是被依赖的库,所以放到后面规避。
- 使用
动态库
好像能规避这种链接顺序问题; - 对代码要求要非常熟悉,做到
高聚低耦
, 不要A库依赖B库,B库依赖A库。