【问题标题】:cmake execute_process cannot find source commandcmake execute_process 找不到源命令
【发布时间】:2015-03-14 20:43:58
【问题描述】:

我最近在 cmake 中遇到了一个非常有趣的问题。 问题如下:

我有一个 CMakeLists.txt,它定义了一个相当简单的项目。我希望能够在构建项目时设置一个 linux 环境变量。为此,我想调用一个小脚本var_set.sh 来完成它。它看起来像这样:

#!/bin/bash
MY_VAR=$1
export MY_VAR

在CMakeLists.txt我运行如下:

execute_process(COMMAND source var_set.sh VALUE
            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
            RESULT_VARIABLE variable_RESULT)
message(STATUS ${variable_RESULT})
message(STATUS $ENV{MY_VAR})

这个的输出是

-- No such file or directory

我认为问题出在source 命令上。如果我使用./var_set.sh 而不是source var_set.sh,脚本实际上会被执行,但是,当然,我无法获得我想要导出的变量。

有人知道这种行为的原因是什么吗?

UPD:

我了解到,可能根本不可能实现我最初想要的。

最初的想法和动机如下。我们有一个使用 ROS 的比较大的项目。它使用 catkin_make 构建一切。它的基本作用是按照 CMakeLists.txt 和 package.xml 文件定义的顺序为它在子文件夹中找到的所有包调用一个 cmake(在这里看起来如何并不重要)。它还提供了一种覆盖方式来使用 find_package 等。

问题在于,有很大一部分代码是以我无法影响的方式编写的。这部分依赖于一个库 G2O(图优化)并且 G2O 包没有“catkinized”,即 catkin 无法知道提供了哪些库。

G2O 本身定义了相当多的库,我们可以通过 FindG2O.cmake 文件找到它们(但如果一个库是“核心”,我们通过 FindG2O.cmake 中设置的名称“G2O_CORE_LIBRARY”知道它)。我们还使用环境变量“G2O_ROOT”来指向当前的 g2o 安装。

我的想法是在构建 G2O 时设置此环境变量(使用包裹在其周围的 catkin 元包),并将这些知识提供给之后构建的任何人,因为这样可以轻松使用 FindG2O.cmake。

我知道这个解释很混乱。有不清楚的地方请追问。

似乎我想要实现的目标是不可能的,因为 catkin_make 可能会在不同的子进程中调用不同的 cmake,然后,当然,我无法修改父进程。

【问题讨论】:

  • 为什么不通过 cmake 的 $ENV{ 设置变量。您在哪里找到源关键字?它不在cmake.org/cmake/help/v3.0/command/execute_process.html的官方文档中
  • 您好,谢谢您的回答。嗯,我确实尝试使用 $ENV{}。问题是在当前调用之后的下一个 cmake 看不到它。请参阅 UPD。

标签: linux bash cmake global-variables


【解决方案1】:

你只是做错了。即使source 可以工作(但它不能,因为它是bash 内部命令,而不是文件系统中的真正二进制/可执行文件),它不会影响任何东西!因为cmake 启动了一个子进程(通过execute_process())并且它将被终止,执行结果在相应的变量中可用。 在子进程中设置任何环境变量都不会影响父环境。

因此,您最好使用$ENV{blah} 来设置所需的变量。或者(更好)只使用 CMake 变量......有很多方法可以做到这一点。只需提供更多详细信息即可实现。

【讨论】:

  • 您好,谢谢您的回答!我已经用更多细节更新了这个问题。我确实明白这不是使用 cmake 的预期方式,而且在理智的情况下,我什至不会尝试做这种肮脏的魔法。但是当您使用相对较旧的代码并希望将其连接到使用新构建系统的一堆新代码时,它会变得更加混乱。如果你问我,我会坚持使用纯 CMake,但这显然不是他们在 ROS 中的做法。
【解决方案2】:

使用execute_process 的OUTPUT_VARIABLE 选项。

让你的脚本看起来像这样:

#!/bin/bash
MY_VAR=$1
echo "$MY_VAR"

并在您的CMakeLists.txt 中使用它,如下所示:

cmake_minimum_required(VERSION 2.6)
execute_process(COMMAND sh "var_set.sh" "VALUE" "VALUE2"
            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
            RESULT_VARIABLE variable_RESULT
            OUTPUT_VARIABLE variable_OUTPUT
)

message(STATUS ${variable_RESULT})
message(STATUS ${variable_OUTPUT})

CMake 配置步骤的输出是:

-- The C compiler identification is GNU 5.1.1
-- The CXX compiler identification is GNU 5.1.1
-- Check for working C compiler: /usr/lib64/ccache/cc
-- Check for working C compiler: /usr/lib64/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib64/ccache/c++
-- Check for working CXX compiler: /usr/lib64/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- 0
-- VALUE

-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/out

这种方法的一个缺点是您必须在脚本中抑制所有不需要的输出。或者,使用 OUTPUT_FILE 并对文件进行后处理。

【讨论】:

    猜你喜欢
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多