CMake函数传递列表参数时自动代码生成未触发的问题
问题根源分析
你遇到的核心问题是列表参数传递时被错误转换为单个字符串,导致CMake无法正确识别add_custom_command的输出文件,进而不会触发代码生成。
具体来说,你调用函数时用双引号包裹了${FOO_DEPENDENCIES}、${FOO_HEADERS}、${FOO_SOURCES}:
setup_code_generation(foo "${FOO_DEPENDENCIES}" "${FOO_HEADERS}" "${FOO_SOURCES}")
这种写法会把原本的CMake列表(多个元素)转换成单个空格分隔的字符串。比如FOO_HEADERS里的两个头文件,会变成"path/to/header1.hpp path/to/header2.hpp",而CMake的OUTPUT字段需要的是多个独立的文件路径,不是单个字符串。这就导致CMake认为你要生成一个包含空格的奇怪文件,而不是实际需要的多个头/源文件,自然不会触发生成逻辑。
另外还有一个隐藏问题:函数里的set(MY_LIB_GENERATED_SOURCE)没有传递到父作用域,即使生成了文件,后续构建库时也无法引用这些生成的源文件。
修复方案
1. 修正函数调用方式
去掉参数的双引号,直接传递列表变量:
setup_code_generation(foo ${FOO_DEPENDENCIES} ${FOO_HEADERS} ${FOO_SOURCES})
这样CMake会保留列表的多个元素,正确传递给函数的DEPENDENCIES、HEADERS、SOURCES参数。
2. 修正函数内的变量传递
修改函数里的set语句,加上PARENT_SCOPE,让生成的源文件变量能在函数外部被访问:
function(setup_code_generation PART_NAME DEPENDENCIES HEADERS SOURCES) add_custom_command( OUTPUT ${HEADERS} ${SOURCES} COMMAND python3 ${GENERATOR_INPUT_DIR}/${PART_NAME}/generator.py --input-files ${GENERATOR_INPUT_DIR}/${PART_NAME} --output-headers ${GENERATOR_OUTPUT_DIR}/header/${PART_NAME} --output-sources ${GENERATOR_OUTPUT_DIR}/source/${PART_NAME} COMMENT "Generating code for ${PART_NAME}" DEPENDS ${DEPENDENCIES} VERBATIM ) # 加上PARENT_SCOPE,将变量传递到父作用域 set(MY_LIB_GENERATED_SOURCE ${MY_LIB_GENERATED_SOURCE} ${SOURCES} PARENT_SCOPE ) endfunction()
3. 额外检查项
- 确保
GENERATOR_INPUT_DIR、GENERATOR_OUTPUT_DIR变量已经正确定义(可以用message(STATUS ${GENERATOR_INPUT_DIR})打印验证) - 确认生成脚本的输出路径和你在
FOO_HEADERS、FOO_SOURCES里定义的路径完全一致(大小写敏感系统如Linux要注意路径大小写) - 检查生成脚本本身是否能独立运行(直接执行
python3 ...命令测试)
验证方法
修改后重新运行CMake和Make:
- 清理之前的构建目录:
rm -rf build && mkdir build && cd build - 重新配置:
cmake .. - 构建:
make
此时应该能看到Generating code for foo的日志,生成的文件也会正确出现在指定目录。
内容的提问来源于stack exchange,提问作者melon_maniac
相关产品推荐
相关产品推荐

