3

我正在使用 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.clibfornol.amain()AllTests.cpp

我在这里做错了什么?

4

2 回答 2

4

您需要删除main()fromAllTests.cpp并将其放入自己的源文件中。

当链接器链接到库中时,它不能拆分库中的目标文件;它必须将库中的每个目标文件作为一个单元链接或省略。(我知道 LLVM 是不同的,但这是另一个话题。)这就是为什么如果你查看像 glibc 这样的库的源代码,每个函数都有自己的源文件。

所以发生在你身上的是链接器需要fornol.o从库 ( ) 中拉入一个目标文件 ( libfornol.a) 以满足依赖关系,但该目标文件带有一个重复的符号 ( main)。

将测试代码放在库中是完全可以的(我们通常在我工作的地方这样做),但将其保存在自己的源文件中(我们传统上使用main.cc. (无论如何,这是一个更好的测试,因为测试代码不应该访问static-declared 符号。)

于 2012-02-03T13:15:48.693 回答
0

一个 library 不应该有一个 main() 函数,因为它是一个library

您应该从 fornol.c 中删除 main() 并再次编译它。

main() 是可执行文件源代码的入口点,因为库(尤其是静态“.a”库)只是预编译的源代码,因此不能在其中使用 main。

如果您想要库的主要生产入口点,您可以将 fornol.c 中的 main() 重命名为更明确且更少保留的名称,例如“fornolMain()”。

静态库在您的二进制可执行文件中编译,因此仅在加载符号时才搜索。它与编译 fornol.c 并链接 fornol.o 和您的其他 .o 完全相同

于 2012-02-03T13:09:07.983 回答