CMake add_custom_target目录存在检查在树莓派构建中失败
问题:CMake自定义目标在树莓派执行bash命令报错,PC环境正常
环境信息
树莓派环境:
$ uname -a Linux raspberry 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux $ cat /etc/issue Raspbian GNU/Linux 9 \n \l
CMake版本:自定义编译的3.28.1
问题代码(CMakeLists.txt)
cmake_minimum_required(VERSION 3.14) project(ProjectName) SET(OPT_DEBS "/opt/debs") add_custom_target(check_opt_debs ALL COMMENT "Checking for existence of ${OPT_DEBS} directory" COMMAND /bin/bash -c "[ ! -d '${OPT_DEBS}' ] && echo 'Directory ${OPT_DEBS} DOES NOT exist; please run \\`sudo mkdir /opt/debs\\` to create it, before running \\`make package\\`/\\`cpack\\` !!'" )
报错信息
执行make时触发错误:
/bin/sh: 1: echo Directory\ /opt/debs\ DOES\ NOT\ exist;\ please\ run\ \`sudo\ mkdir\ /opt/debs\`\ to\ create\ it,\ before\ running\ \`make\ package\`/\`cpack\`\ !!: not found CMakeFiles/check_opt_debs.dir/build.make:70: recipe for target 'CMakeFiles/check_opt_debs' failed make[2]: *** [CMakeFiles/check_opt_debs] Error 127 CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/check_opt_debs.dir/all' failed make[1]: *** [CMakeFiles/check_opt_debs.dir/all] Error 2 Makefile:90: recipe for target 'all' failed make: *** [all] Error 2
原因分析
问题根源在于CMake对嵌套引号、转义字符的跨平台解析差异。PC环境下的CMake版本或shell解析逻辑能兼容现有转义写法,但树莓派上的CMake 3.28.1生成Makefile时,错误地将带转义的整段字符串识别为单个命令名,而非echo命令加参数,导致shell找不到对应命令。
同时,直接在COMMAND中嵌套/bin/bash -c和特殊字符(分号、反引号)时,CMake的变量替换和shell的命令解析容易出现冲突,进一步加剧格式混乱。
解决办法
方法1:使用CMake原生逻辑(推荐)
完全避开shell转义问题,直接用CMake内置的文件检查和输出功能:
cmake_minimum_required(VERSION 3.14) project(ProjectName) SET(OPT_DEBS "/opt/debs") # 构建阶段检查目录 add_custom_target(check_opt_debs ALL COMMENT "Checking for existence of ${OPT_DEBS} directory" COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red "Directory ${OPT_DEBS} DOES NOT exist; please run `sudo mkdir /opt/debs` to create it, before running `make package`/`cpack` !!" VERBATIM ) # 仅当目录不存在时执行检查逻辑 add_custom_command( OUTPUT check_opt_debs_marker COMMAND ${CMAKE_COMMAND} -E touch check_opt_debs_marker COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red "Directory ${OPT_DEBS} DOES NOT exist; please run `sudo mkdir /opt/debs` to create it, before running `make package`/`cpack` !!" MAIN_DEPENDENCY ${OPT_DEBS} VERBATIM ) add_custom_target(check_opt_debs ALL DEPENDS check_opt_debs_marker)
如果允许在配置阶段提前检查,写法更简洁:
cmake_minimum_required(VERSION 3.14) project(ProjectName) SET(OPT_DEBS "/opt/debs") if(NOT EXISTS ${OPT_DEBS}) message(WARNING "Directory ${OPT_DEBS} DOES NOT exist; please run `sudo mkdir /opt/debs` to create it, before running `make package`/`cpack` !!") endif()
方法2:修复shell命令转义
若坚持使用bash命令,需调整引号嵌套逻辑并添加VERBATIM参数,让CMake正确处理特殊字符:
cmake_minimum_required(VERSION 3.14) project(ProjectName) SET(OPT_DEBS "/opt/debs") add_custom_target(check_opt_debs ALL COMMENT "Checking for existence of ${OPT_DEBS} directory" COMMAND /bin/bash -c "[ ! -d '${OPT_DEBS}' ] && echo \"Directory ${OPT_DEBS} DOES NOT exist; please run \`sudo mkdir /opt/debs\` to create it, before running \`make package\`/\`cpack\` !!\"" VERBATIM )
核心调整:
- 用双引号包裹
echo的输出内容,内层反引号无需额外转义 - 添加
VERBATIM参数,确保CMake生成符合目标平台shell规范的命令行,消除跨平台解析差异
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

