使用CMake构建后创建符号链接的语法问题及实现咨询
CMake批量创建符号链接的问题与解决
问题描述
尝试通过add_custom_target循环处理文件创建符号链接,使用了如下CMake代码:
add_custom_target(myTargetNAme-link echo "HERE" # This is printed COMMAND for file in /mylocation/* do ### Create links using $file done DEPENDS dependency WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Create a link to use files in dev env" VERBATIM )
执行时出现错误:
/bin/sh: -c: line 1: syntax error: unexpected end of file
咨询问题:
- 这种批量处理文件的方式是否合理?
- CMake中此类for循环的正确语法是什么?
补充说明:项目生成包含Python模块的.so文件和若干.py文件,需求是将这些文件链接到Python安装目录。此前通过脚本调用nice -n 11 ninja myTargetNAme-link执行该目标,是否可以省去这一步?另外删除VERBATIM关键字后,已能使用*.py通过ln生成符号链接。
问题解答
1. 批量处理文件的方式是否合理?
直接在add_custom_target里写shell循环是可行的,但属于"shell脚本风格"的实现。如果追求跨平台兼容性(比如要支持Windows),更推荐用CMake内置命令(如file(CREATE_LINK));但如果是依赖shell特性的复杂操作,用shell循环也没问题,适合快速落地需求。
2. CMake中此类for循环的正确语法是什么?
你的错误核心是VERBATIM关键字的影响,以及多行shell命令的传递格式问题,下面提供两种靠谱的写法:
写法一:保留VERBATIM,用sh -c包裹完整脚本
VERBATIM会让CMake把命令作为单个参数传递给shell,这时候需要用sh -c把多行脚本打包成一个命令,同时注意转义CMake会解析的变量:
add_custom_target(myTargetName-link COMMAND sh -c " echo 'HERE' for file in /mylocation/*; do # 替换成实际的链接命令,注意转义$符号 ln -sf \"\$file\" \"${PYTHON_INSTALL_DIR}/$(basename \$file)\" done " DEPENDS dependency WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Create links to use files in dev env" VERBATIM )
这里\$file是为了避免CMake提前解析变量,确保它能传递给shell使用。
写法二:用CMake原生循环(更推荐)
用CMake的file(GLOB)先获取文件列表,再通过foreach循环逐个创建链接,这种方式更符合CMake的风格,跨平台性更好,还能处理带空格的文件名:
# 匹配需要链接的文件 file(GLOB FILES_TO_LINK "/mylocation/*.so" "/mylocation/*.py") add_custom_target(myTargetName-link) foreach(FILE ${FILES_TO_LINK}) get_filename_component(FILE_NAME ${FILE} NAME) add_custom_command(TARGET myTargetName-link POST_BUILD COMMAND ln -sf "${FILE}" "${PYTHON_INSTALL_DIR}/${FILE_NAME}" COMMENT "Linking ${FILE_NAME}..." ) endforeach()
补充:能否省去nice -n 11 ninja myTargetNAme-link这一步?
完全可以,有两种处理方式:
- 自动执行链接目标:把链接目标设为项目默认构建目标的依赖,这样执行
ninja时会自动运行它:# 假设你的默认构建目标是myDefaultTarget,替换成实际目标名 add_dependencies(myDefaultTarget myTargetName-link) - 内置nice优先级:如果需要保留低优先级执行,把
nice命令直接加到COMMAND里,不用单独在脚本里调用:COMMAND nice -n 11 sh -c "..."
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

