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_MakeAvailable(googletest)
Вышеприведённая команда не только заполняет контент, но также добавляет его в основную сборку (если это возможно), чтобы основная сборка могла использовать цели заполненного проекта и т. д. В некоторых случаях основному проекту может потребоваться более точный контроль над заполнением или может потребоваться явное определение шагов заполнения (например, если необходимо поддерживать версии CMake, более ранние чем 3.14). Типичный шаблон таких пользовательских шагов выглядит так:
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
endif()
Независимо от используемого метода заполнения, при использовании шаблона «объявить-заполнить» с иерархической структурой проекта, проекты на более высоких уровнях иерархии могут переопределять детали заполнения контента, указанные на более низких уровнях проекта. Возможность обнаруживать, был ли контент уже заполнен, гарантирует, что даже если несколько дочерних проектов хотят, чтобы определённый контент был доступен, первым заполнивший его побеждает. Другие дочерние проекты просто могут использовать уже доступный контент вместо повторного заполнения для себя. См. раздел Примеры, демонстрирующий эту ситуацию.
Модуль FetchContent также поддерживает определение и заполнение контента в одном вызове без проверки, был ли контент уже заполнен где-либо ещё в проекте. Это более низкоуровневая операция, и обычно модуль не используется таким образом, но иногда он полезен в качестве части реализации какой-либо более сложной функции или для заполнения некоторого контента в режиме сценариев CMake.
Изменено в версии 3.14: FetchContent команды могут получить доступ к терминалу. Это необходимо для работы запросов пароля и отображения прогресса в реальном времени.
Команды
Объявление деталей контента
-
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вместо имени ветки или тега. Хэш коммита более безопасен и помогает подтвердить, что загруженный контент соответствует вашим ожиданиям.
Заполнение контента
В большинстве распространённых случаев заполнение означает предоставление контента основной сборке в соответствии с ранее объявленными подробностями для этой зависимости. Существует два основных шаблона заполнения контента, один основан на вызове FetchContent_GetProperties() и FetchContent_Populate() для более точного управления, а другой — на вызове FetchContent_MakeAvailable() для более простого и автоматизированного подхода. Первый обычно следует этому каноническому шаблону:
# Check if population has already been performed
FetchContent_GetProperties(<name>)
string(TOLOWER "<name>" lcName)
if(NOT ${lcName}_POPULATED)
# Fetch the content using previously declared details
FetchContent_Populate(<name>)
# Set custom variables, policies, etc.
# ...
# Bring the populated content into the build
add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR})
endif()
Этот шаблон настолько распространён, что в тех случаях, когда не нужны пользовательские шаги между вызовами FetchContent_Populate() и add_subdirectory(), эквивалентная логика может быть получена вызовом FetchContent_MakeAvailable() вместо этого. Если это соответствует потребностям проекта, FetchContent_MakeAvailable() следует предпочесть, поскольку он проще и предоставляет дополнительные возможности по сравнению с вышеприведённым шаблоном.
-
FetchContent_Populate -
FetchContent_Populate( <name> )
В большинстве случаев единственным аргументом, передаваемым
FetchContent_Populate(), является<name>. В этом случае команда предполагает, что подробности о содержимом были записаны в предыдущем вызовеFetchContent_Declare(). Данные сохраняются в глобальной переменной, поэтому они не зависят от таких факторов, как область видимости переменных или каталогов. Поэтому не имеет значения, где в проекте ранее были объявлены данные, до тех пор, пока они были объявлены до вызоваFetchContent_Populate(). Эти сохранённые данные затем используются для построения вызоваExternalProject_Add()в частном подпроекте для немедленного заполнения содержимого. РеализацияExternalProject_Add()гарантирует, что если содержимое уже было заполнено в предыдущем запуске CMake, оно будет повторно использовано, а не перезаполнено. В распространённом случае, когда заполнение включает загрузку содержимого, затраты на загрузку производятся только один раз.Внутренняя глобальная переменная фиксирует, когда определённый запрос на заполнение содержимого был обработан. Если
FetchContent_Populate()вызывается более одного раза для одного и того же имени содержимого в ходе конфигурации, второй вызов завершится ошибкой. Проекты могут и должны проверить, была ли обработка заполнения содержимого уже выполнена с помощью командыFetchContent_GetProperties()перед вызовомFetchContent_Populate().FetchContent_Populate()установит три переменные в области видимости вызывающего;<lcName>_POPULATED,<lcName>_SOURCE_DIRи<lcName>_BINARY_DIR, где<lcName>— строка<name>в нижнем регистре.<lcName>_POPULATEDвсегда будет установлено вTrueвызовом.<lcName>_SOURCE_DIR— это местоположение, где содержимое может быть найдено по возвращении (оно уже будет заполнено), а<lcName>_BINARY_DIR— это каталог, предназначенный для использования в качестве соответствующего каталога сборки. Основной случай использования двух переменных каталога — вызовadd_subdirectory()сразу после заполнения, например:FetchContent_Populate(FooBar ...) add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})Значения трёх переменных также могут быть получены из любой точки иерархии проекта с помощью команды
FetchContent_GetProperties().Несколько переменных кэша влияют на поведение всех операций заполнения содержимого, выполненных с помощью данных, сохранённых из вызова
FetchContent_Declare():-
FETCHCONTENT_BASE_DIR -
В большинстве случаев сохранённые данные не содержат каких-либо параметров, относящихся к каталогам, используемым для внутреннего подпроекта, конечным областям исходного и скомпилированного кода. Обычно лучше оставить эти решения модулю
FetchContentдля обработки от имени проекта. Переменная кэшаFETCHCONTENT_BASE_DIRуправляет точкой, в которой собираются все каталоги заполнения содержимого, но в большинстве случаев разработчикам не нужно будет изменять это. По умолчанию расположение —${CMAKE_BINARY_DIR}/_deps, но если разработчики изменят это значение, они должны стремиться сохранять путь коротким и чуть ниже верхнего уровня дерева сборки, чтобы избежать проблем с длиной пути в Windows. -
FETCHCONTENT_QUIET -
Выходные данные логов во время заполнения могут быть весьма подробными, что делает этап конфигурации довольно шумным. Этот параметр кэша (
ONпо умолчанию) скрывает все выходные данные заполнения, за исключением случаев возникновения ошибок. Если возникают проблемы с зависанием загрузок, временное отключение этого параметра может помочь в диагностике, какой запрос на заполнение содержимого вызывает проблему. -
FETCHCONTENT_FULLY_DISCONNECTED -
При включении этого параметра не предпринимается попыток загрузить или обновить какое-либо содержимое. Предполагается, что всё содержимое уже было заполнено в предыдущем запуске или каталоги исходных файлов указывают на существующее содержимое, предоставленное разработчиком вручную (используя параметры, описанные ниже). Если разработчик знает, что изменения в каких-либо данных содержимого не вносились, включение этого параметра может значительно ускорить этап конфигурации. По умолчанию он
ON. -
FETCHCONTENT_UPDATES_DISCONNECTED -
Это менее жёсткий контроль загрузки/обновления по сравнению с
FETCHCONTENT_FULLY_DISCONNECTED. Вместо того, чтобы полностью игнорировать логику загрузки и обновления,FETCHCONTENT_UPDATES_DISCONNECTEDотключает только этап обновления. Следовательно, если содержимое не было загружено ранее, оно всё равно будет загружено при включении этого параметра. Это может ускорить этап конфигурации, но не так сильно, какFETCHCONTENT_FULLY_DISCONNECTED. По умолчанию онOFF.
В дополнение к вышеперечисленным переменным кэша, для каждого имени содержимого также определены следующие переменные кэша (
<ucName>— это заглавная версия<name>):-
FETCHCONTENT_SOURCE_DIR_<ucName> -
Если это установлено, то для указанного содержимого не выполняются действия по загрузке или обновлению, и переменная
<lcName>_SOURCE_DIRвозвращается вызывающей стороне, указывая на это местоположение. Это даёт разработчикам возможность иметь отдельный контрольный пункт содержимого, который они могут свободно изменять без вмешательства сборки. Сборка просто использует этот существующий исходный код, но при этом по-прежнему определяет<lcName>_BINARY_DIRдля указания внутренней области сборки. Разработчикам настоятельно рекомендуется использовать этот механизм, а не редактировать исходный код, заполненный по умолчанию, поскольку изменения в исходном коде по умолчанию могут быть потеряны, когда данные содержимого проекта меняются. -
FETCHCONTENT_UPDATES_DISCONNECTED_<ucName> -
Это эквивалент
FETCHCONTENT_UPDATES_DISCONNECTEDдля каждого содержимого. Если глобальный параметр или этот параметрON, то обновления будут отключены для указанного содержимого. Отключение обновлений для отдельных элементов содержимого может быть полезно для содержимого, данные которого редко изменяются, при этом оставляя другие часто изменяемые элементы с включёнными обновлениями.
Команда
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игнорируются.
Переменные
<lcName>_SOURCE_DIRи<lcName>_BINARY_DIRвсё равно возвращаются вызывающей стороне, но поскольку эти расположения не сохраняются как глобальные переменные при использовании этого формата, они доступны только в области вызова и ниже, а не во всей иерархии проекта. Переменная<lcName>_POPULATEDне устанавливается в области вызывающей стороны в этом формате.Поддерживаемые параметры для
FetchContent_Populate()такие же, как и дляFetchContent_Declare(). Те несколько параметров, показанных выше, либо специфичны дляFetchContent_Populate(), либо их поведение немного отличается от того, какExternalProject_Add()их обрабатывает.-
QUIET -
Параметр
QUIETможно указать для скрытия вывода, связанного с заполнением указанного содержимого. Если заполнение завершается неудачей, вывод будет отображаться независимо от того, был ли этот параметр указан или нет, чтобы можно было диагностировать причину ошибки. Глобальная переменная кэшаFETCHCONTENT_QUIETне влияет на вызовыFetchContent_Populate(), где данные содержимого предоставляются напрямую. -
SUBBUILD_DIR -
Аргумент
SUBBUILD_DIRможно указать, чтобы изменить расположение подпроекта, созданного для выполнения заполнения. Значение по умолчанию —${CMAKE_CURRENT_BINARY_DIR}/<lcName>-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}/<lcName>-src, аBINARY_DIRпо умолчанию${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build. Если указан относительный путь, он будет интерпретироваться как относительный кCMAKE_CURRENT_BINARY_DIR.
В дополнение к вышеуказанным явным параметрам, любые другие нераспознанные параметры передаются без изменений команде
ExternalProject_Add()для выполнения этапов загрузки, применения исправлений и обновления. Следующие параметры запрещены (они отключены командойFetchContent_Populate()): -
CONFIGURE_COMMANDBUILD_COMMANDINSTALL_COMMANDTEST_COMMAND
Если использовать
FetchContent_Populate()в режиме скрипта CMake, следует учитывать, что реализация создаёт подмодуль, поэтому требуется генератор CMake и инструмент сборки. Если эти компоненты не могут быть найдены по умолчанию, то необходимо соответствующим образом установить переменныеCMAKE_GENERATORи/илиCMAKE_MAKE_PROGRAMв командной строке при вызове скрипта.Новое в версии 3.18: Добавлена поддержка опций
DOWNLOAD_NO_EXTRACTиSOURCE_SUBDIR.
-
FetchContent_GetProperties -
При использовании сохранённых данных о содержимом, вызов
FetchContent_Populate()записывает информацию в глобальные свойства, которые могут быть запрошены в любое время. Эта информация включает исходный и бинарный каталоги, связанные с содержимым, а также информацию о том, была ли обработка содержимого выполнена во время текущего этапа конфигурации.FetchContent_GetProperties( <name> [SOURCE_DIR <srcDirVar>] [BINARY_DIR <binDirVar>] [POPULATED <doneVar>] )
Опции
SOURCE_DIR,BINARY_DIRиPOPULATEDмогут быть использованы для указания свойств, которые должны быть извлечены. Каждая опция принимает значение, которое является именем переменной, в которой следует сохранить это свойство. Однако в большинстве случаев указывается только<name>, в результате вызов установит те же переменные, что и вызовFetchContent_Populate(name). Это позволяет использовать следующий канонический шаблон, который гарантирует, что соответствующие переменные всегда будут определены, независимо от того, была ли обработка выполнена в другой части проекта:FetchContent_GetProperties(foobar) if(NOT foobar_POPULATED) FetchContent_Populate(foobar) ... endif()
Вышеупомянутый шаблон позволяет другим частям общей иерархии проекта повторно использовать то же содержимое и гарантировать, что оно будет обработано только один раз.
-
FetchContent_MakeAvailable -
FetchContent_MakeAvailable( <name1> [<name2>...] )
Новое в версии 3.14.
Эта команда реализует общий шаблон, обычно необходимый для большинства зависимостей. Она итерируется по каждой из перечисленных зависимостей и для каждой из них примерно следует каноническому шаблону, представленному в начале этого раздела. Важное отличие заключается в том, что
add_subdirectory()будет вызываться только для обработанного содержимого, если в его исходном каталоге верхнего уровня существует файлCMakeLists.txt. Это позволяет использовать команду для зависимостей, которые делают загруженное содержимое доступным в известном месте, но не требуют или не поддерживают непосредственного добавления в сборку.Опция
SOURCE_SUBDIRможет быть указана в объявленных деталях, чтобы указатьFetchContent_MakeAvailable()искать файлCMakeLists.txtв подкаталоге ниже верхнего уровня (то есть таким же образом, какSOURCE_SUBDIRиспользуется командойExternalProject_Add()).SOURCE_SUBDIRвсегда должен быть относительным путём. Смотрите следующий раздел для примера использования этой опции.
Примеры
В этом первом довольно простом примере гарантируется, что некоторые популярные тестовые фреймворки доступны основной сборке:
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 defined and 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.
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, но проект верхнего уровня должен обеспечить, чтобы определённые им данные всё ещё имели смысл для дочерних проектов. - В вызове
FetchContent_MakeAvailable()проектаprojA,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 с помощью CMake's script mode. Вызов 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.21/module/FetchContent.html