[CMake] execute_process seems to execute in parallel and also only shows output of last command

xyzdragon at fastmail.fm xyzdragon at fastmail.fm
Thu Mar 24 07:58:52 EDT 2016


I'm using cmake --version
    cmake version 3.5.0

# First let me tell you, what I wanted to achieve:

I wanted to recursively build some submodule, if that makes sense or not
should be the matter here:

    execute_process( COMMAND cmake ..
                     COMMAND make
                     WORKING_DIRECTORY ./submodule )

What I found is that a folder CMakeFiles was created in ./submodule, but
there were no other files in ./submodule, especially no Makefile, which
made the second command quit with an error message:

    make: *** No targets specified and no makefile found.  Stop.

# What I expected it to do

The CMake 3.5.0 documentation specifies the execute_process command like
this:

    execute_process(COMMAND <cmd1> [args1...]]
                    [COMMAND <cmd2> [args2...] [...]]
                    [WORKING_DIRECTORY <directory>]
                    [...] )

This mail here clarifies that all commands should be run sequentially:
https://cmake.org/pipermail/cmake/2009-June/030158.html

# Here is a minimal non-working example

./CMakeLists.txt:
    cmake_minimum_required(VERSION 3.5)
    execute_process(
        COMMAND echo  "test1"
        COMMAND touch "test1"
        COMMAND sleep 4s
        COMMAND echo  "test2"
        COMMAND touch "test2"
        COMMAND sleep 4s
        COMMAND echo  "test4"
    )

    execute_process(
        COMMAND mkdir -p build
    )

    execute_process(
        COMMAND cmake .
        COMMAND make
        WORKING_DIRECTORY "./build"
    )

./build/CMakeLists.txt
    cmake_minimum_required(VERSION 3.5)
    execute_process(
        COMMAND echo  "build/test1"
        COMMAND touch "test1"
        COMMAND sleep 4s
        COMMAND echo  "build/test2"
        COMMAND touch "test2"
        COMMAND sleep 4s
        COMMAND echo  "build/test4"
    )

Now make a testrun with `time cmake .`:
    test4
    make: *** No targets specified and no makefile found.  Stop.
    -- Configuring done
    -- Generating done
    -- Build files have been written to: ~/cmakeExecuteProcessTest

    real    0m4.141s
    user    0m0.104s
    sys     0m0.016s

After this run the directory structure is as follows (`find . -type f
-exec bash -c 'ls --full-time {}' \;`):

    16:40:37.673199038 ./CMakeFiles/feature_tests.bin
    17:16:51.452163375 ./CMakeFiles/TargetDirectories.txt
    17:16:51.452163375 ./CMakeFiles/Makefile.cmake
    16:40:36.757185936
    ./CMakeFiles/3.5.0/CMakeDetermineCompilerABI_C.bin
    16:40:36.429181244 ./CMakeFiles/3.5.0/CMakeSystem.cmake
    16:40:37.233192745
    ./CMakeFiles/3.5.0/CMakeDetermineCompilerABI_CXX.bin
    16:40:37.681199152 ./CMakeFiles/3.5.0/CMakeCXXCompiler.cmake
    16:40:36.449181531 ./CMakeFiles/3.5.0/CompilerIdC/CMakeCCompilerId.c
    16:40:36.485182046 ./CMakeFiles/3.5.0/CompilerIdC/a.out
    16:40:36.997189369 ./CMakeFiles/3.5.0/CMakeCCompiler.cmake
    16:40:36.517182503
    ./CMakeFiles/3.5.0/CompilerIdCXX/CMakeCXXCompilerId.cpp
    16:40:36.589183533 ./CMakeFiles/3.5.0/CompilerIdCXX/a.out
    17:16:51.452163375 ./CMakeFiles/progress.marks
    17:16:51.452163375 ./CMakeFiles/cmake.check_cache
    16:40:37.677199094 ./CMakeFiles/CMakeOutput.log
    17:16:51.452163375 ./CMakeFiles/Makefile2
    16:40:36.921188282 ./CMakeFiles/feature_tests.c
    16:40:37.537197092 ./CMakeFiles/feature_tests.cxx
    16:41:16.213750307 ./CMakeFiles/CMakeDirectoryInformation.cmake
    17:16:09.227562260 ./build/CMakeLists.txt
    17:16:51.368162180 ./build/CMakeFiles/3.5.0/CMakeSystem.cmake
    17:16:51.396162579
    ./build/CMakeFiles/3.5.0/CompilerIdC/CMakeCCompilerId.c
    17:16:51.440163206 ./build/CMakeFiles/3.5.0/CompilerIdC/a.out
    17:16:51.452163375 ./build/CMakeFiles/CMakeOutput.log
    17:16:45.900084334 ./CMakeLists.txt
    16:40:37.685199210 ./CMakeCache.txt
    16:41:16.213750307 ./cmake_install.cmake
    17:16:47.328104663 ./test1
    17:16:47.332104722 ./test2
    17:16:51.452163375 ./Makefile

First things to note:

  - ./test1, ./test2 do exist, meaning all commands seem to have run
  - ./build/test1 and ./build/test2 don't exist, meaning `cmake ..`
  didn't run completely
  - only build/CMakeFiles/ exists, but not other files, especially not
  build/Makefile
  - the timestamps of test1 and test2 are definitely not 4s apart,
  meaning it looks like all commands did run in parallel
  - the time needed by CMake is 4s not 8s like it should be if both
  `sleep 4s` commands would have been executed sequentially
  - only "test4" will be printed, meaning the output of all commands
  except the last specified in `execute_process` is ignored

# Further Test:

Changing the order in:

    execute_process(
        COMMAND cmake .
        COMMAND make
        WORKING_DIRECTORY "./build"
    )

to:

    execute_process(
        COMMAND make
        COMMAND cmake .
        WORKING_DIRECTORY "./build"
    )

Will make result in a Makefile being created and no error message being
produced by Makefile.
This suggests, that the last command is spawned before the command
before it, meaning the other way around like intuitively suggested.
Although I find it a bit weird, that there seems to be an order, even
though the results above suggest all commands are executed in parallel.
It seems the short latency between spawning is enough for `cmake .` to
finish before `make` is begin spawned.

# Workarounds

Don't group multiple commands

    execute_process( COMMAND cmake ..
                     WORKING_DIRECTORY ./submodule )
    execute_process( COMMAND make
                     WORKING_DIRECTORY ./submodule )

For many commands using the same WORKING_DIRECTORY this leads to extreme
code bloat though.

-- 
http://www.fastmail.com - The professional email service



More information about the CMake mailing list