CMake的execute_process和任意Shell脚本

12

CMake的execute_process命令似乎只能让你执行进程,而不能执行你可以传递给命令行shell的任意行。问题是,我想使用管道、文件描述符重定向等等,但似乎这是不可能的。另一个选择对我来说将非常痛苦(我想)...

我该怎么办?

PS-CMake 2.8和3.x版本的答案都很有趣。

3个回答

27
你可以执行任何shell脚本,使用你的shell支持将脚本作为字符串参数传入。
例子:
execute_process(
    COMMAND bash "-c" "echo -n hello | sed 's/hello/world/;'" 
    OUTPUT_VARIABLE FOO
)

这将导致FOO包含world

当然,您需要小心地转义引号和反斜杠。还要记住,运行bash只会在具有bash的平台上运行,即它在Windows上不起作用。


10
  1. execute_process命令似乎只允许您执行进程,而不是可以提供给命令shell的任意行。

是的,确实在该命令的文档中写明了这一点:

所有参数都会逐字传递给子进程。不使用中间 shell,因此 shell 操作符(如 >)将被视为常规参数。

  1. 我想使用管道

在同一次execute_process调用中,不同的COMMAND实际上是通过管道连接起来的:

运行给定的一个或多个命令,每个进程的标准输出都会被输送到下一个进程的标准输入中。

  1. 文件描述符重定向等复杂操作似乎不可能。

对于复杂的操作,请准备一个单独的 shell 脚本,并使用execute_process运行它。您可以使用其参数或通过预先进行的configure_file将变量从 CMake 传递到此脚本。


我无法在目标机器上准备一个独立的shell脚本,因为它不是开发机器 - 那么,您建议我将这个shell脚本打包吗?再加一个文件专门用于此? - einpoklum
我的意思是在源代码中添加额外的shell脚本。如果您不是在目标机器上执行构建,则无需将此脚本放在那里。 - Tsyvarev
有一个名为 INPUT_FILE 的文件描述符,你可以将 /dev/null 作为文件名放入其中。 - Sandburg

2

我需要将两个命令依次传递,实际上我了解到execute_process的每个COMMAND已经被管道化了。因此,只需将命令依次添加即可解决这个问题:

execute_process(
    COMMAND echo "Hello"
    COMMAND sed -e 's/H/h/'
    OUTPUT_VARIABLE GREETINGS
    OUTPUT_STRIP_TRAILING_WHITESPACE)

现在变量GREETINGS被设置为hello

如果您确实需要大量的文件重定向(正如您所述),您可能希望编写一个外部脚本,然后从CMakeLists.txt执行该脚本。在CMake中正确转义所有内容真的很困难。

如果您可以简化脚本为一个命令生成一个文件,另一个处理该文件等,则始终可以使用INPUT_FILEOUTPUT_FILE选项。或者将文件名传递给您的命令以进行输入。

一次处理一个文件通常更加清晰。虽然我理解有些命令可能需要多个源和目标。


这个管道功能需要的最低 CMake 版本是多少? - einpoklum
据我所见,它在2.8.0中已经是这样了。 - Alexis Wilke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接