This seems as a trivial question, since CMake is a script language the general answer is: strictly sequential. But I came across several cases where it was important when or in which order CMake is parsing certain files. So I wonder:
- Is there a documentation available that describes the order in which files (incl. internal CMake files) are parsed?
- Is the file order depending on the CMake version or some CMake options/settings/environment incl. the chosen generator or host environment?
The cases I came across so far, where the above information was important:
- The toolchain file is parsed before the compiler is identified, so you have to populate certain CMake variables in the cache first/in the toolchain file: CMake cross-compile with specific linker doesn't pass arguments to armlink
- The toolchain file is parsed multiple times, therefore e.g. printing messages from the toolchain file show multiple times: CMake toolchain includes multiple files
- Variable watch can be called from a scope outside your main
CMakeLists.txtfile has been parsed: Execute command or macro in CMake as the last step before the 'configure' step finishes
Maybe you know even more.
To find an answer, I have tried the following: I have setup a simple main CMakeLists.txt as shown below and run cmake --trace … to analyze the parsing order.
cmake_minimum_required(VERSION 2.8) include(BeforeProjectCmd.cmake) project(ParserTest CXX) add_subdirectory(LibTarget1) add_subdirectory(LibTarget2) add_executable(ExeTarget Test.cpp) variable_watch(CMAKE_BACKWARDS_COMPATIBILITY) When I then run e.g. cmake --debug-output --trace -G"Visual Studio 12 2013" -DCMAKE_TOOLCHAIN_FILE:FILE_PATH=Toolchain.txt I got a long trace that I tried to summarize:
# Begin try to read CMakeCache.txt ${CMAKE_BINARY_DIR}/CMakeCache.txt PreLoad.cmake ${CMAKE_BINARY_DIR}/PreLoad.cmake # End try to read ┌ CMakeLists.txt(1): cmake_minimum_required(VERSION 2.8 ) │ CMakeLists.txt(3): include(BeforeProjectCmd.cmake ) │ ├─ BeforeProjectCmd.cmake │ │ CMakeLists.txt(5): project(ParserTest CXX ) ├┬ share/cmake-3.2/Modules/CMakeDetermineSystem.cmake ││ │└─ Toolchain.txt │ ├┬ ${CMAKE_PLATFORM_INFO_DIR}/CMakeSystem.cmake ││ │└─ Toolchain.txt │ ├─ share/cmake-3.2/Modules/CMakeSystemSpecificInitialize.cmake ├┬ share/cmake-3.2/Modules/CMakeDetermineCXXCompiler.cmake │├┬ share/cmake-3.2/Modules/CMakeDetermineCompiler.cmake ││├ share/cmake-3.2/Modules/Platform/Windows-CXX.cmake … ││├ share/cmake-3.2/Modules/CMakeDetermineCompilerId.cmake ││├─ share/cmake-3.2/Modules/CMakeCompilerIdDetection.cmake … ││├ share/cmake-3.2/Modules/Compiler/MSVC-DetermineCompiler.cmake … │├ ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/3.2.2/CMakeCXXCompiler.cmake │├ share/cmake-3.2/Modules/CMakeSystemSpecificInformation.cmake │├┬ share/cmake-3.2/Modules/CMakeGenericSystem.cmake ││├ share/cmake-3.2/Modules/Platform/Windows.cmake ││└─ share/cmake-3.2/Modules/Platform/WindowsPaths.cmake │├ share/cmake-3.2/Modules/CMakeCXXInformation.cmake │├┬ share/cmake-3.2/Modules/Compiler/MSVC-CXX.cmake ││├ share/cmake-3.2/Modules/Platform/Windows-MSVC-CXX.cmake ││├┬ share/cmake-3.2/Modules/Platform/Windows-MSVC.cmake │││└─ share/cmake-3.2/Modules/CMakeRCInformation.cmake ││└ share/cmake-3.2/Modules/CMakeCommonLanguageInclude.cmake │├ share/cmake-3.2/Modules/CMakeTestCXXCompiler.cmake │├┬ share/cmake-3.2/Modules/CMakeTestCompilerCommon.cmake ││├ share/cmake-3.2/Modules/CMakeDetermineCompilerABI.cmake ││├ share/cmake-3.2/Modules/CMakeDetermineCompileFeatures.cmake ││├ share/cmake-3.2/Modules/Internal/FeatureTesting.cmake ││└ share/cmake-3.2/Modules/Compiler/MSVC-CXX-FeatureTests.cmake │└ ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/3.2.2/CMakeCXXCompiler.cmake │ │ CMakeLists.txt(7): add_subdirectory(LibTarget1 ) │ ├─ LibTarget1/CMakeLists.txt │ │ CMakeLists.txt(8): add_subdirectory(LibTarget2 ) │ ├─ LibTarget2/CMakeLists.txt │ │ CMakeLists.txt(10): add_executable(ExeTarget Test.cpp ) │ CMakeLists.txt(12): variable_watch(CMAKE_BACKWARDS_COMPATIBILITY ) │ │ CMake Debug Log in CMakeLists.txt: │ Variable "CMAKE_BACKWARDS_COMPATIBILITY" was accessed using UNKNOWN_READ_ACCESS with value "". -- Configuring done -- Generating ${CMAKE_BINARY_DIR} -- Generating ${CMAKE_BINARY_DIR}/LibTarget1 -- Generating ${CMAKE_BINARY_DIR}/LibTarget2 -- Generating done # Writes ${CMAKE_BINARY_DIR}/CMakeCache.txt So seeing the above output I came - so far - to following conclusion (which I hope are true and somewhat generic):
- The CMakeCache.txt file is only read once when configuration is started and written after the generation is finished. It just persists the state of the "global variables" cache.
- The
project()command trigger most of CMake's detection magic (including reading from theToolchain.txtfile). - The toolchain file is read twice. Once before the make/compile system is detected and once inside the then generated
CMakeSystem.cmake. - The
variable_watch()hook can trigger anytime, so the scope in which the optimal "command to execute" is called is undefined.