4

Problem Description

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.

Run_bash_command.cmake contents:

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

Environment Setup

  • I followed the directions to setup MSYS2 64bit and added the mingw-w64 toolchain as well as cmake using the command pacman -S base-devel git mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain
  • To run the commands I use the MinGW-w64 Win64 Shell that is installed with MSYS2
  • The file bootstrap.sh comes from the libusb github repository and the folder c:/bash_test contains a clone of the master branch

Output

$ 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'

Things I have tried:

  • Substituting bash -l -c but this causes the shell to default to the home directory and then it is unable to find the file bootstrap.sh
  • Verified the correct version of bash is found by inspecting my environmental PATH varaiable
  • Verified MSYS2 and its packages are up to date
  • Using sh instead of bash
  • Calling autoreconf -ivf directly, but the same issue occurs
  • Using Unix style paths instead of Windows style

1 Answer 1

1

I was able to fix the issue using the code below.

Run_bash_command.cmake contents:

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

Important Notes:

  • Using 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.
  • Using -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.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.