CppUnit и CMake: файлы.cpp компилируются дважды
В настоящее время я использую CMake для сборки своего проекта и CppUnit для его тестирования. В моем файле CMake я создаю два исполняемых файла. sample
это сам скомпилированный источник. И с sample_test
Я запускаю тесты. Если ир
Здесь часть моего 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})
это вывод 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
Как вы видете Object.cpp
, World.cpp
а также KeyBuffer.cpp
получить компиляцию дважды! Как я могу предотвратить это? Или есть лучший способ обработки тестов CppUnit с использованием CMake?
2 ответа
Для каждой цели могут быть настроены различные флаги компилятора, поэтому, если вы добавляете один исходный файл к двум целевым объектам, необходимо создать отдельные объектные файлы из этого одного исходного файла для обеих целей.
Обычное решение состоит в том, чтобы скомпилировать общие исходные файлы в статическую библиотеку, которая затем связывается с обоими целями приложения.
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)
Концептуально CMake рассматривает каждую цель (т. Е. Исполняемый файл или библиотеку) как отдельную единицу сборки. Сгенерированная система сборки создаст объектный файл для каждого исходного файла, принадлежащего цели. По умолчанию CMake не избегает избыточных компиляций исходных файлов, которые используются в нескольких целях, даже если параметры компиляции (флаги компиляции, определения препроцессора...) в точности совпадают.
CMake 2.8.8 представил новую функцию под названием OBJECT_LIBRARY
Цель для решения проблемы избегания избыточных компиляций:
Для создания библиотеки объектов используйте add_library
:
FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp)
ADD_LIBRARY(sample_objects OBJECT EXCLUDE_FROM_ALL ${SAMPLE_SOURCE_FILES})
Другие цели, созданные add_library
или же add_executable
может ссылаться на объекты, используя выражение вида $<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})
По сравнению с использованием обычной статической библиотеки, чтобы избежать избыточной компиляции, библиотека объектов имеет то преимущество, что ее не нужно связывать. Кроме того, он не может быть импортирован, экспортирован или установлен.