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_COMMANDBUILD_COMMANDINSTALL_COMMANDTEST_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, но проект верхнего уровня должен убедиться, что определенные им данные всё ещё имеют смысл для дочерних проектов. - В вызове
projAFetchContent_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