Reputation: 71
I am having trouble setting up a CMake external_process() command that executes a MSYS2 bash command. When I am in the MSYS2 shell if I run the command $ bash -v ./bootstrap.sh
the command works correctly. But if I run the CMake script in the MSYS2 shell using $ cmake -P Run_bash_command.cmake
the command errors out part way through the process. An important piece of information I found in the CMake Documentation makes me think that I am not invoking bash correctly or missing an environmental variable:
CMake executes the child process using operating system APIs directly. All arguments are passed VERBATIM to the child process. No intermediate shell is used, so shell operators such as > are treated as normal arguments.
I would like to be able to do this command using CMake if possible as this problem is part of a much larger CMake superbuild project. If there is another approach to solving the problem I am open to suggestions as long as I can include it into the automation of the superbuild project. Any help will be appreciated.
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
output:$ 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
output:$ 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
but this causes the shell to default to the home directory and then it is unable to find the file bootstrap.shsh
instead of bash
autoreconf -ivf
directly, but the same issue occursUpvotes: 4
Views: 2302
Reputation: 71
I was able to fix the issue using the code below.
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
causes the shell to default to the home directory, to get around this I added a change directory cd <path>
command to get us back to the directory where we want to issue the bash command.-c
causes bash to read a command from a string. Since we want to issue two commands, one for change directory and one for running the shell script, we need to use &&
to chain the commands together as well as use "quotation marks" to make sure the entire command is read properly as a string.Upvotes: 1