我正在我的 cmake 项目中编写函数,该函数需要从一个目标创建两个目标,并稍微更改其中之一:
option(BORG_STRIP_TEST_BINARIES OFF "Strip symbols from test binaries to reduce disk space usage" )
function(add_borg_test target)
add_test(${target} ${target} --gtest_color=yes)
if(BORG_STRIP_TEST_BINARIES)
# copy target, but make it optional
duplicate_target(FROM ${target} TO ${target}_debug )
set_target_properties(${target}_debug PROPERTIES EXCLUDE_FROM_ALL TRUE)
# alter
target_link_options(${target} PRIVATE -s)
endif()
endfunction()
所以这应该是这样工作的:
- 我创建使用 gtest 的二进制目标。设置全部
target_link_libraries
和所有。示例名称example-utests
- 相反添加通用
add_test
,我用的是自定义的add_borg_test
- now
example-utests
带有标志的链接-s
并包含在all
target.
-
example-utests_debug
不包括在all
目标,但当明确请求时,它会链接而不-s
.
如何实施duplicate_target
从上面的代码片段?
我的第一直觉(抱歉)是质疑为什么要这样做。我不是你,我不知道你的背景,所以问问自己:你是吗?sure您是否认为仅通过生成多个构建系统并为每个构建系统指定单独的配置选项无法实现您想要的目标?毕竟,CMake 的整个设计就是为了让生成构建系统变得容易。
话虽这么说,如果您确信您有充分的理由想要复制/克隆/重复目标定义在同一个构建系统中,然后按照 Brad King(CMake 维护者之一)的建议进行操作这个邮件线程 https://cmake.org/pipermail/cmake-developers/2017-March/029902.html:
尽管您可以这样做,但没有内置的方法可以做到这一点
接近从读取目标属性的宏
原始的以便使用适当的命令重现它们。
它可能会有助于利用如何获取目标的所有属性 https://stackoverflow.com/q/69761538/11107541。请注意,我在我的回答帖子中列出了一些重大限制。我所知道的最佳解决方案仅允许读取内置到 CMake 的目标属性,而不允许读取您或任何其他 CMake 配置代码自定义定义的任何属性。因此,同样的限制也适用于这里的解决方案,大致如下:
execute_process(COMMAND "${CMAKE_COMMAND}" "--help-property-list" "${CMAKE_BINARY_DIR}/--help-property-list.txt")
file(STRINGS "${CMAKE_BINARY_DIR}/--help-property-list.txt" property_list)
function(copy_target_props src_target dest_target)
set(config_types "${CMAKE_CONFIGURATION_TYPES}")
if(NOT DEFINED CMAKE_CONFIGURATION_TYPES)
set(config_types "Release;Debug;RelWithDebInfo;MinSizeRel")
endif()
foreach(prop_name ${property_list})
if("${prop_name}" MATCHES "(^LOCATION)|^VS_DEPLOYMENT_LOCATION$|^MACOSX_PACKAGE_LOCATION$|^CXX_MODULE_SETS$|^HEADER_SETS$|^IMPORTED_GLOBAL$|^INTERFACE_CXX_MODULE_SETS$|^INTERFACE_HEADER_SETS$|^NAME$|^TYPE$")
continue()
endif()
if("${prop_name}" MATCHES "<CONFIG>")
foreach(config ${config_types})
string(REPLACE "<CONFIG>" "${config}" config_prop_name "${prop_name}")
get_target_property(prop_val "${src_target}" "${config_prop_name}")
if(NOT "${prop_val}" STREQUAL "prop_val-NOTFOUND")
#message("${config_prop_name}: ${prop_val}")
set_property(TARGET "${dest_target}" PROPERTY "${config_prop_name}" "${prop_val}")
endif()
endforeach()
else()
get_target_property(prop_val "${src_target}" "${prop_name}")
if(NOT "${prop_val}" STREQUAL "prop_val-NOTFOUND")
#message("${prop_name}: ${prop_val}")
set_property(TARGET "${dest_target}" PROPERTY "${prop_name}" "${prop_val}")
endif()
endif()
endforeach()
set(prop_name "IMPORTED_GLOBAL")
get_target_property(prop_val "${src_target}" "${prop_name}")
if((NOT "${prop_val}" STREQUAL "prop_val-NOTFOUND") AND "${prop_val}")
#message("${config_prop_name}: ${prop_val}")
set_property(TARGET "${dest_target}" PROPERTY "${prop_name}" "${prop_val}")
endif()
endfunction()
# example usage
add_executable(foo1 foo.c)
add_executable(foo2)
copy_target_props(foo1 foo2)
我太懒了,无法编写一个不需要手动定义第二个目标的实际复制函数。但你可以通过阅读目标来做到这一点TYPE
源目标的属性,然后对所有add_executable
/add_library
变体(首次定义目标后无法更改目标的类型(source https://stackoverflow.com/a/76078866/11107541)).
还有另一种适用性有限的技术 - 与其说是用于复制目标,不如说是为了使公共目标属性设置可重用(同样,适用性有限):在接口库 https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries,然后将多个相似的目标链接到接口目标,以便它们继承接口目标的值。
最后一点:我有一个项目,我使用 CMake 来驱动 PGO 两个阶段的训练和优化构建,我在其中创建了项目ExternalProject本身,并为训练和使用阶段定义了两个自定义构建配置,这需要不同的编译标志。也就是说(毫无帮助),您所采取的方法的适用性取决于具体情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)