Spec-Zone.ru › CMake 3.22

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 secret_sauce)

Команда 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

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

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

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

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

    Новое в версии 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 необходимо установить соответствующим образом в командной строке вызова скрипта.

Добавлено в версии 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, он загрузит и распакует tarball в _deps/mycompany_toolchains-src относительно каталога сборки. Переменная CMAKE_TOOLCHAIN_FILE не используется до тех пор, пока не будет достигнут команда project(), в этот момент CMake ищет файл набора инструментов с указанным именем относительно каталога сборки. Поскольку tarball уже был загружен и распакован к тому моменту, файл набора инструментов будет на месте, даже в первый раз, когда cmake запускается в каталоге сборки.

Наконец, следующий пример демонстрирует, как можно загрузить и распаковать файл firmware tarball с помощью 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–2021 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.22/module/FetchContent.html

Spec-Zone.ru

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