CppUnit 和 CMake:.cpp文件被编译两次
CppUnit and CMake: .cpp files get compiled twice
我目前正在使用 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
被编译两次!我该如何预防它?或者有没有更好的方法来使用 CMake 处理 CppUnit 测试?
每个目标可能配置了不同的编译器标志,因此,如果将一个源文件添加到两个目标,则需要从这两个目标的这一个源文件生成单独的对象文件。
通常的解决方案是将共享源文件编译为静态库,然后将其链接到两个应用程序目标中。
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
target 的新功能,以解决避免冗余编译的问题:
要生成对象库,请使用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})
与使用常规静态库避免冗余编译相比,对象库的优点是不需要链接。最重要的是,它不能导入,导出或安装。
相关文章:
- g++的分段错误(在NaN上使用to_string两次时)
- 蛇在C++不会连续转两次
- 检查一个数组是否包含在另一个数组中,以相反的顺序,至少两次
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 我应该如何去缓解两次出现的cin?
- Realloc 两次无法在 Visual Studio 上运行
- 使用 getline(cin, var) 两次在进行字符串比较时会产生错误 (==)
- 为什么映射插入和 map.find() 的单次迭代比插入和 map.find() 的两次单独迭代慢得多
- C++析构函数调用两次,堆栈分配的复合对象
- 为什么参数在构造 std::thread 时移动两次
- Qt插槽调用了两次
- 做 std::用相同的unique_ptr移动两次
- C++两次定义相同的函数会导致错误
- 为什么具有静态存储持续时间的同一内联变量在包含在 VS2017 编译的两个翻译单元中时会构造和销毁两次
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- 使用柯南打包时如何避免列出两次依赖?
- 两次相同的 for 循环:一个编译,另一个不编译
- 是否可以仅通过编写 debian/rules 来编译两次并构建单独的软件包?
- CppUnit 和 CMake:.cpp文件被编译两次
- 我如何配置cmake编译一个文件两次与两个不同的编译器