我在设置执行MSYS2 bash命令的CMake external_process()命令时遇到问题。当我在MSYS2 shell中运行命令$ bash -v ./bootstrap.sh
时,该命令正常工作。但是如果我使用$ cmake -P Run_bash_command.cmake
在MSYS2 shell中运行CMake脚本,那么命令会在整个过程中出错。我在CMake Documentation中找到的一条重要信息让我觉得我没有正确地调用bash或者错过了一个环境变量:
CMake直接使用操作系统API执行子进程。所有参数都将VERBATIM传递给子进程。没有使用中间shell,因此shell运算符如>被视为正常的论点。
如果可能的话,我希望能够使用CMake执行此命令,因为此问题是更大的CMake superbuild项目的一部分。如果有另一种解决问题的方法,只要我可以将其包含在superbuild项目的自动化中,我就可以接受建议。任何帮助将不胜感激。
SET( ENV{MSYSTEM} MINGW64 )
SET( DIR_CONTAINING_BOOTSTRAP_SH C:/bash_test )
SET( BASH_COMMAND_TO_RUN bash -v ./bootstrap.sh )
EXECUTE_PROCESS( COMMAND ${BASH_COMMAND_TO_RUN}
WORKING_DIRECTORY ${DIR_CONTAINING_BOOTSTRAP_SH} RESULT_VARIABLE command_result )
IF( NOT "${command_result}" STREQUAL "0" )
MESSAGE( FATAL_ERROR "Error: command_result='${command_result}'" )
ENDIF()
pacman -S base-devel git mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain
$ bash -v ./bootstrap.sh
输出:$ bash -v ./bootstrap.sh
#!/bin/sh
if ! test -d m4 ; then
mkdir m4
fi
autoreconf -ivf || exit 1
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I m4
autoreconf: configure.ac: tracing
autoreconf: running: libtoolize --copy --force
libtoolize: putting auxiliary files in '.'.
libtoolize: copying file './ltmain.sh''
...<clipped output due to length>...
configure.ac:29: installing './install-sh'
configure.ac:29: installing './missing'
examples/Makefile.am: installing './depcomp'
autoreconf: Leaving directory `.'
$ cmake -P Run_bash_command.cmake
输出:$ cmake -P Run_bash_command.cmake
#!/bin/sh
if ! test -d m4 ; then
mkdir m4
fi
autoreconf -ivf || exit 1
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I m4
aclocal-1.15: error: aclocal: file '/msys64/usr/share/aclocal/xsize.m4' does not exist
autoreconf: aclocal failed with exit status: 1
CMake Error at Run_bash_command.cmake:10 (MESSAGE):
Error: command_result='1'
bash -l -c
但这会导致shell默认为主目录,然后无法找到文件bootstrap.sh sh
代替bash
autoreconf -ivf
但发生同样的问题答案 0 :(得分:1)
我能够使用下面的代码解决问题。
SET( DIR_CONTAINING_BOOTSTRAP_SH /C/bash_test )
SET( BASH_COMMAND_TO_RUN bash -l -c "cd ${DIR_CONTAINING_BOOTSTRAP_SH} && sh ./bootstrap.sh" )
EXECUTE_PROCESS( COMMAND ${BASH_COMMAND_TO_RUN}
WORKING_DIRECTORY ${DIR_CONTAINING_BOOTSTRAP_SH} RESULT_VARIABLE command_result )
IF( NOT "${command_result}" STREQUAL "0" )
MESSAGE( FATAL_ERROR "Error: command_result='${command_result}'" )
ENDIF()
bash -l
会导致shell默认为主目录,为了解决这个问题,我添加了一个更改目录cd <path>
命令,让我们回到我们想要发出bash命令的目录。 -c
会导致bash从字符串中读取命令。由于我们要发出两个命令,一个用于更改目录,另一个用于运行shell脚本,我们需要使用&&
将命令链接在一起以及使用“引号”以确保读取整个命令正确地作为一个字符串。