美文网首页
Cmake命令之execute_process

Cmake命令之execute_process

作者: Domibaba | 来源:发表于2023-08-21 17:17 被阅读0次

本文所使用的相关软件版本:

软件名称 软件版本
Linux操作系统 Ubuntu 22.04 LTS
cmake 3.22.1

一、基本介绍

如其名字,该命令通过运行指定的命令来执行一个或多个子进程。命令的签名如下:

execute_process(COMMAND <cmd1> [<arguments>]
 [COMMAND <cmd2> [<arguments>]]...
 [WORKING_DIRECTORY <directory>]
 [TIMEOUT <seconds>]
 [RESULT_VARIABLE <variable>]
 [RESULTS_VARIABLE <variable>]
 [OUTPUT_VARIABLE <variable>]
 [ERROR_VARIABLE <variable>]
 [INPUT_FILE <file>]
 [OUTPUT_FILE <file>]
 [ERROR_FILE <file>]
 [OUTPUT_QUIET]
 [ERROR_QUIET]
 [COMMAND_ECHO <where>]
 [OUTPUT_STRIP_TRAILING_WHITESPACE]
 [ERROR_STRIP_TRAILING_WHITESPACE]
 [ENCODING <name>]
 [ECHO_OUTPUT_VARIABLE]
 [ECHO_ERROR_VARIABLE]
 [COMMAND_ERROR_IS_FATAL <ANY|LAST>])

execute_process可以指定多个命令,并且多个命令是通过管道方式执行,上一个命令的标准输出通过管道传递,作为下一个命令的标准输入。所有的命令都共享单个标准错误管道。

来看几个简单的例子:

  1. 执行单个命令,本例子以执行uname -o获取操作系统名称为例。
# CMakeLists.txt
# 输出操作系统名称
EXECUTE_PROCESS(COMMAND uname -o)

运行结果:

GNU/Linux

  1. 执行多个命令,前一个命令的输出会作为后一个命令的输入(相当于Unix/Linux中管道的概念),本例以ls -algrep "cmake"awk '{print $9}',请注意,实际相当于在命令行中执行ls -al | grep "cmake" | awk "{print $9}",即过滤出带匹配cmake字符串的行后,取该行以空格分割的第9项(对于ls -al命令就是过滤出文件名称)。
# CMakeLists.txt
# 列出当前文件目录内容项,通过"cmake"和"awk"过滤出文件名"cmake_install.cmake"
# 相当于执行命令: ls -al | grep "cmake" | awk "{print $9}"
EXECUTE_PROCESS(COMMAND ls -al
 COMMAND grep "cmake"
 COMMAND awk "{print $9}")

运行结果 cmake_install.cmake

二、参数选项详解

  • COMMAND:待执行的子命令,可以指定多个。

  • WORKING_DIRECTORY:将指定的目录作为子命令执行的当前工作目录。

# 指定命令的工作目录,在指定目录下执行pwd命令
EXECUTE_PROCESS(COMMAND pwd
 WORKING_DIRECTORY "/home")

运行结果: /home

  • TIMEOUT:设置子命令执行的超时时间,单位是秒,可以不是整数。注意,是针对每个子命令而言的超时时间,而不是命令总的执行时间。当超时时间到,所有未完成的子命令会结束,并且RESULT_VARIABLE指定的变量会被设置为包含timeout的字符串。因此如果下面例子中的TIMEOUT值大于5,子命令执行可以成功。
# 设置子命令的超时时间
# 注意,是针对每个子命令而言的超时时间,而不是命令总的执行时间
EXECUTE_PROCESS(COMMAND sleep 5
 COMMAND sleep 5
 TIMEOUT 4
 RESULT_VARIABLE msg)
 MESSAGE("Commands execute result: ${msg}")

运行结果: Commands execute result: Process terminated due to timeout

  • RESULT_VARIABLE:包含子命令的执行结果,该变量会被设置为最后一个子命令执行的返回码,或执行出错时候的描述字符串(像上个例子中的超时)。
# 最后一个子命令是删除一个不存在的文件,即使前面的命令执行成功,它也只是包含最后一个子命令的执行结果
EXECUTE_PROCESS(COMMAND rm "notexistfile.ext"
 RESULT_VARIABLE msg)
MESSAGE("Command execute result: ${msg}")

运行结果: rm: 无法删除 'notexistfile.ext': 没有那个文件或目录 Command execute result: 1

  • RESULTS_VARIABLE3.10版本引入。将所有的子命令执行结果存入该变量中,子命令的执行结果以分号连接,存储的顺序按照COMMAND命令的顺序。
# 存储所有子命令的运行结果
EXECUTE_PROCESS(COMMAND ls -al
 COMMAND rm "notexistfile.ext"
 RESULTS_VARIABLE msg_all)
MESSAGE("ALL commands execute result: ${msg_all}")

运行结果: rm: 无法删除 'notexistfile.ext': 没有那个文件或目录 ALL commands execute result: 0;1

  • OUTPUT_VARIABLE, ERROR_VARIABLE:将标准输出和标准错误管道内容分别写入OUTPUT_VARIABLEERROR_VARIABLE指定的变量中,如果指定的是同一个变量,那么会按照执行的顺序合并输出。
EXECUTE_PROCESS(COMMAND echo "start"
 COMMAND rm "notexistfile.ext"
 COMMAND pwd
 COMMAND rm "notexistfile2.ext"
 COMMAND pwd
 WORKING_DIRECTORY "/home"
 RESULTS_VARIABLE msg_result
 OUTPUT_VARIABLE msg_out
 ERROR_VARIABLE msg_err)
MESSAGE("Commands execute results: ${msg_result}")
MESSAGE("Commands output: ${msg_out}")
MESSAGE("Commands error: ${msg_err}")

运行结果:值得注意的是,由于命令是按照管道方式执行,OUTPUT_VARIABLE只会存储最后一个命令的运行结果,而ERROR_VARIABLE则是存储所有错误 Commands execute results: 0;1;0;1;0 Commands output: /home

Commands error: rm: 无法删除 'notexistfile.ext': 没有那个文件或目录 rm: 无法删除 'notexistfile2.ext': 没有那个文件或目录

  • INPUT_FILE:指定文件作为第一个命令的标准输入 OUTPUT_FILE:指定文件作为最后一个命令的标准输出 ERROR_FILE:所有命令运行错误结果存储的文件。
EXECUTE_PROCESS(COMMAND read
 COMMAND rm "noexistfile.ext"
 COMMAND rm "noexistfile2.ext"
 COMMAND echo "write message to output"
 INPUT_FILE input
 OUTPUT_FILE output
 ERROR_FILE error)

output文件内容: write message to output error文件内容: rm: noexistfile.ext: No such file or directory rm: noexistfile2.ext: No such file or directory

  • OUTPUT_QUIET, ERROR_QUIET:忽略标准输出或者标准错误。

  • COMMAND_ECHO <where>3.15版本引入。将运行的命令echoSTDOUT(标准输出)、STDERR(标准错误)、NONE,也可以通过设置变量CMAKE_EXECUTE_PROCESS_COMMAND_ECHO来控制默认值。本例子中将运行的命令(包括参数)都echo到标准出错(不包含命令本身执行的输出),并且通过执行cmake . 2> file_stderr来将标准出错重定位到文件file_stderr中。

EXECUTE_PROCESS(
 COMMAND echo "execute commad"
 COMMAND ls "CMakeLists.txt"
 COMMAND_ECHO STDERR
 )

执行:cmake . 2> file_stderr的命令行输出为(最后一个命令ls的输出仍然在命令行展示): CMakeLists.txt

查看文件file_stderrcat file_stderr 'echo' 'execute commad' 'ls' 'CMakeLists.txt'

  • ENCODING <name>:指定命令执行的输出用何种方式解码,只在Windows下生效。有如下取值:

NONE:默认值,使用CMake内部默认的编码方式(也就是UTF-8)对命令输出进行解码。 AUTO:使用当前的控制台编码方式,如果未找到合法的编码方式,则使用ANSIANSI:使用ANSI方式解码命令输出。 OEM:使用OEM方式解码命令输出。 UTF8UTF-8:使用UTF-8方式解码命令输出(3.11版本引入)。

  • ECHO_OUTPUT_VARIABLE, ECHO_ERROR_VARIABLE:将标准输出或标准错误复制一份到指定的变量(例如通过OUTPUT_VARIABLE指定的变量),而不是重定向。这意味着标准输出或者标准错误仍然会有效。
EXECUTE_PROCESS(
 COMMAND echo "hello world"
 OUTPUT_VARIABLE var_output
 ECHO_OUTPUT_VARIABLE # 如果没有指定这个选项,那么命令行终端不会有"hello world"的打印
 )
MESSAGE("output var: ${var_output}")

运行结果: hello world output var: hello world

  • COMMAND_ERROR_IS_FATAL <ANY|LAST>3.19版本引入。指定当遇到错误时的命令行为。

ANY:任一子命令执行错误,execute_process会停止执行并抛出错误 LAST:最后一个子命令执行错误,execute_process会停止执行抛出错误

EXECUTE_PROCESS(COMMAND pwd
 COMMAND rm "noexistfile.ext"
 COMMAND echo "hello world"
 COMMAND_ERROR_IS_FATAL LAST)

运行结果(最后一个子命令执行成功,LAST选项不会导致CMake抛出错误): rm: noexistfile.ext: No such file or directory hello world

EXECUTE_PROCESS(COMMAND pwd
 COMMAND rm "noexistfile.ext"
 COMMAND echo "hello world"
 COMMAND_ERROR_IS_FATAL ANY)

运行结果(第二个子命令执行失败,ANY选项会导致CMake抛出错误): rm: noexistfile.ext: No such file or directory hello world CMake Error at CMakeLists.txt:21 (execute_process): execute_process failed command indexes:

2: "Child return code: 1"


附录:参考文档

  1. https://cmake.org/cmake/help/latest/command/execute_process.html

相关文章

网友评论

      本文标题:Cmake命令之execute_process

      本文链接:https://www.haomeiwen.com/subject/kkzemdtx.html