I have a library that has many different cpp test files.
They look like this, A.cpp
, B.cpp
, C.pp
, etc.
A.cpp:
#define BOOST_TEST_MODULE "C++ Unit Tests A"
#include<boost/test/unit_test.hpp>
#include <multi/array.hpp>
BOOST_AUTO_TEST_CASE(test_case_A1) {
...
}
B.cpp:
#define BOOST_TEST_MODULE "C++ Unit Tests B"
#include<boost/test/unit_test.hpp>
#include <multi/array.hpp>
BOOST_AUTO_TEST_CASE(test_case_B1) {
...
}
I have the following Cmake code to compile and test
include(CTest)
file(
GLOB TEST_SRCS
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
*.cpp
)
foreach(TEST_FILE ${TEST_SRCS})
set(TEST_EXE "${TEST_FILE}.x")
add_executable(${TEST_EXE} ${TEST_FILE})
target_link_libraries(${TEST_EXE} PRIVATE multi)
target_include_directories(${TEST_EXE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_include_directories(${TEST_EXE} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS} )
target_link_libraries (${TEST_EXE} PRIVATE Boost::unit_test_framework )
endforeach()
The problem with this is that each test takes sometime to compile. I know that if I merge all these cpp files it will compile much faster overall.
(For example, I have 40 cpp test files, each takes 10 second, total compilation is 400 second. If I merge all it takes perhaps 20 seconds. Even if I could parallelize the build of individual files a 20x factor is hard to achieve. Obviously the compiler is doing a lot of repeated work. Supposedly gch pre-compiled headers would help but I never figured out how to use them with cmake).
Is there a way to force the compilation of these test to work on a single merged file?
I tried replacing the loop with this:
add_executable(multi_test ${TEST_SRCS})
add_test(NAME multi_test COMMAND ./multi_test)
target_include_directories(multi_test PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_include_directories(multi_test SYSTEM PRIVATE ${Boost_INCLUDE_DIRS} )
target_link_libraries (multi_test PRIVATE Boost::unit_test_framework )
However, it still has two problems: First, it is still slow to compile because each cpp is used to generate individual .o files (later link into the same executable). The second problem is that each .o will contain a main function (defined by Boost.Test) and therefore there will be a linker error.
Is there a change I can make to make to compile several cpp files as if it was a single cpp file? (I would like to avoid generating a temporary merged file manually) Is there a Boost.Test flag that can help me with this?
I would like a solution where each test source file can still be compiled into its own executable.
As an illustration, I was able to do this process to obtain a single file.
echo '#define BOOST_TEST_MODULE "C++ Unit Tests for Multi, All in one"' > ../test/all.cpp # Boost Test need a module name
cat ../test/*.cpp | grep -v BOOST_TEST_MODULE >> ../test/all.cpp # filter macros to avoid warnings