【问题标题】:CMake Add (Test) ExecutableCMake 添加(测试)可执行文件
【发布时间】:2017-01-23 17:01:12
【问题描述】:

我想创建两个可执行文件:一个用于应用程序的可执行文件,一个用于测试应用程序。为此,我的CMakeLists.txt 文件中有以下内容:

include_directories(include)

file(GLOB SOURCE "src/*.cc")
file(GLOB TEST "test/*.cc")

add_executable(interest_calc ${SOURCE})
add_executable(interest_calc_test "src/interest_calc.cc" ${TEST})

由于srctest 目录都包含主要功能,我必须手动将源文件添加到“测试”可执行文件中。是否有另一种非手动方式将所需的源文件添加到“测试”可执行文件?

此外,有没有比创建单独的测试可执行文件更好的方法来测试功能?如果是,是什么/如何?

【问题讨论】:

  • Is there another, non-manual, way to add required source files to the "test" executable? - 例如您可以将文件main.cc 放入不同的文件夹,然后手动将其添加到列表中。 Further, is there a better way to test functionality than creating a separate test executable? If so, what/how? - 这个问题广泛为“什么是编写软件的更好方法”。有许多测试策略。只需选择其中一个似乎适合您的目的。
  • 请注意,如果您只有一个带有少量源文件的可执行文件,那么将所有源文件通配到您的可执行文件中是可行的……但是随着项目的增长,手动将源文件添加到单元、库,可执行文件和适当的测试通常被认为是更好的方法。您将面临临时可执行文件、概念验证源、仅供参考的过时源以及大量其他原因,而不仅仅是“将所有内容编译为一个”。

标签: c++ cmake googletest


【解决方案1】:

改进流程的一种方法是将可执行文件的内容提取到库中,然后有一个名义上的“主”可执行文件,它只是调用你的库,还有一个“测试”可执行文件,它可以根据你的需要来练习库测试一下。

这样,您需要对库进行的任何更改都不会影响可执行的构建过程。

编辑以使用您的示例显示 CMake:

include_directories(include)

file(GLOB SOURCE "src/*.cc")

# Remove main from library, only needed for exec.
list(REMOVE_ITEM SOURCE "main.cc")

file(GLOB TEST "test/*.cc")

add_library(interest_calc_lib STATIC ${SOURCE})
add_executable(interest_calc "main.cc")
target_link_libraries(interest_calc interest_calc_lib)
add_executable(interest_calc_test ${TEST})
target_link_libraries(interest_calc_test interest_calc_lib)

【讨论】:

    【解决方案2】:

    Soerenmascoj 已经给出了一些不错的答案,但我想给出更具体的建议。

    如果您的可执行文件已经有一个 CMakeLists.txt 并且您想添加测试,我建议您添加一个 static 虚拟库。该库可以包含除 main 方法之外的所有可执行文件源(如果您还没有 main 方法,那么在单独的文件中挑选出 main 方法可能是最简单的)。使用 静态 库会给您带来两个好处:

    • 最终的可执行文件将与您当前的完全一样,因此无需处理新的共享库的分发
    • 您无需处理导出符号或跨共享对象边界抛出异常

    对 CMakeLists.txt 的更改可能非常小。我将在这里举一个例子,假设您使用 cmake 3.0 或更高版本。首先,添加虚拟库之前的CMakeLists.txt示例:

    project(MyProject)
    set(SOURCES src/First.cc src/Second.cc src/Third.cc)
    
    add_executable(${PROJECT_NAME} ${SOURCES} src/Main.cc)
    target_include_directories(${PROJECT_NAME}
        ${CMAKE_CURRENT_SOURCE_DIR}/include
        ${CMAKE_CURRENT_SOURCE_DIR}/src
        ${CMAKE_CURRENT_BINARY_DIR})
    target_compile_options(${PROJECT_NAME}
        $<$<CXX_COMPILER_ID:GNU>:-Wall;-pedantic)
    target_compile_definitions(${PROJECT_NAME}
        $<$<CONFIG:Debug>:DEBUG;_DEBUG>)
    set_target_properties(${PROJECT_NAME}
        PROPERTIES CXX_STANDARD 14)
    target_link_libraries(${PROJECT_NAME}
        Threads::Threads)
    

    要添加虚拟库和测试,您需要引入一个具有不同名称的新目标。我在这里选择使用${PROJECT_NAME}_lib,因为这不会对 CMakeLists.txt 造成干扰。这是更新的版本。请注意,几乎所有地方都使用${PROJECT_NAME}_lib 代替${PROJECT_NAME}。大多数属性现在通过设置为PUBLIC 传递给可执行文件。只有对 set_target_properties() 的调用是不可传递的,并且必须为库和可执行文件重复。

    project(MyProject)
    set(SOURCES src/First.cc src/Second.cc src/Third.cc)
    
    add_library(${PROJECT_NAME}_lib STATIC ${SOURCES})
    add_executable(${PROJECT_NAME} src/Main.cc)
    target_include_directories(${PROJECT_NAME}_lib PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/include
        ${CMAKE_CURRENT_SOURCE_DIR}/src
        ${CMAKE_CURRENT_BINARY_DIR})
    target_compile_options(${PROJECT_NAME}_lib PUBLIC
        $<$<CXX_COMPILER_ID:GNU>:-Wall;-pedantic)
    target_compile_definitions(${PROJECT_NAME}_lib PUBLIC
        $<$<CONFIG:Debug>:DEBUG;_DEBUG>)
    set_target_properties(${PROJECT_NAME}_lib
        PROPERTIES CXX_STANDARD 14)
    set_target_properties(${PROJECT_NAME}
        PROPERTIES CXX_STANDARD 14)
    target_link_libraries(${PROJECT_NAME}
        ${PROJECT_NAME}_lib
        Threads::Threads)
    

    现在您可以使用不同的 main 方法将您的测试与 ${PROJECT_NAME}_lib 关联起来。

    【讨论】:

    • 这是一个不错的模式!非常适合我的用例。
    【解决方案3】:

    你可以这样做:
    在当前的 CMakeLists.txt 中,放入这些行:

    添加子目录(src)
    添加子目录(测试)

    然后,在每个目录中添加一个 CMakeLists.txt,将源正确链接到每个文件。

    关于测试,我听说 CMake 可以做测试自动化,但我真的不知道它是如何工作的。

    【讨论】:

      【解决方案4】:

      在我看来,最好的解决方案是创建一个(共享或静态)和两个可执行文件(一个用于主程序,一个用于测试主程序)。之后,您应该将库链接到两个应用程序。 在answer 中,我用一个小例子来解释如何使用 cmake 管理项目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-27
        • 2021-12-08
        • 2020-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-04
        相关资源
        最近更新 更多