Spec-Zone.ru › CMake 3.23

FetchContent

Новое в версии 3.11.

  • Обзор
  • Команды
  • Переменные
  • Примеры

Обзор

Этот модуль позволяет заполнять содержимое во время конфигурации с помощью любого метода, поддерживаемого модулем ExternalProject. В то время как ExternalProject_Add() загружает данные во время сборки, модуль FetchContent делает содержимое доступным немедленно, что позволяет шагу конфигурации использовать содержимое в командах, таких как add_subdirectory(), include() или операциях file().

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

Следующий пример демонстрирует типичное объявление деталей содержимого для некоторых зависимостей и последующее их заполнение отдельным вызовом:

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
FetchContent_Declare(
  myCompanyIcons
  URL      https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
  URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)

FetchContent_MakeAvailable(googletest myCompanyIcons)

Команда FetchContent_MakeAvailable() гарантирует, что указанные зависимости были заполнены (либо ранее, либо заполнены сами). При выполнении заполнения она также добавит их в основную сборку, если это возможно, так что основная сборка сможет использовать цели, и т. д. заполненных проектов. См. документацию команды для получения подробностей об этих шагах.

При использовании иерархической структуры проектов проекты на более высоких уровнях иерархии могут переопределять объявленные детали содержимого, указанные где-либо ниже в иерархии проекта. Первые объявленные детали для данной зависимости имеют приоритет, независимо от того, где в иерархии проекта они появляются. Аналогично, первый вызов, пытающийся заполнить зависимость, «выигрывает», и последующие заполнения повторно используют результат первого, а не повторяют заполнение снова. См. Примеры, демонстрирующие эту ситуацию.

В некоторых случаях основному проекту может потребоваться более точный контроль над заполнением, или может потребоваться явно определить шаги заполнения способом, который не может быть захвачен только объявленными деталями. Для таких ситуаций можно использовать команды нижнего уровня FetchContent_GetProperties() и FetchContent_Populate(). Однако они не обладают более широкими возможностями, предоставляемыми FetchContent_MakeAvailable(), поэтому их прямое использование следует рассматривать как крайнюю меру. Типичный шаблон таких пользовательских шагов выглядит следующим образом:

# NOTE: Where possible, prefer to use FetchContent_MakeAvailable()
#       instead of custom logic like this

# Check if population has already been performed
FetchContent_GetProperties(depname)
if(NOT depname_POPULATED)
  # Fetch the content using previously declared details
  FetchContent_Populate(depname)

  # Set custom variables, policies, etc.
  # ...

  # Bring the populated content into the build
  add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR})
endif()

Модуль FetchContent также поддерживает определение и заполнение содержимого в одном вызове без проверки того, было ли содержимое уже заполнено где-либо еще. Это не должно делаться в проектах, но может быть уместно для заполнения содержимого в режиме сценариев CMake. См. FetchContent_Populate() для получения подробностей.

Команды

FetchContent_Declare
FetchContent_Declare(<name> <contentOptions>...)

Функция FetchContent_Declare() записывает параметры, описывающие, как заполнить указанное содержимое. Если такие детали уже были записаны ранее в этом проекте (независимо от места в иерархии проекта), этот и все последующие вызовы для того же содержимого <name> игнорируются. Этот подход «первый записанный, выигрывает» позволяет иерархическим проектам иметь родительские проекты, переопределяющие детали содержимого дочерних проектов.

Содержимое <name> может быть любой строкой без пробелов, но хорошей практикой будет использовать только буквы, цифры и символы подчеркивания. Имя будет обрабатываться без учета регистра и должно быть очевидным для представляемого содержимого, часто являясь именем дочернего проекта или значением, заданным для его команд project() (если это проект CMake). Для известных публичных проектов имя должно, как правило, соответствовать официальному названию проекта. Выбор необычного имени затрудняет вероятность того, что другие проекты, нуждающиеся в том же содержимом, будут использовать то же имя, что приведет к многократному заполнению содержимого.

<contentOptions> может быть любым из параметров загрузки, обновления или исправления, которые понимает команда ExternalProject_Add(). Шаги конфигурации, сборки, установки и тестирования явно отключены, и поэтому связанные с ними параметры будут проигнорированы. Параметр SOURCE_SUBDIR является исключением, см. FetchContent_MakeAvailable() для получения подробностей о влиянии этого на поведение.

В большинстве случаев <contentOptions> будет состоять всего из пары параметров, определяющих метод загрузки и детали метода, такие как тег коммита или хеш архива. Например:

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)

FetchContent_Declare(
  myCompanyIcons
  URL      https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
  URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)

FetchContent_Declare(
  myCompanyCertificates
  SVN_REPOSITORY svn+ssh://svn.mycompany.com/srv/svn/trunk/certs
  SVN_REVISION   -r12345
)

Когда содержимое извлекается из удаленного расположения и вы не контролируете этот сервер, рекомендуется использовать хеш для GIT_TAG вместо имени ветки или тега. Хеш коммита более безопасен и помогает подтвердить, что загруженное содержимое соответствует ожиданиям.

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

Новое в версии 3.22: Переменные CMAKE_TLS_VERIFY, CMAKE_TLS_CAINFO, CMAKE_NETRC и CMAKE_NETRC_FILE теперь предоставляют значения по умолчанию для соответствующих параметров содержимого, как и для ExternalProject_Add(). Ранее эти переменные игнорировались модулем FetchContent.

FetchContent_MakeAvailable

New in version 3.14.

FetchContent_MakeAvailable(<name1> [<name2>...])

Эта команда гарантирует, что каждая из указанных зависимостей будет обработана и потенциально добавлена в сборку к моменту её возврата. Она итерируется по списку, и для каждой зависимости применяется следующий алгоритм:

  • Если зависимость уже была обработана ранее в этом запуске, установите переменные <lowercaseName>_POPULATED, <lowercaseName>_SOURCE_DIR и <lowercaseName>_BINARY_DIR таким же образом, как и при вызове FetchContent_GetProperties(), затем пропустите оставшиеся шаги и перейдите к следующей зависимости в списке.
  • Вызовите FetchContent_Populate() для обработки зависимости, используя данные, записанные в предыдущем вызове FetchContent_Declare(). Прервите выполнение с ошибкой, если такие данные не были записаны. FETCHCONTENT_SOURCE_DIR_<uppercaseName> может быть использована для переопределения записанных данных и использования содержимого из указанного расположения.
  • Если верхний каталог обработаного содержимого содержит файл CMakeLists.txt, вызовите add_subdirectory() для добавления его в основную сборку. Отсутствие файла CMakeLists.txt не является ошибкой, что позволяет использовать команду для зависимостей, которые делают загруженное содержимое доступным в известном месте, но не нуждаются или не поддерживают прямое добавление в сборку.

    New in version 3.18: Параметр SOURCE_SUBDIR может быть задан в объявленных данных для поиска в подкаталогах верхнего каталога вместо самого верхнего (аналогично тому, как используется SOURCE_SUBDIR командой ExternalProject_Add()). Путь, указанный с помощью SOURCE_SUBDIR, должен быть относительным и будет обрабатываться относительно верхнего каталога. Он также может указывать на каталог, не содержащий файл CMakeLists.txt или даже на несуществующий каталог. Это может быть использовано для предотвращения добавления проекта, содержащего файл CMakeLists.txt в своём верхнем каталоге.

Проекты должны объявлять данные всех зависимостей, которые они могут использовать, перед вызовом FetchContent_MakeAvailable() для любой из них. Это гарантирует, что если какие-либо зависимости также являются подзависимостями одной или нескольких других, основной проект по-прежнему контролирует используемые данные (потому что он объявляет их первым, прежде чем зависимости смогут это сделать). В следующих примерах кода предполагается, что зависимость uses_other также использует FetchContent для добавления зависимости other вовнутрь:

# WRONG: Should declare all details first
FetchContent_Declare(uses_other ...)
FetchContent_MakeAvailable(uses_other)

FetchContent_Declare(other ...)    # Will be ignored, uses_other beat us to it
FetchContent_MakeAvailable(other)  # Would use details declared by uses_other
# CORRECT: All details declared first, so they will take priority
FetchContent_Declare(uses_other ...)
FetchContent_Declare(other ...)
FetchContent_MakeAvailable(uses_other other)
FetchContent_Populate

Примечание

В тех случаях, когда это возможно, предпочтительно использовать FetchContent_MakeAvailable() вместо ручного заполнения с помощью данной команды.

FetchContent_Populate(<name>)

В большинстве случаев единственным аргументом, передаваемым FetchContent_Populate(), является <name>. В этом случае команда предполагает, что данные о контенте были записаны в результате предыдущего вызова FetchContent_Declare(). Данные хранятся в глобальной переменной, поэтому они не зависят от таких аспектов, как область видимости переменных или директорий. Следовательно, не имеет значения, где в проекте были ранее объявлены данные, главное, чтобы они были объявлены до вызова FetchContent_Populate(). Затем эти сохранённые данные используются для создания вызова ExternalProject_Add() в частном подпроекте для немедленного заполнения контента. Реализация ExternalProject_Add() гарантирует, что если контент уже был заполнен в предыдущем запуске CMake, он будет повторно использован, а не заполнен снова. В общем случае, когда заполнение включает загрузку контента, затраты на загрузку несут только один раз.

Внутренняя глобальная переменная записывает информацию о том, был ли обработан запрос на заполнение конкретного контента. Если FetchContent_Populate() вызывается более одного раза для одного и того же имени контента в ходе конфигурации, второй вызов завершится с ошибкой. Проекты могут и должны проверять, был ли контент уже заполнен с помощью команды FetchContent_GetProperties() перед вызовом FetchContent_Populate().

FetchContent_Populate() установит три переменные в области видимости вызывающей функции:

<lowercaseName>_POPULATED

Это значение всегда будет установлено в TRUE при вызове.

<lowercaseName>_SOURCE_DIR

Расположение, где можно найти заполненный контент после возврата.

<lowercaseName>_BINARY_DIR

Директория, предназначенная для использования в качестве соответствующей директории сборки.

Основное применение переменных <lowercaseName>_SOURCE_DIR и <lowercaseName>_BINARY_DIR заключается в немедленном вызове add_subdirectory() после заполнения:

FetchContent_Populate(FooBar)
add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})

Значения этих трёх переменных также могут быть получены из любой части иерархии проекта с помощью команды FetchContent_GetProperties().

Команда FetchContent_Populate() также поддерживает синтаксис, позволяющий указать данные о контенте напрямую, а не использовать сохранённые данные. Это более низкий уровень, и использование этого формата следует избегать в пользу использования сохранённых данных о контенте, как описано выше. Тем не менее, в определённых ситуациях может быть полезно вызывать заполнение контента как изолированную операцию (обычно в рамках реализации какой-либо другой функции более высокого уровня или при использовании CMake в режиме сценариев):

FetchContent_Populate(
  <name>
  [QUIET]
  [SUBBUILD_DIR <subBuildDir>]
  [SOURCE_DIR <srcDir>]
  [BINARY_DIR <binDir>]
  ...
)

Этот формат имеет ряд ключевых отличий от случая, когда указан только <name>:

  • Предполагается, что все необходимые данные для заполнения были указаны непосредственно в вызове FetchContent_Populate(). Любые сохранённые данные для <name> игнорируются.
  • Не проверяется, был ли контент для <name> уже заполнен.
  • Не устанавливается глобальная переменная, записывающая информацию о том, что заполнение произошло.
  • Не сохраняются глобальные переменные, содержащие источники или двоичные каталоги заполненного контента.
  • Кэшируемые переменные FETCHCONTENT_FULLY_DISCONNECTED и FETCHCONTENT_UPDATES_DISCONNECTED игнорируются.

Переменные <lowercaseName>_SOURCE_DIR и <lowercaseName>_BINARY_DIR всё ещё возвращаются вызывающей функции, но поскольку эти расположения не хранятся как глобальные переменные при использовании этого формата, они доступны только вызывающей функции и ниже, а не всей иерархии проекта. Переменная <lowercaseName>_POPULATED не устанавливается в области видимости вызывающей функции в этом формате.

Поддерживаемые параметры для FetchContent_Populate() такие же, как и для FetchContent_Declare(). Те немногие параметры, показанные выше, либо специфичны для FetchContent_Populate(), либо их поведение немного отличается от того, как ExternalProject_Add() их обрабатывает:

QUIET

Параметр QUIET может быть задан для скрытия вывода, связанного с заполнением указанного контента. Если заполнение завершится ошибкой, вывод будет показан независимо от того, был ли задан этот параметр или нет, для того, чтобы можно было диагностировать причину ошибки. Глобальная кэшируемая переменная FETCHCONTENT_QUIET не влияет на вызовы FetchContent_Populate(), где данные о контенте предоставляются напрямую.

SUBBUILD_DIR

Аргумент SUBBUILD_DIR может быть указан для изменения расположения подпроекта, созданного для выполнения заполнения. Значение по умолчанию — ${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-subbuild, и обычно нет необходимости его изменять. Если указан относительный путь, он интерпретируется относительно CMAKE_CURRENT_BINARY_DIR. Этот параметр не следует путать с параметром SOURCE_SUBDIR, который влияет только на команду FetchContent_MakeAvailable().

SOURCE_DIR, BINARY_DIR

Аргументы SOURCE_DIR и BINARY_DIR поддерживаются ExternalProject_Add(), но FetchContent_Populate() использует разные значения по умолчанию. SOURCE_DIR по умолчанию устанавливается в ${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-src, а BINARY_DIR по умолчанию устанавливается в ${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-build. Если указан относительный путь, он интерпретируется относительно CMAKE_CURRENT_BINARY_DIR.

В дополнение к явным параметрам выше, любые другие нераспознанные параметры передаются без изменений в ExternalProject_Add() для выполнения шагов загрузки, исправления и обновления. Следующие параметры явно запрещены (они отключены командой FetchContent_Populate()):

  • CONFIGURE_COMMAND
  • BUILD_COMMAND
  • INSTALL_COMMAND
  • TEST_COMMAND

Если вы используете FetchContent_Populate() в режиме сценариев CMake, имейте в виду, что реализация создаёт подпроект, который, следовательно, требует наличия генератора CMake и инструмента сборки. Если они не найдены по умолчанию, необходимо соответствующим образом установить переменные CMAKE_GENERATOR и/или CMAKE_MAKE_PROGRAM в командной строке при вызове сценария.

New in version 3.18: Добавлена поддержка параметра DOWNLOAD_NO_EXTRACT.

FetchContent_GetProperties

При использовании сохранённых данных о контенте вызов FetchContent_MakeAvailable() или FetchContent_Populate() записывает информацию в глобальные переменные, которую можно запросить в любое время. Эта информация включает в себя директории исходников и библиотек, связанные с контентом, а также информацию о том, был ли контент заполнен в текущей конфигурации.

FetchContent_GetProperties(
  <name>
  [SOURCE_DIR <srcDirVar>]
  [BINARY_DIR <binDirVar>]
  [POPULATED <doneVar>]
)

Параметры SOURCE_DIR, BINARY_DIR и POPULATED могут быть использованы для указания, какие свойства необходимо получить. Каждый параметр принимает значение, являющееся именем переменной, в которую следует сохранить это свойство. Однако чаще всего используется только <name>, в этом случае вызов установит те же переменные, что и вызов FetchContent_MakeAvailable(name) или FetchContent_Populate(name).

Эта команда редко требуется при использовании FetchContent_MakeAvailable(). Она чаще используется в рамках реализации следующего шаблона с FetchContent_Populate(), что гарантирует, что соответствующие переменные будут определены независимо от того, было ли заполнение выполнено где-либо ещё в проекте:

# Check if population has already been performed
FetchContent_GetProperties(depname)
if(NOT depname_POPULATED)
  # Fetch the content using previously declared details
  FetchContent_Populate(depname)

  # Set custom variables, policies, etc.
  # ...

  # Bring the populated content into the build
  add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR})
endif()

Переменные

Несколько переменных кэша могут влиять на поведение, где данные из вызова FetchContent_Declare() используются для заполнения содержимого. Все переменные предназначены для настройки поведения разработчиком и обычно не должны устанавливаться проектом.

FETCHCONTENT_BASE_DIR

В большинстве случаев сохранённые данные не содержат никаких параметров, относящихся к каталогам для использования во внутренней подсборке, конечных областях исходного кода и сборки. Обычно лучше доверить эти решения модулю FetchContent для обработки от имени проекта. Переменная кэша FETCHCONTENT_BASE_DIR контролирует точку, под которой собираются все каталоги заполнения содержимого, но в большинстве случаев разработчикам не нужно менять это. По умолчанию расположение — ${CMAKE_BINARY_DIR}/_deps, но если разработчики изменят это значение, им следует стремиться к тому, чтобы путь был коротким и располагался чуть ниже верхнего уровня дерева сборки, чтобы избежать проблем с длиной пути в Windows.

FETCHCONTENT_QUIET

Лог-вывод во время заполнения может быть довольно подробным, что делает этап конфигурации довольно шумным. Этот параметр кэша (ON по умолчанию) скрывает весь вывод заполнения, если не возникает ошибка. Если возникают проблемы с зависанием загрузок, временное отключение этого параметра может помочь диагностировать, какая операция заполнения содержимого вызывает проблему.

FETCHCONTENT_FULLY_DISCONNECTED

При включенном этом параметре не предпринимается попытка загрузить или обновить какое-либо содержимое. Предполагается, что всё содержимое уже было заполнено в предыдущем запуске или каталоги исходного кода указывали на существующее содержимое, которое разработчик предоставил вручную (используя параметры, описанные ниже). Если разработчик знает, что изменения в деталях содержимого не производились, включение этого параметра ON может значительно ускорить этап конфигурации. По умолчанию он OFF.

FETCHCONTENT_UPDATES_DISCONNECTED

Это менее жёсткий контроль за загрузкой/обновлением по сравнению с FETCHCONTENT_FULLY_DISCONNECTED. Вместо того, чтобы полностью пропустить логику загрузки и обновления, FETCHCONTENT_UPDATES_DISCONNECTED только отключает этап обновления. Таким образом, если содержимое ранее не загружалось, оно всё ещё будет загружено при включенном этом параметре. Это может ускорить этап конфигурации, но не так сильно, как FETCHCONTENT_FULLY_DISCONNECTED. По умолчанию он OFF.

FETCHCONTENT_SOURCE_DIR_<uppercaseName>

Если он установлен, шаги загрузки или обновления для указанного содержимого не выполняются, и переменная <lowercaseName>_SOURCE_DIR возвращается вызывающей стороне, указывающая на это расположение. Это даёт разработчикам возможность иметь отдельный набор исходных кодов содержимого, которые они могут свободно изменять без вмешательства сборки. Сборка просто использует эти существующие исходные файлы, но всё ещё определяет <lowercaseName>_BINARY_DIR для указания внутри своей собственной области сборки. Разработчикам настоятельно рекомендуется использовать этот механизм, а не редактировать данные, заполненные по умолчанию, так как изменения в исходных данных по умолчанию могут быть потеряны, когда детали заполнения содержимого изменяются проектом.

FETCHCONTENT_UPDATES_DISCONNECTED_<uppercaseName>

Это эквивалент для каждого содержимого параметра FETCHCONTENT_UPDATES_DISCONNECTED. Если глобальный параметр или этот параметр ON, обновления будут отключены для указанного содержимого. Отключение обновлений для отдельных элементов содержимого может быть полезным для содержимого, чьи данные редко меняются, в то время как другие часто изменяющиеся данные всё ещё будут обновляться.

Примеры

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

include(FetchContent)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
FetchContent_Declare(
  Catch2
  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  GIT_TAG        de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4
)

# After the following call, the CMake targets defined by googletest and
# Catch2 will be available to the rest of the build
FetchContent_MakeAvailable(googletest Catch2)

Если файл CMakeLists.txt подпроекта не находится на верхнем уровне его дерева исходных кодов, параметр SOURCE_SUBDIR может использоваться для указания FetchContent места его нахождения. Следующий пример показывает, как использовать этот параметр, а также устанавливает переменную, имеющую смысл для подпроекта перед его включением в основную сборку:

include(FetchContent)
FetchContent_Declare(
  protobuf
  GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
  GIT_TAG        ae50d9b9902526efd6c7a1907d09739f959c6297 # v3.15.0
  SOURCE_SUBDIR  cmake
)
set(protobuf_BUILD_TESTS OFF)
FetchContent_MakeAvailable(protobuf)

В более сложных иерархиях проектов зависимость может быть более сложной. Рассмотрим иерархию, где projA — проект верхнего уровня, и он напрямую зависит от проектов projB и projC. Оба projB и projC могут быть скомпилированы автономно, и оба также зависят от другого проекта projD. projB дополнительно зависит от projE. Этот пример предполагает, что все пять проектов доступны на корпоративном сервере Git. Файлы CMakeLists.txt каждого проекта могут содержать разделы, подобные следующим:

projA:

include(FetchContent)
FetchContent_Declare(
  projB
  GIT_REPOSITORY git@mycompany.com:git/projB.git
  GIT_TAG        4a89dc7e24ff212a7b5167bef7ab079d
)
FetchContent_Declare(
  projC
  GIT_REPOSITORY git@mycompany.com:git/projC.git
  GIT_TAG        4ad4016bd1d8d5412d135cf8ceea1bb9
)
FetchContent_Declare(
  projD
  GIT_REPOSITORY git@mycompany.com:git/projD.git
  GIT_TAG        origin/integrationBranch
)
FetchContent_Declare(
  projE
  GIT_REPOSITORY git@mycompany.com:git/projE.git
  GIT_TAG        v2.3-rc1
)

# Order is important, see notes in the discussion further below
FetchContent_MakeAvailable(projD projB projC)

projB:

include(FetchContent)
FetchContent_Declare(
  projD
  GIT_REPOSITORY git@mycompany.com:git/projD.git
  GIT_TAG        20b415f9034bbd2a2e8216e9a5c9e632
)
FetchContent_Declare(
  projE
  GIT_REPOSITORY git@mycompany.com:git/projE.git
  GIT_TAG        68e20f674a48be38d60e129f600faf7d
)

FetchContent_MakeAvailable(projD projE)

projC:

include(FetchContent)
FetchContent_Declare(
  projD
  GIT_REPOSITORY git@mycompany.com:git/projD.git
  GIT_TAG        7d9a17ad2c962aa13e2fbb8043fb6b8a
)

# This particular version of projD requires workarounds
FetchContent_GetProperties(projD)
if(NOT projd_POPULATED)
  FetchContent_Populate(projD)

  # Copy an additional/replacement file into the populated source
  file(COPY someFile.c DESTINATION ${projd_SOURCE_DIR}/src)

  add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR})
endif()

Несколько ключевых моментов следует отметить выше:

  • projB и projC определяют различные данные содержимого для projD, но projA также определяет набор данных содержимого для projD. Так как projA определит их первым, данные из projB и projC не будут использованы. Данные переопределения, определенные projA, не обязаны совпадать ни с одним из данных из projB или projC, но проект верхнего уровня должен убедиться, что определенные им данные всё ещё имеют смысл для дочерних проектов.
  • В вызове projA FetchContent_MakeAvailable(), projD перечислен раньше projB и projC для того, чтобы projA контролировал способ заполнения projD.
  • Хотя projA определяет данные содержимого для projE, он не обязан явным образом вызывать FetchContent_MakeAvailable(projE) или FetchContent_Populate(projD) сам. Вместо этого он оставляет это дочерним projB. Для проектов верхнего уровня часто достаточно просто определить переопределенные данные содержимого и оставить фактическое заполнение дочерним проектам. Это позволяет избежать ненужного повторения одного и того же на каждом уровне иерархии проекта.

Проектам не всегда нужно добавлять заполненное содержимое в сборку. Иногда проект просто хочет сделать загруженное содержимое доступным в предсказуемом месте. Следующий пример гарантирует, что набор стандартных файлов инструментария компании (и, возможно, даже сами двоичные файлы инструментария) доступны достаточно рано, чтобы их можно было использовать для этой же сборки.

cmake_minimum_required(VERSION 3.14)

include(FetchContent)
FetchContent_Declare(
  mycom_toolchains
  URL  https://intranet.mycompany.com//toolchains_1.3.2.tar.gz
)
FetchContent_MakeAvailable(mycom_toolchains)

project(CrossCompileExample)

Проект можно настроить на использование одного из загруженных наборов инструментов таким образом:

cmake -DCMAKE_TOOLCHAIN_FILE=_deps/mycom_toolchains-src/toolchain_arm.cmake /path/to/src

Когда CMake обрабатывает файл CMakeLists.txt, он загрузит и распакует архив в _deps/mycompany_toolchains-src относительно каталога сборки. Переменная CMAKE_TOOLCHAIN_FILE используется только до тех пор, пока не будет достигнут команд project(), в этот момент CMake ищет именованный файл набора инструментов относительно каталога сборки. Поскольку архив уже загружен и распакован к этому времени, файл набора инструментов будет на месте, даже в первый раз, когда cmake выполняется в каталоге сборки.

Наконец, следующий пример демонстрирует, как можно загрузить и распаковать архив firmware с помощью script mode CMake. Вызов FetchContent_Populate() указывает все данные содержимого, и распакованный firmware будет помещен в каталог firmware ниже текущей рабочей директории.

getFirmware.cmake:

# NOTE: Intended to be run in script mode with cmake -P
include(FetchContent)
FetchContent_Populate(
  firmware
  URL        https://mycompany.com/assets/firmware-1.23-arm.tar.gz
  URL_HASH   MD5=68247684da89b608d466253762b0ff11
  SOURCE_DIR firmware
)

© 2000–2022 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.23/module/FetchContent.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API