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_COMMANDBUILD_COMMANDINSTALL_COMMANDTEST_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