3

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?

lindelof
  • 34,556
  • 31
  • 99
  • 140

2 Answers2

4

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.)

Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
  • I did not split `AllTests.cpp` but split `fornol.c` into a `main.c` part that had the `main()` function and `fornol.c` which held everything else, and that helped to some extent. The `libfornol.a` archive is now composed of two `.o` files and I can use a `main()` function from `AllTests.cpp`. But what I don't understand now is that gcc lets me override, in `AllTests.cpp`, functions that are still defined in `fornol.c`. So why would `main()` be treated differently? – lindelof Feb 03 '12 at 13:56
  • You misunderstand the linker. It does not think in terms of functions or overriding. It think in terms of finding missing symbols. Each object file has a list of symbols it provides and symbols it needs. The linker first goes through the object files given to it and matches up symbols provided by one object file with those needed by another. When it's done with that, it has a list of still-missing symbols, and it goes through each library in order, looking for objects which provide those symbols. But if an object that provides a symbol also provides a symbol that is already provided, it fails. – Mike DeSimone Feb 03 '12 at 14:08
  • There is nothing special about 'main'; the same could happen for 'printf'. The linker continues this process until it hits an error or it has no more needed symbols. – Mike DeSimone Feb 03 '12 at 14:10
  • Oh I think I grok it now. Thanks for clarifying the fact that an object file is either wholly linked or not at all. Are there any resources you might recommend where I could read more about how linking works? – lindelof Feb 07 '12 at 05:17
  • The GNU `ld` documentation is all I can think of. That's where I read up on this a decade ago. One thing I forgot to mention: GCC has an option (`-ffunction-sections`, IIRC) that puts each function in separate "sections" in the object file. Passing a similar flag to the linker allows it to use section granularity instead of object file granularity. This works for both object files and libraries. – Mike DeSimone Feb 07 '12 at 14:26
0

A library is supposed not to have a main() function as it is a library.

You should remove that main() from fornol.c and compile it again.

main() is the entry point of an executable file's source code, since a library (especially a static ".a" library) is only pre-compiled source code, you cannot use a main in there.

If you want a main production entry point of your library you could rename the main() in fornol.c to something more explicit and less reserved such as "fornolMain()" for example.

A static library is compiled in your binary executable and thus is not searched only if the symbol is loaded. It is exactly the same as compiling fornol.c and linking fornol.o and your other .o

Eregrith
  • 4,263
  • 18
  • 39