I'm using CppUTest to test the C code defined in a fornol.c
source file. That file defines the main production main()
function.
I also have an AllTests.cpp
file that also has a main()
function, but that main()
is supposed to be used only when running the unit tests.
AllTests.cpp
gets compiled to a .o
file, whereas fornol.c
gets compiled to a libfornol.a
archive.
Then CppUTest tries to link everything together, but here is what I get instead:
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
It looks as if the main()
function defined in fornol.c
and present in the archive libfornol.a
conflicts with the main()
defined in AllTests.cpp
. But my understanding was that archive/library files are searched only if/when a given symbol hasn't been referenced yet. It should therefore not be a problem to have the same symbol defined more than once, provided all definitions are in archive/library files.
What am I doing wrong here?
You need to remove the main()
from AllTests.cpp
and put it in its own source file.
When a linker links in a library, it can't split object files in the library; it has to either link or omit each object file in the library as a unit. (I know LLVM is different, but that's another topic.) This is why, if you look at the source for a library like glibc, each function gets its own source file.
So what's happening to you is that the linker needs to pull in an object file (fornol.o
) from the library (libfornol.a
) to satisfy dependencies, but that object file carries a duplicate symbol with it (main
).
It's perfectly okay to put test code in a library (we do this routinely where I work), but keep it in its own source files (we traditionally use main.cc
). (This is a better test anyway, because test code should not have access to static
-declared symbols.)