CMake: в каком порядке обрабатываются файлы (кеш, toolchain и т. Д.)?

Это кажется тривиальным вопросом, поскольку CMake – это язык сценария, общий ответ: строго последовательный. Но я столкнулся с несколькими случаями, когда было важно, когда или в каком порядке CMake анализирует определенные файлы. Поэтому мне интересно:

  1. Есть ли доступная документация, описывающая порядок обработки файлов (включая внутренние файлы CMake)?
  2. Является ли порядок файлов в зависимости от версии CMake или некоторых параметров / настроек / окружения CMake, включая. выбранного генератора или среды хоста?

Случаи, к которым я дошел до сих пор, где важна информация:

  • Файл toolchain анализируется до того, как компилятор будет идентифицирован, поэтому вам необходимо заполнить некоторые переменные CMake в кеше сначала / в файле инструментальной привязки: кросс-компиляция CMake с конкретным компоновщиком не передает аргументы в armlink
  • Файл toolchain анализируется несколько раз, поэтому, например, печать сообщений из файла инструментальной привязки выполняется несколько раз: инструментальная цепочка CMake включает в себя несколько файлов
  • Переменные часы можно вызывать из области вне вашего основного файла CMakeLists.txt Был проанализирован: выполнить команду или макрос в CMake в качестве последнего шага перед тем, как завершится шаг «configure»

Возможно, вы знаете еще больше.

Чтобы найти ответ, я попробовал следующее: у меня есть простой основной CMakeLists.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_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 

Поэтому, увидев вышеупомянутый вывод, я пришел – до сих пор – к следующему выводу (который, я надеюсь, правдивый и несколько общий):

  1. Файл CMakeCache.txt считывается только один раз, когда настройка запускается и записывается после завершения генерации. Он просто сохраняет состояние кеша «глобальных переменных».
  2. Команда project() запускает большую часть магии обнаружения CMake (включая чтение из файла Toolchain.txt ).
  3. Файл toolchain считывается дважды. Однажды до того, как система make / компиляции обнаружена и один раз внутри созданной CMakeSystem.cmake .
  4. Ключ variable_watch() может запускаться в любое время, поэтому область, в которой вызывается оптимальная команда «выполнить», не определена.

Нет официальной документации об этой конкретной внутренней работе CMake, поэтому, пожалуйста, найдите ниже резюме того, что я узнал о CMake до сих пор …

Какие файлы анализируются, зависит от

  1. Хост и целевая операционная система
  2. Целевой компилятор
  3. Окружающая среда вашего компьютера (переменные, реестр, установленное программное обеспечение)
  4. Файлы сценария CMake вашего проекта, которые могут включать
    1. Ваш файл toolchain
    2. Ваши выбранные языки программирования
    3. Любые внешние проекты / библиотеки / файлы / скрипты

Существует множество возможных комбинаций этих параметров, но большую часть времени CMake делает все возможное, чтобы автоматически определять правильные настройки для вас, и вам не нужно беспокоиться о том, как это делается. Хорошая новость – когда вам нужно знать – это следует за некоторыми внутренними узорами.

Интересно, что он лишь незначительно зависит от выбранного вами генератора CMake .

Начальный шаг: обнаружение и проверка компилятора

Это главным образом начинается с команды project() . В качестве примера, используя язык CXX , основные файлы для обнаружения компилятора (см. Также корневые файлы в выводе трассировки вопроса):

  • share/cmake-xy/Modules/CMakeDetermineCXXCompiler.cmake

    Это в основном пытается определить местоположение исполняемого файла компилятора и вызывает его для получения более конкретного идентификатора компилятора.

    Кроме того, он, например, определяет расширения исходного / выходного файла на основе среды хост-компьютера и целевой операционной системы.

  • share/cmake-xy/Modules/CMakeCXXCompiler.cmake.in

    Это шаблон для хранения результата обнаружения компилятора в ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/xyz/CMakeCXXCompiler.cmake .

    Главным образом эти переменные: CMAKE_CXX_COMPILER , CMAKE_CXX_SOURCE_FILE_EXTENSIONS , CMAKE_CXX_IGNORE_EXTENSIONS и CMAKE_CXX_COMPILER_ENV_VAR

  • share/cmake-xy/Modules/CMakeCXXInformation.cmake

    Этот файл устанавливает базовые флаги для компилятора. Кроме того, компилятор, хост и цель оказывают наибольшее влияние на настройку с такими вызовами:

     include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL) include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX OPTIONAL) include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL) include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) 
  • share/cmake-xy/Modules/CMakeTestCXXCompiler.cmake

    Это проверяет все и, например, определяет возможности компилятора, фактически вызывая компилятор в простых сгенерированных проектах CMake.

Результаты этих шагов хранятся в кэшированных переменных, и эти файлы являются особыми в этом случае, они защищены такими переменными, как CMAKE_CXX_COMPILER_LOADED , CMAKE_CXX_INFORMATION_LOADED или CMAKE_CXX_COMPILER_WORKS чтобы не запускаться с каждым последующим шагом конфигурации CMake еще раз.

Файлы конфигурации проекта: изменение настроек по умолчанию

Существует несколько способов изменить значения по умолчанию CMake, не CMakeLists.txt файлам CMakeLists.txt вашего проекта.

  • -C вариант командной строки

    Это можно использовать, если вы хотите дать некоторые предустановленные значения (вы обычно передавали бы через -D ... ) через несколько проектов снова и снова. Как некоторые пути поиска библиотеки на вашем компьютере или некоторые пресеты, используемые в вашей компании.

  • CMakeCache.txt например, cmake-gui

    cmake-gui позволяет вручную изменять параметры вашего проекта (редактирование всех не внутренних переменных в CMakeCache.txt ), прежде чем вы, наконец, CMakeCache.txt среду сборки.

  • CMAKE_TOOLCHAIN_FILE

    В основном используется для кросс-компиляции , но в более общем смысле это может быть указано как заданные значения для используемой инструментальной привязки компилятора.

  • PreLoad.cmake

    Более или менее то же, что и опция «начального кеша» (см. Выше), но она не предоставляется через параметр командной строки. Он должен находиться в том же каталоге, что и CMakeLists.txt вашего проекта.

    Примечание . Он поддерживает все команды сценария CMake, такие как вызовы if() , но PreLoad.cmake имеет свои

    • собственный диапазон переменных (все не кэшированные здесь не видны в вашем основном CMakeLists.txt )
    • ограничения, которые уже известны (он работает до всего остального, поэтому в основном вы можете проверить CMAKE_GENERATOR )
  • CMAKE_USER_MAKE_RULES_OVERRIDE , CMAKE_USER_MAKE_RULES_OVERRIDE_

    Это позволяет изменять неизменяемые значения по умолчанию после автоматического обнаружения CMake.

    Пример . Расширение допустимых расширений исходного файла .c файлов .c

    MakeRulesOverwrite.cmake

     list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c) 

    Затем вы можете вызвать cmake с чем-то вроде

     > cmake -D CMAKE_USER_MAKE_RULES_OVERRIDE:PATH=..\MakeRulesOverwrite.cmake .. 
  • CMAKE_PROJECT_ParserTest_INCLUDE

    Это предназначено для «ввода пользовательского кода в сборку проекта без изменения его источника» непосредственно после обработки команды project() (и была обнаружена среда сборки).

Toolchain.cmake: разобрано несколько раз

Файл toolchain считывается несколько раз при определении системы, компилятора и т. Д.

Важно знать:

  • Он считывается с каждым try_compile() . И так как try compile должен создать допустимый исполняемый файл, вам может понадобиться – если вы, например, перекрестно-компилируете – на

    • CMAKE_TRY_COMPILE_TARGET_TYPE в STATIC_LIBRARY (версия CMake версии 3.6 или выше)
    • Проверьте глобальное свойство IN_TRY_COMPILE чтобы добавить дополнительные параметры
  • Если вы измените файл инструментальной привязки, CMake снова запустит обнаружение компилятора (как в предыдущей строке). Что глубоко помогает играть со своими настройками компилятора.

Реадаптация CMake: все происходит из кэша

И последнее, но не менее важное: важно знать, что вышеприведенный след показывает только начальный шаг. Все последовательные конфигурации проектов будут занимать почти все, начиная с кэшированных переменных и, следовательно, будут читать гораздо меньше файлов в ходе повторной настройки конфигурации.

Рекомендации

  • Архитектура приложений с открытым исходным кодом: CMake
  • Общее правило от makefile до cmake
  • Ошибка CMake в CMakeLists.txt: 30 (проект): не найдено CMAKE_C_COMPILER
  • Как добавить библиотеки boost в CMakeLists.txt
  • CMake не находит компилятор Visual C ++
  • Как настроить CMake для создания приложения для iPhone
  • Невозможно указать компилятор с помощью CMake
  • Как связать программу на C ++ с помощью Boost с помощью CMake
  • OpenCV как статическая библиотека (cmake)
  • Как скопировать DLL-файлы в ту же папку, что и исполняемый файл, используя CMake?
  • Почему файл cmake GLOB-зло?
  • CMake: Какое использование find_package (), если вам нужно указать CMAKE_MODULE_PATH?
  • Как обнаружить поддержку C ++ 11 компилятора с помощью CMake
  • CMake: Как получить имя всех подкаталогов каталога?
  • Interesting Posts

    Карта Thinkpad W500 ATI не запускается в Windows 7 64-бит

    Обнаружение аппаратного обеспечения и установка драйверов в Windows XP

    Использовать самоподписанный сертификат cURL?

    Основы того, как заставить процедуру VBA работать в excel при изменении ячейки

    Разница между каждым экземпляром сервлета и каждым streamом сервлета в сервлетах?

    Как создать случайный номер int в C #?

    C # Добавить массив байтов в существующий файл

    Силовой неmonoпольный шрифт в фиксированную ширину с использованием CSS

    Как безопасно удалить диск eSATA, когда он не находится в диалоговом окне «Безопасное извлечение оборудования»

    Захват запросов SOAP для веб-службы ASP.NET ASMX

    Вернуться к основному виду деятельности, связанной с созданием уведомлений

    Что такое алгоритм JVM Scheduling?

    ServiceStack vs ASP.Net Web API

    jackson: Что произойдет, если имущество отсутствует?

    Добавить задержку на ярлык на рабочем столе

    Давайте будем гением компьютера.