Adam Bujak
Adam Bujak

Reputation: 143

My build system is optimizing out my google test functions

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.

Upvotes: 1

Views: 223

Answers (1)

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38883

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

Upvotes: 2

Related Questions