Это кажется тривиальным вопросом, поскольку CMake - это script язык, общий ответ: строго последовательный. Но я столкнулся с несколькими случаями, когда было важно, когда или в каком порядке CMake анализирует определенные файлы. Поэтому мне интересно:
- Имеется ли доступная документация, описывающая порядок, в котором файлы (включая внутренние файлы CMake) анализируются?
- Является ли порядок файлов в зависимости от версии CMake или некоторых параметров/настроек/окружения CMake, включая. выбранный генератор или хост окружающая среда?
Случаи, к которым я дошел до сих пор, где важна информация выше:
- Файл toolchain анализируется до того, как компилятор будет идентифицирован, поэтому вы должны заполнить некоторые переменные CMake в кеше сначала/в файле инструментальной привязки: кросс-компиляция cmake с конкретным компоновщиком doesn 't передать аргументы в armlink
- Файл toolchain анализируется несколько раз, поэтому, например, многократно печатать сообщения из файла toolchain: toolchain cmake включает несколько файлов
- Изменены часы с переменной видимостью вне вашего основного файла
CMakeLists.txt
: Выполнение команды или макроса в CMake как последний шаг перед завершением этапа "Настроить"
Возможно, вы знаете еще больше.
Чтобы найти ответ, я попробовал следующее: у меня есть простой основной CMakeList.txt, как показано ниже, и запустите cmake --trace …
, чтобы проанализировать порядок разбора.
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)
Когда я запускаю, например, cmake --debug-output --trace -G"Visual Studio 12 2013" -DCMAKE_TOOLCHAIN_FILE:FILE_PATH=Toolchain.txt
Я получил длинный след, который я попытался обобщить:
# 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
Итак, увидев вышеприведенный вывод, я пришел - до сих пор - к следующему выводу (который, я надеюсь, правдивый и несколько общий):
- Файл CMakeCache.txt читается только один раз, когда настройка запускается и записывается после завершения Поколения. Он просто сохраняет состояние кэша "глобальных переменных".
- Команда
project()
запускает большую часть магии обнаружения CMake (включая чтение из файлаToolchain.txt
). - Файл toolchain считывается дважды. Однажды до того, как система make/компиляции обнаружена и один раз внутри созданного тогда
CMakeSystem.cmake
. - Крючок
variable_watch()
может запускаться в любое время, поэтому область, в которой вызывается "команда для выполнения", называется undefined.