在 cmake 中展开包含生成器表达式的变量名称
Expand variable name containing a generator expression in cmake
在构建过程中,我设置了收集不同子项目构建输出的目录。目录设置为:
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_LIST_DIR}/../build/bin/debug" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_LIST_DIR}/../build/bin/release" )
现在,我想根据其构建的配置将一些文件(qt 插件目录)复制到该目录。
我试过了:
# copy qt plugins
add_custom_command( TARGET mytarget POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${QT_DIR}/../../../plugins"
"${$<UPPER_CASE:CMAKE_RUNTIME_OUTPUT_DIRECTORY_$<CONFIG> >}/plugins"
COMMAND_EXPAND_LISTS)
因此,我尝试构建一个等于变量名称的字符串,然后尝试按照此处所述展开它:。换句话说:我想要一个生成器表达式,它根据当前构建配置评估 CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG
或 CMAKE_RUNTIME_OUTPUT_DIRECTOR_RELEASE
的内容。
但是 运行 使用上述语句的 cmake 会导致错误:
"CMakeLists.txt:112: error: Syntax error in cmake code at [..] when parsing string ${$<UPPER_CASE:CMAKE_RUNTIME_OUTPUT_DIRECTORY_$<CONFIG> >}/plugins Invalid character ('<') in a variable name: '$'
所以我的问题是,如何使用生成器表达式来访问相应的变量? (附加问题:是否有 another/better 方法来实现相同的目标?)
So my question is, how can I use a generator-expression to access the corresponding variable?
你不能。当前(CMake <=3.23)无法扩展名称由生成器表达式的值确定的变量。
Bonus question: is there another/better way to achieve the same goal?
是的,你快到了!您可以使用 $<TARGET_FILE_DIR:...>
:
add_custom_command(
TARGET mytarget POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_directory
"${QT_DIR}/../../../plugins"
"$<TARGET_FILE_DIR:mytarget>/plugins"
VERBATIM
)
这是可行的,因为 TARGET_FILE_DIR
评估包含 mytarget
的可执行文件或库文件的实际目录,无论活动配置、属性 值等如何。
文档:https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_FILE_DIR
CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG>
已经相对于二进制目录,因此您应该 而不是 尝试在其定义中计算二进制目录。此外,它还支持生成器表达式。因此,以下将 更 更健壮:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/$<LOWER_CASE:$<CONFIG>>"
CACHE STRING "Common output directory for runtime artifacts")
这有很多具体的好处:
- 无需设置
CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG
或CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE
- 这将适用于
MinSizeRel
和 RelWithDebInfo
,以及您可能添加的任何自定义配置。
- 由于它被定义为缓存变量,因此可以覆盖它以进行调试/解决名称冲突等问题。
(3) 的更多上下文:大多数 CMAKE_*
变量打算 read-only 或 user-configurable(即在命令行、从 GUI 等)。通过 set(CACHE)
覆盖它们的默认值是一种礼貌的妥协。此规则的一个显着例外是 Qt 代码生成标志 (CMAKE_AUTO{MOC,RCC,UIC}
) 的集合。通常必须为构建设置这些以生成可用的二进制文件。
在构建过程中,我设置了收集不同子项目构建输出的目录。目录设置为:
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_LIST_DIR}/../build/bin/debug" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_LIST_DIR}/../build/bin/release" )
现在,我想根据其构建的配置将一些文件(qt 插件目录)复制到该目录。
我试过了:
# copy qt plugins
add_custom_command( TARGET mytarget POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${QT_DIR}/../../../plugins"
"${$<UPPER_CASE:CMAKE_RUNTIME_OUTPUT_DIRECTORY_$<CONFIG> >}/plugins"
COMMAND_EXPAND_LISTS)
因此,我尝试构建一个等于变量名称的字符串,然后尝试按照此处所述展开它:CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG
或 CMAKE_RUNTIME_OUTPUT_DIRECTOR_RELEASE
的内容。
但是 运行 使用上述语句的 cmake 会导致错误:
"CMakeLists.txt:112: error: Syntax error in cmake code at [..] when parsing string ${$<UPPER_CASE:CMAKE_RUNTIME_OUTPUT_DIRECTORY_$<CONFIG> >}/plugins Invalid character ('<') in a variable name: '$'
所以我的问题是,如何使用生成器表达式来访问相应的变量? (附加问题:是否有 another/better 方法来实现相同的目标?)
So my question is, how can I use a generator-expression to access the corresponding variable?
你不能。当前(CMake <=3.23)无法扩展名称由生成器表达式的值确定的变量。
Bonus question: is there another/better way to achieve the same goal?
是的,你快到了!您可以使用 $<TARGET_FILE_DIR:...>
:
add_custom_command(
TARGET mytarget POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_directory
"${QT_DIR}/../../../plugins"
"$<TARGET_FILE_DIR:mytarget>/plugins"
VERBATIM
)
这是可行的,因为 TARGET_FILE_DIR
评估包含 mytarget
的可执行文件或库文件的实际目录,无论活动配置、属性 值等如何。
文档:https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_FILE_DIR
CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG>
已经相对于二进制目录,因此您应该 而不是 尝试在其定义中计算二进制目录。此外,它还支持生成器表达式。因此,以下将 更 更健壮:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/$<LOWER_CASE:$<CONFIG>>"
CACHE STRING "Common output directory for runtime artifacts")
这有很多具体的好处:
- 无需设置
CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG
或CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE
- 这将适用于
MinSizeRel
和RelWithDebInfo
,以及您可能添加的任何自定义配置。 - 由于它被定义为缓存变量,因此可以覆盖它以进行调试/解决名称冲突等问题。
(3) 的更多上下文:大多数 CMAKE_*
变量打算 read-only 或 user-configurable(即在命令行、从 GUI 等)。通过 set(CACHE)
覆盖它们的默认值是一种礼貌的妥协。此规则的一个显着例外是 Qt 代码生成标志 (CMAKE_AUTO{MOC,RCC,UIC}
) 的集合。通常必须为构建设置这些以生成可用的二进制文件。