我使用CppUTest来测试fornol.c
源文件中定义的C代码。该文件定义了主要生产main()
函数。
我还有一个AllTests.cpp
文件也有main()
函数,但main()
只能在运行单元测试时使用。
AllTests.cpp
被编译为.o
文件,而fornol.c
被编译为libfornol.a
档案。
然后CppUTest尝试将所有内容链接在一起,但这是我得到的内容:
Linking fornol_tests
cc -o fornol_tests objs/tests/AllTests.o objs/tests/FornolTests.o lib/libfornol.a ../../CppUTest/lib/libCppUTest.a ../../CppUTest/lib/libCppUTestExt.a -lstdc++ -lgcov
lib/libfornol.a(fornol.o): In function `main':
/home/dlindelof/Work/endor/nol/fornol/fornol.c:453: multiple definition of `main'
objs/tests/AllTests.o:/home/dlindelof/Work/endor/nol/fornol/tests/AllTests.cpp:4: first defined here
collect2: ld returned 1 exit status
好像main()
中定义并存档fornol.c
中的libfornol.a
功能与main()
中定义的AllTests.cpp
冲突。但我的理解是,只有当/或某个给定符号尚未被引用时,才会搜索存档/库文件。因此,如果所有定义都在归档/库文件中,则多次定义相同的符号应该不是问题。
我在这里做错了什么?
答案 0 :(得分:4)
您需要从main()
中移除AllTests.cpp
并将其放入自己的源文件中。
当链接器在库中链接时,它不能拆分库中的目标文件; 它必须链接或省略库中的每个目标文件作为一个单元。 (我知道LLVM是不同的,但这是另一个话题。)这就是为什么,如果你看一下像glibc这样的库的源代码,每个函数都会获得自己的源文件。
所以发生的事情是链接器需要从库(fornol.o
)中提取目标文件(libfornol.a
)以满足依赖性,但该目标文件带有用它复制符号(main
)。
将测试代码放在库中是完全可以的(我们常常在我工作的地方这样做),但是将它保存在自己的源文件中(我们传统上使用main.cc
)。 (无论如何,这是一个更好的测试,因为测试代码不应该访问static
- 声明的符号。)
答案 1 :(得分:0)
库应该没有main()函数,因为它是库。
你应该从fornol.c中删除那个main()并再次编译它。
main()是可执行文件源代码的入口点,因为库(特别是静态“.a”库)只是预编译的源代码,你不能在那里使用main。
如果你想要你的库的主要生产入口点你可以将fornol.c中的main()重命名为更明确和更少保留的东西,例如“fornolMain()”。
静态库在二进制可执行文件中编译,因此只有在加载符号时才会搜索。它与编译fornol.c并链接fornol.o和您的其他.o
完全相同