1

I'm trying to make an application that runs some unit tests using GoogleTest but the tests in the test files outside of the main file are not discovered by GoogleTest.

I have 2 test files:

main_test.cpp:

#include <gtest/gtest.h>

TEST(MainTest, Test1) {
  EXPECT_EQ(1,1);
}

int main(int argc, char* argv[]) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

external_test.cpp:

#include <gtest/gtest.h>

TEST(ExternalTest, Test1) {
  EXPECT_EQ(1,1);
}

ExternalTest is never discovered and run when I try and build with my build system.

These are the commands that my build system uses to build this app and it seemingly optimizes out the functions in external_test.cpp:

clang++ -c googletest/googletest/src/gtest-all.cc -o build/gtest -Igoogletest/googletest/include/ -Igoogletest/googletest/ -std=c++17
clang++ -c external_test.cpp -o build/external_test -Igoogletest/googletest/include/ -Igoogletest/googletest/ -std=c++17
clang++ -c main_test.cpp -o build/main_test -Igoogletest/googletest/include/ -Igoogletest/googletest/ -std=c++17

cd build

libtool -o test_app.lib main_test gtest external_test
clang++ test_app.lib

Result:

./a.out
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MainTest
[ RUN      ] MainTest.Test1
[       OK ] MainTest.Test1 (0 ms)
[----------] 1 test from MainTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

If I build like so:

clang++ -c googletest/googletest/src/gtest-all.cc -o build/gtest -Igoogletest/googletest/include/ -Igoogletest/googletest/ -std=c++17
clang++ -c external_test.cpp -o build/external_test -Igoogletest/googletest/include/ -Igoogletest/googletest/ -std=c++17
clang++ -c main_test.cpp -o build/main_test -Igoogletest/googletest/include/ -Igoogletest/googletest/ -std=c++17
cd build
clang++ external_test gtest main_test

I get the expected result:

./a.out
[==========] Running 2 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from ExternalTest
[ RUN      ] ExternalTest.Test1
[       OK ] ExternalTest.Test1 (0 ms)
[----------] 1 test from ExternalTest (0 ms total)

[----------] 1 test from MainTest
[ RUN      ] MainTest.Test1
[       OK ] MainTest.Test1 (0 ms)
[----------] 1 test from MainTest (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 2 test suites ran. (0 ms total)
[  PASSED  ] 2 tests.

But our build system needs to generate the lib file and then link. Also, if I create some function foo in external_test.cpp, and then declare that function as extern in main_test.cpp and call it in the main function - then all tests are discovered correctly.

My theory is that libtool and clang++ somehow preform some link time optimization and remove the tests. I've tried adding the -fno-lto flag to no avail.

Does anyone have any ideas? Any help would be greatly appreciated.

user4581301
  • 33,082
  • 7
  • 33
  • 54
Adam Bujak
  • 63
  • 7
  • I see, unfortunately we want to include these tests in our existing build system without cmake - is there any workaround? – Adam Bujak Feb 02 '23 at 01:47
  • @273K: I don’t think it’s `libtool` that’s at fault here—it’s just the usual [object-at-a-time behavior](https://stackoverflow.com/q/54126641/8586227) of static libraries. – Davis Herring Feb 02 '23 at 01:53

1 Answers1

2

Try this command

clang++ -Wl,--whole-archive test_app.lib -Wl,--no-whole-archive

It will prevent discarding global initializers, that register test suites.

Try this on macOS

clang++ -Wl,-all_load test_app.lib
273K
  • 29,503
  • 10
  • 41
  • 64