I ran into a stupid problem with C++ and googletest.
I set up a C++ project with CMake, and included googletest for writing tests. As usual, I created a library, and respecive test executable:
add_library(mylib mylib.cc)
...
add_executable(test-mylib test-mylib.cc)
...
target_link_libraries(test-mylib mylib gtest gtest_main)
...which is the typical recommended way to write test executables. You only need to write
the TEST()
fixtures in your code, and use the provided main()
function from library gtest_main
.
The provided main()
discovers the tests automatically and runs them. Nice and easy!
However, this time something weird happened. The build was successful (-DCMAKE_BUILD_TYPE=Debug
), but the resulting binary produced no output. The executable didn't respond to -h
or --help
arguments, like you would expect. Really strange.
Then I noticed the test binary (test-mylib
) was a not actually an executable:
$ file ./test-mylib
test/test-mylib: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, ...
What on earth is going on??? I deleted the build tree, disabled ccache
from my configuration and tried again.
No luck. Not a single warning or error in the build log.
I began investigating the build commands (make VERBOSE=1
), in case there was a configuration issue. Then double checked all CMakeLists.txt files, but all of them were correct. Libraries were defined with add_library()
, exectuables were defined with add_executable()
. The final compiler invocation command contained was what you'd expect, without any suspicious flags; i.e no -shared
or anything like that.
I googled wether there was a bug in CMake. But nothing came up. I reverted googletest to previous known good release. Tried another host with newer CMake version and compilers.
No change.
Luckily, I had an epiphany. I realized I had an extra dummy main()
definition in mylib.cc;
a leftover from experiments before CMake and googletest integration. Sigh. No wonder the test
program didn't work, it somehow used the wrong main()
!
I wrote this in case you come across a this problem. Although really should not be a problem.
Why does the linker NOT warn you about this? I hypothesize gtest_main
does some clever tricks during runtime and uses the user defined main()
if it exists... Whatever the reason is, it is silly. This is a really easy footgun to create; how would you detect that your tests are actually running? If you are only looking the test executable return value - you are fucked.