我有以下源代码:
然后我运行以下命令来生成 foo.cpp 的静态版本和共享版本:
g++ -c -fPIC foo.cpp
ar rvs libfoo.a foo.o
g++ -shared -o libfoo.so foo.o
g++ -c main.cpp
如果我尝试使用静态生成可执行文件libfoo.a
and main.o
,目标文件和库文件的顺序很重要:
g++ main.o libfoo.a -o main # works
g++ libfoo.a main.o -o main # fails with undefined references to `foo()`
正如中所解释的这个帖子,顺序很重要。
但是,如果我尝试使用共享构建可执行文件libfoo.so
and main.o
,目标文件和库文件的顺序不再重要:
g++ main.o libfoo.so -o main # works
g++ libfoo.so main.o -o main # also works without errors
这是否意味着当我们链接目标文件和共享库时顺序并不重要?或者这只是一个特例或我不知道的巧合?
上述代码和命令在以下平台测试:
- Linux:CentOS 7.4
- gcc:7.3.1 或 4.8.5(均已测试)
正如这篇文章中所解释的,顺序很重要。
更详细的解释是here.
订单很重要传统的UNIX 链接器,但最近 LLD 决定打破传统,记录存档库中符号的可用性,即使它们没有立即引用。
目前,Linux 上提供三种不同的链接器:原始 BFD 链接器、Gold 链接器(大约 2008 年)和 LLD(大约 2019 年)。
使用“正确”的顺序对所有三个都成功(自然)。
使用“错误”的顺序:g++ libfoo.a main.o
BFD 和 Gold 失败,但 LLD 成功:
g++ libfoo.a main.o -fuse-ld=lld && echo $?
0
但是,如果我尝试使用共享的 libfoo.so 和 main.o 构建可执行文件,则目标文件和库文件的顺序不再重要
The reason it doesn't matter is that linkers treat .so
similarly to how they treat .o
. In particular, there is no need to "pull out parts" of .so
-- you get the entire .so
(just as you would1 if you used foo.o
)
所以当你链接时g++ libfoo.so main.o
,这个链接是almost相当于使用g++ foo.o main.o
,并且前一个命令中的顺序无关紧要,其原因与后一个命令中的顺序无关紧要相同。
1Building with -ffunction-sections
and using --gc-sections
notwithstanding.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)