CMake的execute_process无法找到source命令。

3

我最近在使用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”,脚本实际上会被执行,但当然,我无法获得所需的导出变量。
有人知道这种行为的原因吗?
更新:
我意识到最初想要的可能根本不可能实现。
最初的想法和动机如下。我们有一个相对较大的项目使用ROS。它使用catkin_make来构建所有内容。它基本上是按照CMakeLists.txt和package.xml文件定义的顺序调用所有子文件夹中找到的包的cmake(这里不重要)。它还提供了一种覆盖方式来使用find_package等。
问题是代码的一个重要部分是以我无法影响的方式编写的。这一部分依赖于图优化库G2O(Graph Optimization),而G2O包未经过“catkin化”,即catkin无法知道提供哪些库。
G2O本身定义了相当数量的库,我们通过FindG2O.cmake文件可以找到它们(但如果库是“core”,那么我们会使用FindG2O.cmake中设置的“G2O_CORE_LIBRARY”名称进行了解)。我们还使用一个环境变量“G2O_ROOT”来指向当前的g2o安装。
我的想法是在构建G2O时设置此环境变量(使用包装在其周围的catkin元包),并使这些知识对于后续构建的任何人都可用,因为这将使FindG2O.cmake的使用变得容易。
我理解这种解释非常混乱。如果有不清楚的,请问一下。
似乎我试图实现的是不可能的,因为catkin_make可能会在不同的子进程中调用不同的cmake,然后,当然,我无法修改父进程。

为什么不通过cmake的$ENV{}来设置变量?你在哪里找到了source关键字?官方文档http://www.cmake.org/cmake/help/v3.0/command/execute_process.html中并没有提到它。 - arved
嘿,谢谢你的回答。嗯,我确实尝试使用了$ENV{}。问题是在当前cmake之后调用的下一个cmake看不到它。请参见UPD。 - niosus
2个回答

3
你做错了。即使能够工作(但它不能,因为它是bash内部命令,而不是您的文件系统中实际存在的二进制/可执行文件),也不会影响任何事情!因为cmake启动一个子进程(通过execute_process()),并且该进程将被终止,同时执行结果将在相应的变量中可用。在子进程中设置任何环境变量都不会影响父环境
因此,你最好使用$ENV{blah}来设置所需的变量。或者(更好的方法)只需使用CMake变量...有很多方法可以做到这一点。只需提供更多详细信息,你想要实现什么。

嗨,感谢你的回答!我已经用更多的细节更新了问题。我明白这不是使用cmake的预期方式,在正常情况下,我甚至都不会尝试做这样的“魔法”。但是当你正在使用相对旧的代码并希望将其连接到一堆使用新构建系统的新代码时,情况会变得更加混乱。如果你问我的话,我会坚持纯CMake,但显然在ROS中他们不是这样做的。 - niosus

1
使用 execute_processOUTPUT_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并对文件进行后处理。

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