CMake中file(GENERATE)命令的CONTENT参数如何编写多行内容
问题原因与解决方案
报错原因
报错的核心原因是你使用了CMake的**括号参数(Bracket Argument)**语法[==[]==],这类参数的设计就是完全忽略内部的变量展开、转义序列,所有内容都会作为字面量传递。所以你写在里面的${TARGET}、${FILENAME_RELEASE}都不会被CMake替换为实际值,最终传给生成器表达式的是字面量$<TARGET_FILE_NAME:${TARGET}>,CMake解析生成器表达式的时候找不到${TARGET}这个目标,自然就报错了。
解决方法
方案1:直接使用支持换行的双引号字符串(兼容性最好)
CMake的双引号字符串原生支持跨多行书写,内部的${}格式变量会正常展开,$<>格式的生成器表达式会完整保留到生成阶段处理,完全符合需求:
function(foo TARGET) set(FILENAME_RELEASE $<TARGET_FILE_BASE_NAME:${TARGET}>.dll) # 直接用双引号包裹多行内容即可,变量正常展开 file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/text.log CONTENT "$<TARGET_FILE_NAME:${TARGET}> ${FILENAME_RELEASE}") endfunction()
如果不需要开头的空行,把第一行内容紧跟在双引号后面即可。
方案2:保留括号参数语法(适合内容包含大量特殊符号的场景)
如果你的生成内容里有大量双引号、反斜杠,不想手动转义,可以先通过string(CONFIGURE)(要求CMake 3.18+)预处理括号参数里的变量,再传给file(GENERATE):
function(foo TARGET) set(FILENAME_RELEASE $<TARGET_FILE_BASE_NAME:${TARGET}>.dll) # 先展开括号参数里的变量,不修改生成器表达式 string(CONFIGURE [==[ $<TARGET_FILE_NAME:${TARGET}> ${FILENAME_RELEASE}]==] GENERATED_CONTENT @ONLY) # 传入预处理后的内容 file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/text.log CONTENT "${GENERATED_CONTENT}") endfunction()
这里的@ONLY参数会确保只展开${VAR}、@VAR@格式的变量,不会改动$<>格式的生成器表达式。
内容的提问来源于stack exchange,提问作者lucaboni
相关产品推荐
相关产品推荐

