【问题标题】:CppUnit and CMake: .cpp files get compiled twiceCppUnit 和 CMake:.cpp 文件被编译两次
【发布时间】:2012-08-07 13:13:00
【问题描述】:

我目前正在使用 CMake 来构建我的项目并使用 CppUnit 来测试它。在我的 CMake 文件中,我创建了两个可执行文件。 sample 是编译后的源代码本身。我使用sample_test 运行测试。如果我 r

这是我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.cppWorld.cppKeyBuffer.cpp 被编译两次!我该如何预防?或者有没有更好的方法来使用 CMake 处理 CppUnit 测试?

【问题讨论】:

    标签: c++ cmake cppunit


    【解决方案1】:

    每个目标可能配置了不同的编译器标志,因此如果您将一个源文件添加到两个目标,则需要从这一个源文件为两个目标生成单独的目标文件。

    通常的解决方案是将共享源文件编译成一个静态库,然后链接到两个应用程序目标。

    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)
    

    【讨论】:

      【解决方案2】:

      从概念上讲,CMake 将每个目标(即可执行文件或库)视为一个单独的构建单元。生成的构建系统将为属于目标的每个源文件生成一个目标文件。默认情况下,CMake 不会避免对多个目标中使用的源文件进行冗余编译,即使编译设置(编译标志、预处理器定义...)完全相同。

      CMake 2.8.8 引入了一个名为OBJECT_LIBRARYnew feature 目标来解决避免冗余编译的问题:

      要生成对象库,请使用add_library:

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

      add_libraryadd_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})
      

      与使用常规静态库避免冗余编译相比,对象库的优点是不需要链接。除此之外,它无法导入、导出或安装。

      【讨论】:

        猜你喜欢
        • 2017-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-27
        • 1970-01-01
        • 2023-03-23
        • 2017-12-29
        相关资源
        最近更新 更多