CppUnit and CMake: .cpp files compiled twice

I am currently using CMake to create my project and CppUnit to test it. In my CMake file, I create two executables. sample is the compiled source itself. And with sample_test I run tests. If i r

Here is part of my CMakeLists.txt

 SET(SAMPLE_ROOT_PATH ${PROJECT_BINARY_DIR}) SET(SAMPLE_SOURCE_PATH ${SAMPLE_ROOT_PATH}/src) SET(SAMPLE_TEST_SOURCE_PATH ${SAMPLE_ROOT_PATH}/test) SET(SAMPLE_BIN_PATH ${SAMPLE_ROOT_PATH}/bin) SET(SAMPLE_EXEC_NAME sample) SET(SAMPLE_TEST_EXEC_NAME sample_test) SET(EXECUTABLE_OUTPUT_PATH ${SAMPLE_BIN_PATH}) FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp) FILE(GLOB_RECURSE SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_PATH}/*.cpp) SET(SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_FILES} ${SAMPLE_SOURCE_FILES} ) LIST(REMOVE_ITEM SAMPLE_TEST_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/main.cpp) SET(CMAKE_CXX_FLAGS "-g -Wall") ADD_EXECUTABLE(${SAMPLE_EXEC_NAME} ${SAMPLE_SOURCE_FILES}) ADD_EXECUTABLE(${SAMPLE_TEST_EXEC_NAME} ${SAMPLE_TEST_SOURCE_FILES}) 

this is the conclusion of make

 [ 8%] Building CXX object CMakeFiles/sample.dir/src/KeyBuffer.cpp.obj [ 12%] Building CXX object CMakeFiles/sample.dir/src/main.cpp.obj [ 20%] Building CXX object CMakeFiles/sample.dir/src/Object.cpp.obj [ 45%] Building CXX object CMakeFiles/sample.dir/src/World.cpp.obj Linking CXX executable bin/sample.exe [ 45%] Built target sample [ 50%] Building CXX object CMakeFiles/sample_test.dir/test/KeyBufferTest.cpp.obj [ 54%] Building CXX object CMakeFiles/sample_test.dir/test/ObjectTest.cpp.obj [ 66%] Building CXX object CMakeFiles/sample_test.dir/src/KeyBuffer.cpp.obj [ 75%] Building CXX object CMakeFiles/sample_test.dir/src/Object.cpp.obj [100%] Building CXX object CMakeFiles/sample_test.dir/src/World.cpp.obj Linking CXX executable bin/sample_test.exe 

As you can see, Object.cpp , World.cpp and KeyBuffer.cpp compiled twice! How can I prevent this? Or is there a better way to handle CppUnit tests with CMake?

+4
source share
2 answers

Each target can have different compiler flags, so if you add one source file to two goals, separate object files must be created from this one source file for both purposes.

The usual solution is to compile the common source files into a static library, which is then linked to both target applications.

 add_library(base STATIC ${shared_SOURCES}) # except eg foo_main.cpp add_executable(foo ${foo_only_SOURCES}) target_link_libraries(foo base) add_executable(bar ${bar_only_SOURCES}) target_link_libraries(bar base) 
+4
source

Conceptually, CMake considers each target (i.e., executable or library) as a separate assembly block. The generated assembly system will create an object file for each source file belonging to the target. By default, CMake does not avoid redundant compilation of source files, which are used for several purposes, even if the compilation options (compilation flags, preprocessor definitions ...) are exactly the same.

CMake 2.8.8 introduced a new function called OBJECT_LIBRARY to solve the problem of avoiding redundant compilations:

To create an object library, use add_library :

 FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp) ADD_LIBRARY(sample_objects OBJECT EXCLUDE_FROM_ALL ${SAMPLE_SOURCE_FILES}) 

Other targets created by add_library or add_executable can refer to objects using an expression of the form $<TARGET_OBJECTS:objlib> :

 ADD_EXECUTABLE(${SAMPLE_EXEC_NAME} $<TARGET_OBJECTS:sample_objects>) FILE(GLOB_RECURSE SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_PATH}/*.cpp) ADD_EXECUTABLE(${SAMPLE_TEST_EXEC_NAME} $<TARGET_OBJECTS:sample_objects> ${SAMPLE_TEST_SOURCE_FILES}) 

Compared to using a regular static library, to avoid redundant compilation, the object library has the advantage of not having to link it. In addition, it cannot be imported, exported, or installed.

+4
source

All Articles