c++ - 在子目录中调用 target_link_libraries 的替代方法

标签 c++ cmake code-coverage gcov lcov

案例:

我声明了一个函数setup_target_for_coverage在单独的 .cmake 脚本中,添加到 CMAKE_MODULE_PATH ,它为代码覆盖率分析准备目标 ( mylib )。 setup_target_for_coverage从子目录调用 mylib (mylib_tests)。

要求是,与测试和代码覆盖率相关的所有事情(仅针对此目标)都发生在 mylib/tests 中。和setup_target_for_coverage ,来自 mylib/CMakeLists.txt我们只添加 test-子目录,仅此而已。最后,mylib 既不知道测试细节,也不知道代码覆盖率的存在。 ,它只是“盲目地”调用add_subdirectory( tests ) .

示例:

看起来像这样:

mylib:

# ./mylib/CMakeLists.txt:

project( mylib )
add_library( mylib main.cpp )
# This is all mylib should be aware of, everything else is hidden
add_subdirectory( tests )

mylib_tests:

# ./mylib/tests/CMakeLists.txt:

project( mylib_tests )

# ...

include(code-coverage)
setup_target_for_coverage(
    TARGET mylib
    TEST_RUNNER mylib_tests
)

代码覆盖率:

# ./cmake/code-coverage.txt:

function(setup_target_for_coverage)
    # Parse arguments...

    # Setting compile flags: Works as expected
    target_compile_options( ${args_TARGET}
        PRIVATE
            -g -O0 --coverage
    )

    # Setting linker flags: THIS FAILS <---------------
    target_link_libraries( ${args_TARGET}
        PRIVATE
            --coverage
    )

    add_custom_target( ${args_TARGET}_coverage}
        # Setup lcov, run "TEST_RUNNER", generate html...
        COMMAND ...
    )

endfunction()

简而言之,它设置编译器和链接器标志 ( --coverage ) 并添加运行 gcov/lcov 和 genhtml 的自定义目标。

问题:

问题出在 target_link_libraries ,(如文档所述)需要出现在创建目标的同一“目录”中:

The named <target> must have been created in the current directory by a command such as add_executable() or add_library() [...]

因此我收到以下错误:

Attempt to add link library "--coverage" to target "mylib" which is not built in this directory.

我尝试使用set_property来解决这个问题直接

set_property(
    TARGET ${TARGET} 
    APPEND_STRING PROPERTY LINK_FLAGS "--coverage"
)

无济于事。即使在相同的 CMakeLists.txt 中,它也会失败并出现以下错误:

"undefined reference to `__gcov_merge_add'"

如果 target_link_libraries 则有效已移至./mylib/CMakeLists.txt ,但这正如提到的不满足我的要求。

有什么想法吗?

最佳答案

将评论转化为答案。正如您所强调的,您只能对同一目录范围中定义的目标调用 target_link_libraries() (编辑:自 CMake 3.13 起不再存在此限制)。当您调用 add_subdirectory() 时,您输入了一个新的目录范围,因此遇到了您所询问的问题。

另一方面,include() 命令不会创建新的目录范围。这有两个直接相关的影响:

  • included 目录的文件中,您仍然可以为 include 目录范围内的目标调用 target_link_libraries()
  • CMAKE_CURRENT_SOURCE_DIR 的值不会更改,因此您可能希望在包含的文件中使用 CMAKE_CURRENT_LIST_DIR。请注意,CMAKE_CURRENT_BINARY_DIR 没有等效项,它也不会改变。

典型的模式可能是这样的:

mylib/CMakeLists.txt:

add_library( mylib main.cpp )
include( tests/CMakeLists.txt )

mylib/tests/CMakeLists.txt:

add_executable( someTest "${CMAKE_CURRENT_LIST_DIR}/someTest.cpp" )
# ...

也许至少是相关的,您也可以在this article中找到这些想法。引起兴趣。它展示了如何跨目录管理源和目标,并涉及 add_subdirectory()include() 的讨论。

关于c++ - 在子目录中调用 target_link_libraries 的替代方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44811329/

相关文章:

c++ - 如何将 DeviceIOControl 移植到 ioctl?

cmake - 如何在 CMake 中创建临时目录?

c++ - 用于开发 C++ 代码覆盖工具的解析器

typescript - TypeScript 的 Webpack Karma Istanbul 重映射

linux - 将 autogen.sh 与 ExternalProject_Add 结合使用

java - 如何将连体衣集成到开源项目中?

c++ - 在构造函数中使用通用引用时如何允许默认构造?

c++ - 使用 C++ 方式对结构和数组进行别名处理

php - 通过 C++ 程序进行 Wordpress 身份验证

c++ - 如何使用 CMake 在 MinGW 上激活 c++11 支持?