首页 > 解决方案 > 在 Linux 上使用 Cmake add_custom_command 的 Shell 命令

问题描述

我无法弄清楚在 Linux 上的 Cmake 的构建后步骤中运行 shell 命令的正确语法。我可以做一个简单的echo工作,但是当我想迭代所有文件和echo那些文件时,我得到了一个错误。

以下作品:

add_custom_command(TARGET ${MY_LIBRARY_NAME}
                   POST_BUILD
                   COMMAND echo Hello world!
                   USES_TERMINAL)

这正确打印Hello world!

但现在我想遍历所有.obj文件并打印它们。我想我应该这样做:

add_custom_command(TARGET ${MY_LIBRARY_NAME} 
                   POST_BUILD
                   COMMAND for file in *.obj; do echo @file ; done 
                   VERBATIM
                   USES_TERMINAL)

但这给出了以下错误:

/bin/sh: 1: Syntax error: end of file unexpected

我尝试了各种带引号或以 开头的组合sh,但似乎都不起作用。我怎样才能正确地做到这一点?

标签: linuxshellcmakepost-build

解决方案


add_custom_command(以及执行 a 的所有其他 CMake 函数COMMAND)不运行 shell 脚本,而只允许执行单个命令。这USES_TERMINAL不会导致命令在实际终端中运行,也不会允许使用 shell 内置函数,如for循环。

文档中:

要运行完整的脚本,请使用 configure_file() 命令或 file(GENERATE) 命令来创建它,然后指定一个命令来启动它。

或者,对于非常简单的脚本,您可以执行@lojza 在评论中对您的问题提出的建议,并bash使用实际脚本内容作为参数运行命令。

add_custom_command(
  TARGET ${MY_LIBRARY_NAME}
  POST_BUILD 
  COMMAND bash -c [[for file in *.obj; do echo ${file}; done]]
  VERBATIM
)

请注意,我在这里故意使用了 CMake 原始字符串文字,因此${file}不会将其扩展为 CMake 变量。您也可以使用bash -c "for file in *obj; do echo $file; done"常规字符串文字,在这种情况下,$file由于缺少花括号,也不会扩展。不过,在我知道在此类脚本中跟踪由 CMake 变量意外扩展引起的错误是多么困难之前,已经将其他来源的 bash 代码复制并粘贴到 CMake 中,所以我总是建议使用[[]]除非你真的想要展开一个 CMake 变量。

但是,对于使用与模式匹配的所有文件执行某些操作的具体示例,还有一个更简单的替代方法:使用find命令而不是 bash 循环:

add_custom_command(
  TARGET ${MY_LIBRARY_NAME}
  POST_BUILD 
  COMMAND find
    -maxdepth 1 
    -name *.obj 
    -printf "%P\\n"
  VERBATIM
)

推荐阅读