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

Build 在cmake命令中使用子shell或管道?,build,cmake,subshell,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(pc

我想添加一个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_target(pclean
     COMMAND bash -c "find "${CMAKE_SOURCE_DIR}" -name \"*.rej\" -or -name \"*.orig\"")

我得到了
*.orig
*.rej
文件的列表。

这是一个不完整的答案

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

  • 首先是CMake
  • 然后由GNU制造
  • 最后是贝壳
当它只是最后一个字符时-您只需转义glob字符
*

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变量——这些变量总是以某种方式搞砸。因此,我的问题中的第二个变体,或者读f时的
,没有运气;请填写“$f”rm;在find命令后完成

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

将我的评论转化为答案

我可以重现您的问题,并将
逐字添加到您的解决方案中

以下方面确实起了作用:

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
)
如果您在自定义命令中开始“转义”,则提示您应该使用
逐字

CMakeFiles/pclean:
    bash -c rm\ $(find\ "/mnt/c/temp/StackOverflow/SubShell"\ -name\ "*.rej"\ -or\ -name\ "*.orig")
CMakeFiles/pclean:
    bash -c "rm \$$(find \"/mnt/c/temp/StackOverflow/SubShell\" -name \"*.rej\" -or -name \"*.orig\")"
对于构建工具,命令的所有参数都将正确转义,以便被调用的命令接收到的每个参数保持不变。请注意,在
add\u custom\u target
甚至看到参数之前,CMake语言处理器仍然使用一级转义

生成的
makefile
的摘录,不带
逐字

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

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


@Florian:引号不是问题。您可以使用
附加的\u MAKE\u CLEAN\u文件
属性吗?e、 g.
SET(addfiles foo bar)SET_属性(DIRECTORY APPEND属性ADDITIONAL_MAKE_CLEAN_FILES“${addfiles}”)
要获取要删除的文件列表,可以使用
file(GLOB…
命令。@vre:我不知道。。。我会调查的。。。哦,等等,这不会导致
makeclean
删除这些文件吗?我不希望发生这种情况。我猜在shell看到它之前,
$(find)
构造是由
make
评估的。在任何情况下,都不建议在命令中使用复杂表达式。如果是
find
命令,您可以传递
rm{}
作为其
-exec
参数;这将有效地删除
find
找到的每个文件。为什么不使用
find
-delete
标志?转义和反斜杠部分听起来像是你只需要将
逐字添加到你的
add_custom_target()
调用中。@Florian:你能把它发展成一个答案吗?