在cmake命令中使用子shell或管道?

时间:2017-10-20 10:32:06

标签: build cmake subshell

我想添加一个CMake目标,当制作时,会触发以下内容:

rm $(find "${CMAKE_SOURCE_DIR}" -name "*.rej" -or -name "*.orig")

我试过了:

add_custom_target(pclean
    COMMAND bash -c "rm $(find \"${CMAKE_SOURCE_DIR}\" -name \"*.rej\" -or -name \"*.orig\")")

和此:

 add_custom_target(pclean
     COMMAND bash -c "find "${CMAKE_SOURCE_DIR}" -name \"*.rej\" -or -name \"*.orig\" | xargs rm")

但不起作用。我该怎么办?我应该使用像add_custom_command这样的东西吗?

注意:此处的问题不是引号。因此,如果我使用:

 add_custom_target(pclean
     COMMAND bash -c "find "${CMAKE_SOURCE_DIR}" -name \"*.rej\" -or -name \"*.orig\"")

我获取了*.orig*.rej个文件的列表。

2 个答案:

答案 0 :(得分:1)

将我的评论转化为答案

我可以重现您的问题,并将VERBATIM关键字添加到您的add_custom_target()确实修复了它。

以下工作:

cmake_minimum_required(VERSION 2.6)

project(SubShell NONE)

add_custom_target(
    pclean
    COMMAND bash -c "rm $(find \"${CMAKE_SOURCE_DIR}\" -name \"*.rej\" -or -name \"*.orig\")"
    VERBATIM
)

如果您在自定义命令中开始“转义”内容,则提示您应该使用VERBATIM

  

对于构建工具,将正确转义命令的所有参数,以便调用的命令接收每个参数不变。请注意,在add_custom_target看到参数之前,CMake语言处理器仍然使用一级转义。

生成的makefile没有VERBATIM的摘录:

CMakeFiles/pclean:
    bash -c rm\ $(find\ "/mnt/c/temp/StackOverflow/SubShell"\ -name\ "*.rej"\ -or\ -name\ "*.orig")

VERBATIM

CMakeFiles/pclean:
    bash -c "rm \$$(find \"/mnt/c/temp/StackOverflow/SubShell\" -name \"*.rej\" -or -name \"*.orig\")"

<强>参考

答案 1 :(得分:0)

这是一个不完整的答案。

我们面临的问题似乎是COMMAND之后的论证被解释了三次:

  • 首先是CMake,
  • 然后由GNU Make,
  • 然后最终由shell。

当它只是最后一个 - 你只需要转义全局字符*

find some/where -name \*.rej -or -name \*.orig | xargs rm

当它在Makefile时,你需要像:

bash -c "find some/where -name \\*.rej -or -name \\*.orig | xargs rm"

最后,在CMake命令中,您需要另一级别的转义,因此您可以:

add_custom_target(pclean 
    COMMAND bash -c "find \"${CMAKE_SOURCE_DIR}\" -name \\\\*.rej -or -name \\\\*.orig \\| xargs rm")

但是,我还没有设法让命令工作,它也设置然后使用shell变量 - 总是以某种方式弄乱。所以我的问题中的第二个变体没有运气,或者在find命令后使用| while read f; do rm "$f"; done

PS:正如评论者所指出的那样,显然也可以让find命令本身删除文件(-exec-delete)。