[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