如何在使用CMake execute_process()时正确调用MSYS2 Bash命令?

4

问题描述

我在设置一个执行MSYS2 bash命令的CMake external_process()命令时遇到了问题。当我在MSYS2 shell中运行命令$ bash -v ./bootstrap.sh时,命令能够正确运行。但是如果我使用$ cmake -P Run_bash_command.cmake在MSYS2 shell中运行CMake脚本,则命令会在处理过程中出现错误。在CMake文档中发现的一条重要信息让我认为我没有正确地调用bash或者缺少环境变量:

CMake直接使用操作系统API执行子进程。所有参数都被直接传递给子进程。不使用中间shell,因此shell运算符(如>)被视为普通参数。

如果可能的话,我希望能够使用CMake来执行这个命令,因为这个问题是一个更大的CMake超级构建项目的一部分。如果有其他解决问题的方法,只要能够将其包含在超级构建项目的自动化中,我就愿意尝试。非常感谢您的帮助。

Run_bash_command.cmake内容:

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()

环境设置

  • 我按照说明安装了MSYS2 64位,并使用命令pacman -S base-devel git mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain添加了mingw-w64工具链和cmake。
  • 我使用安装在MSYS2上的MinGW-w64 Win64 Shell运行命令。
  • 文件bootstrap.sh来自于libusb github存储库,文件夹c:/bash_test包含主分支的克隆版本。

输出

$ 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文件
  • 通过检查环境PATH变量,确认正确的bash版本已找到
  • 确认MSYS2及其包已更新至最新版本
  • 使用sh代替bash
  • 直接调用autoreconf -ivf,但出现相同问题
  • 使用Unix风格路径而不是Windows风格
1个回答

1
我能使用以下代码解决问题。

Run_bash_command.cmake 内容:

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脚本,我们需要使用&&将这些命令链接在一起,并使用“引号”确保整个命令被正确地读取为一个字符串。

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