You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:21:02