Build 在cmake命令中使用子shell或管道?
我想添加一个CMake目标,该目标在生成时将触发以下事件: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
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:你能把它发展成一个答案吗?