案例:
我声明了一个函数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 asadd_executable()
oradd_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/