简单的说,就是
g++ A.o B.o C.o -o a.out
和
ar rv libpack.a A.o B.o
g++ C.o libpack.a -o a.out
或者
ar rv libpack.a A.o B.o
g++ C.o -o a.out -lpack
有什么区别,对最终的行为有什么影响?
我只知道.a就是多个.o打个包,然后加个索引之类,但是在输送给g++的时候,有什么影响?
下面是背景,有点长:
使用google test框架写单元测试。
使用的方案是将具体的test 和 所有的test的单一入口main分开。
也就是:
main.cpp:
#include "gtest/gtest.h"
int main(int argc, char* argv[]){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
testxxx.cpp,有好多个
#include "testedClass.h"
#include "gtest/gtest.h"
TEST(xxx, yyy){
...
}
...
按照正常流程,将每个cpp编译为对象文件*.o
,然后全部link起来就可以得到一个可执行文件,运行之后,执行各种test,然后pass,没什么问题。
main.cpp显然是通过gtest.h得知其他各种test的存在,然后调用。也就是TEST语句等于是在gtest中注册了一个回调。
============ 异常出现 ===============
现在换了一种方法
将各种testxxx.o打包成libtest.a
然后
g++ main.o libtest.a -o test
当然还有许多链接库,先省略吧。
结果就是,程序链接成功,但是运行之后,gtest直接认为没有注册的test,直接pass返回。也就是和没写test一样。
为了验证是不是打包的时候丢失了信息,特地还将.a重新解开,然后链接。这样操作就没有任何问题了,挨个test,然后pass。
================================
所以说,到底是哪里出问题了,还是google test本身实现的缺陷。
各位大侠给小弟解个惑吧!!
问题已经解决了。
链接器在处理
.a
文件的时候,会自动忽略那些没有被引用的项,以保证链接结果中没有太多无用的代码而在处理
.o
文件的时候,则是你给它什么就链接什么gtest的使用并没有使用显式的引用,因此会被链接器忽略。gtest具体是如何找到测试用例的就不清楚了,需要看源代码吧。
对这个问题的解决方案有两种:
一开始就不要生成
.a
把
.a
解开,用一堆.o
代替在链接TEST的
.a
时,用这个选项-Wl,--whole-archive libtest.a
,它可以强制引入libtest.a
中的所有符号