Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CppUnit and CMake: .cpp files get compiled twice

Tags:

c++

cmake

cppunit

I'm currently using CMake to build 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 the tests. If i r

Here a 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 output 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 get compiled twice! How can i prevent it? Or is there a better way to handle the CppUnit tests using CMake?

like image 769
MarcDefiant Avatar asked Feb 20 '23 14:02

MarcDefiant


2 Answers

Each target may have different compiler flags configured, so if you add one source files to two targets, separate object files need to be produced from this one source file for both targets.

The usual solution is to compile the shared source files into a static library which is then linked into both application targets.

add_library(base STATIC ${shared_SOURCES}) # except e.g. 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)
like image 107
Stefan Majewsky Avatar answered Mar 03 '23 17:03

Stefan Majewsky


Conceptually CMake treats each target (i.e., executable or library) as a separate build unit. The generated build system will produce an object file for each source file belonging to the target. By default CMake does not avoid redundant compilations of source files that are used in multiple targets, even if the compilation settings (compilation flags, preprocessor definitions ...) are exactly the same.

CMake 2.8.8 introduced a new feature called OBJECT_LIBRARY target to address the problem of avoiding redundant compilations:

To generate 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 may reference the 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 with using a regular static library to avoid redundant compilation, an object library has the advantage that it does not need to be linked. On top of that it cannot be imported, exported or installed.

like image 26
sakra Avatar answered Mar 03 '23 17:03

sakra