2014年3月26日星期三

gcc (g++) 编译时只链接静态库

为啥编译时要只链接静态库呢?链接动态库时,编译后的程序需要目标机器安装对应的动态库。链接静态库就不存在这个问题了。而且有时候链接的动态库还依赖于其他动态库,只要有一个版本不对就抓虾了。
今天就碰到这样的一个问题:我们的程序使用了google protocol buffers库,在开发机器上(suse 10)安装了pb库,编译正常,程序运行也正常。但是在测试机器上就有问题了。首先在测试机器上安装了pb库,安装顺利,运行pb库的make check也显示所有测试通过。但是运行时提示: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.10' not found (required by /usr/lib64/libprotobuf.so.8),然后我把开发机器上的 libstdc++.so.6 拷贝过来,还是不行。这就抓瞎了(后来发现了错误,libstdc++.so.6只是一个软链接,链接到libstdc++.so.6.0.8这个文件的。所以我只是拷贝了一个软链接!)
当时时间比较急,所以就把程序重新用pb的静态库文件编译了。这里大概总结一下链接只链接静态库的方法。
1.gcc (g++) 编译选项里面 -l 选项是默认先链接动态库的,所以我一开始用 -lprotobuf 选项链接的都是 libprotobuf.so.8 这个库。
2.要只链接静态库 libprotobuf.a 这个文件的话,可以直接写死静态库路径(相当与把静态库当作.o文件来使用),比如:g++ /usr/local/lib/libprotobuf.a -o myserver,或者用 g++ -o myserver /usr/local/lib/libprotobuf.a 也可以。同时把原来的-lprotobuf选项去掉,这样就可以了。最后链接完成后,用ldd myserver就可以看到程序里面已经没有pb的动态库了。
3.可以把libprotobuf.a文件拷贝到makefile的搜索路径里面。比如我的搜索路径设置为当前的./lib目录,然后就把libprotobuf.a拷贝到这个目录里面。(这个方法其实还是有问题的,有时候链接的还是动态库
4.最好的办法:使用-Wl,-Bstatic选项。在要链接的库文件前加入这个选项,可以强制链接静态库。比如我的makefile最后就写成这个样子:
-Wl,-Bstatic -lprotobuf -Wl,-Bdynamic -lgcc_s
-Wl,-Bstatic -lprotobuf 即强制链接libprotobuf.a
-Wl,-Bdynamic -lgcc_s 这个是因为需要gcc_s的动态库,所以在前面加了一个使用动态库的选项。
5.-static选项:这个选项是全局的,一旦用了就要求全部链接静态库。

2 条评论:

  1. 5.-static选项:这个选项是全局的,一旦用了就要求全部链接动态库。

    -static 是禁止动态链接啊

    回复删除