FetchContent
Добавлено в версии 3.11.
Этот модуль предоставляет команды для получения содержимого на этапе конфигурирования или в составе вызывающего скрипта.
Загрузите этот модуль в CMake с помощью:
include(FetchContent)
Примечание
Using Dependencies Guide содержит вводный обзор этой общей темы на высоком уровне. В нем дается более широкое представление о месте модуля FetchContent в общей картине, включая его связь с командой find_package(). Перед изучением приведенных ниже подробностей рекомендуется сначала ознакомиться с этим руководством.
Обзор
Этот модуль позволяет получать содержимое на этапе конфигурирования любым способом, поддерживаемым модулем 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 также поддерживает определение параметров и получение содержимого одним вызовом без проверки, не было ли содержимое получено ранее в другом месте. В проектах так делать не следует, однако это может подойти для получения содержимого в режиме скрипта CMake. Подробности см. в описании FetchContent_Populate().
Команды
-
FetchContent_Declare -
FetchContent_Declare( <name> <contentOptions>... [EXCLUDE_FROM_ALL] [SYSTEM] [OVERRIDE_FIND_PACKAGE | FIND_PACKAGE_ARGS args...] )
Функция
FetchContent_Declare()сохраняет параметры, описывающие способ получения указанного содержимого. Если такие параметры уже были сохранены ранее в этом проекте (независимо от уровня иерархии проекта), этот и все последующие вызовы для того же содержимого<name>игнорируются. Такой подход — «первый сохранивший параметры побеждает» — позволяет родительским проектам переопределять параметры содержимого дочерних проектов.Имя содержимого
<name>может быть любой строкой без пробелов, но рекомендуется использовать только буквы, цифры и символы подчеркивания. Имя не учитывает регистр и должно быть очевидно связано с представляемым содержимым. Часто это имя дочернего проекта или значение, переданное его командеproject()верхнего уровня (если это проект CMake). Для известных публичных проектов обычно следует использовать их официальное название. Необычное имя снижает вероятность того, что другие проекты, которым требуется то же содержимое, выберут такое же имя, что приведет к многократному получению содержимого.Параметры
<contentOptions>могут включать любые параметры загрузки, обновления или исправления, поддерживаемые командойExternalProject_Add(). Этапы конфигурирования, сборки, установки и тестирования явно отключены, поэтому параметры, относящиеся к этим этапам, запрещены и будут отброшены, если они указаны. Исключение составляет параметрSOURCE_SUBDIR; сведения о его влиянии на поведение см. в описании командыFetchContent_MakeAvailable().Изменено в версии 3.30: Если политика
CMP0168установлена в значениеNEW, некоторые параметры, связанные с выводом и каталогами, игнорируются. Подробности см. в документации политики.В большинстве случаев
<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игнорировал эти переменные.Добавлено в версии 3.24:
-
FIND_PACKAGE_ARGS -
Этот параметр предназначен для случаев, когда команда
FetchContent_MakeAvailable()может сначала попытаться вызватьfind_package(), чтобы удовлетворить зависимость для<name>. По умолчанию такой вызов выполнялся бы просто какfind_package(<name>), но с помощьюFIND_PACKAGE_ARGSможно добавить дополнительные аргументы после<name>. ПараметрFIND_PACKAGE_ARGSтакже можно указать без последующих аргументов: это означает, чтоfind_package()все еще можно вызвать, еслиFETCHCONTENT_TRY_FIND_PACKAGE_MODEустановлена в значениеOPT_INили не установлена.Обычно не следует указывать
REQUIREDсреди дополнительных аргументов послеFIND_PACKAGE_ARGS. В этом случае вызовfind_package()должен будет завершиться успешно, поэтому остальные сведения, указанные в вызовеFetchContent_Declare(), не смогут использоваться в качестве запасного варианта.Все, что указано после ключевого слова
FIND_PACKAGE_ARGS, добавляется к вызовуfind_package(), поэтому все остальные<contentOptions>должны предшествовать ключевому словуFIND_PACKAGE_ARGS. Если переменнаяCMAKE_FIND_PACKAGE_TARGETS_GLOBALустановлена в значение true на момент вызоваFetchContent_Declare(), к аргументамfind_package()будет добавлено ключевое словоGLOBAL, если оно еще не указано. Оно также будет добавлено, еслиFIND_PACKAGE_ARGSне указано, ноFETCHCONTENT_TRY_FIND_PACKAGE_MODEустановлена в значениеALWAYS.Нельзя использовать
OVERRIDE_FIND_PACKAGE, если указан параметрFIND_PACKAGE_ARGS.В разделе Поставщики зависимостей описан другой способ перенаправления вызовов
FetchContent_MakeAvailable(). ПараметрFIND_PACKAGE_ARGSпредназначен для управления проектом, тогда как поставщики зависимостей позволяют пользователям переопределять поведение проекта. -
OVERRIDE_FIND_PACKAGE -
Если вызов
FetchContent_Declare(<name> ...)содержит этот параметр, последующие вызовыfind_package(<name> ...)будут гарантировать, что вызовFetchContent_MakeAvailable(<name>)выполнен, а затем использовать файлы пакета конфигурации из каталогаCMAKE_FIND_PACKAGE_REDIRECTS_DIR(обычно создаваемые командойFetchContent_MakeAvailable()). По сути, это позволяетFetchContent_MakeAvailable()переопределитьfind_package()для указанной зависимости, позволяя первой команде удовлетворять требования к пакету второй. Нельзя использоватьFIND_PACKAGE_ARGS, если указан параметрOVERRIDE_FIND_PACKAGE.Если задан поставщик зависимостей и проект вызывает
find_package()для зависимости<name>, параметрOVERRIDE_FIND_PACKAGEне помешает поставщику увидеть этот вызов. Поставщики зависимостей всегда могут перехватить любой прямой вызовfind_package(), за исключением вызовов, содержащих параметрBYPASS_PROVIDER.
Добавлено в версии 3.25:
-
SYSTEM -
Если указан аргумент
SYSTEM, свойство каталогаSYSTEMдля подкаталога, добавленного командойFetchContent_MakeAvailable(), будет установлено в значение true. Это повлияет на неимпортированные цели, созданные в рамках этой команды. Более подробное описание эффектов см. в документации свойства целиSYSTEM.
Добавлено в версии 3.28:
-
EXCLUDE_FROM_ALL -
Если указан аргумент
EXCLUDE_FROM_ALL, цели в подкаталоге, добавленном командойFetchContent_MakeAvailable(), по умолчанию не будут включаться в цельALLи могут быть исключены из файлов проекта IDE. Подробное описание эффектов см. в документации свойства каталогаEXCLUDE_FROM_ALL.
-
-
FetchContent_MakeAvailable -
Добавлено в версии 3.14.
FetchContent_MakeAvailable(<name1> [<name2>...])
Эта команда гарантирует, что к моменту её завершения все указанные зависимости будут доступны проекту. Для каждой зависимости должен быть вызван
FetchContent_Declare(); первый такой вызов определяет, как эта зависимость будет предоставлена, как описано ниже.Если
FETCHCONTENT_SOURCE_DIR_<uppercaseName>не задана:-
Добавлено в версии 3.24: Если задан поставщик зависимостей, вызовите команду поставщика, передав
FETCHCONTENT_MAKEAVAILABLE_SERIALпервым аргументом, а затем аргументы первого вызоваFetchContent_Declare()для<name>. ЕслиSOURCE_DIRилиBINARY_DIRне входили в исходные объявленные аргументы, они будут добавлены со значениями по умолчанию. Если при объявлении сведений дляFETCHCONTENT_TRY_FIND_PACKAGE_MODEпеременнаяNEVERбыла установлена вFIND_PACKAGE_ARGS, всеOVERRIDE_FIND_PACKAGEбудут пропущены. Ключевое словоFetchContent_MakeAvailable()также всегда пропускается. Если поставщик выполнил запрос,find_package(<name> [<args>...])считает эту зависимость обработанной, пропускает оставшиеся шаги ниже и переходит к следующей зависимости в списке. -
Добавлено в версии 3.24: Если это разрешено, будет вызвана команда
<args>..., гдеFIND_PACKAGE_ARGSможет быть задан параметромFetchContent_Declare()вFETCHCONTENT_TRY_FIND_PACKAGE_MODE. Значение переменнойFetchContent_Declare()на момент вызоваFetchContent_MakeAvailable()определяет, может лиfind_package()вызыватьCMAKE_FIND_PACKAGE_TARGETS_GLOBAL. Если при вызовеFetchContent_MakeAvailable()переменнаяfind_package()установлена в true, это по-прежнему влияет на любые импортированные цели, созданные при вызовеfind_package(), даже если при объявлении соответствующих сведений эта переменная имела значение false.
Если поставщик или вызов
FetchContent_MakeAvailable()не удовлетворил зависимость,<lowercaseName>_POPULATEDиспользует следующую логику, чтобы сделать её доступной:- Если зависимость уже была заполнена ранее в этом запуске, установите переменные
<lowercaseName>_SOURCE_DIR,<lowercaseName>_BINARY_DIRиFetchContent_GetProperties()так же, как при вызовеFetchContent_Declare(), затем пропустите оставшиеся шаги ниже и перейдите к следующей зависимости в списке. - Заполните зависимость, используя сведения, сохранённые предыдущим вызовом
FETCHCONTENT_SOURCE_DIR_<uppercaseName>. Если такие сведения не были сохранены, завершите выполнение с критической ошибкой.CMAKE_FIND_PACKAGE_REDIRECTS_DIRможно использовать, чтобы переопределить объявленные сведения и вместо этого использовать содержимое из указанного расположения. -
Добавлено в версии 3.24: Убедитесь, что каталог
<lowercaseName>-config.cmakeсодержит файл<lowercaseName>-config-version.cmakeи файл<name>Config.cmake(или, что эквивалентно,<name>ConfigVersion.cmakeиCMAKE_FIND_PACKAGE_REDIRECTS_DIR). Каталог, на который указывает переменнаяincludes, очищается в начале каждого запуска CMake. Если после заполнения зависимости на предыдущем шаге файл конфигурации отсутствует, будет создан минимальный файл, который подключает с флагом<lowercaseName>-extra.cmakeлюбой файл<name>Extra.cmakeилиOPTIONAL(поэтому эти файлы могут отсутствовать и предупреждение не будет выдано). Аналогично, если файл версии конфигурации отсутствует, будет создан очень простой файл, устанавливающийPACKAGE_VERSION_COMPATIBLEиPACKAGE_VERSION_EXACTв true. Это гарантирует, что все последующие вызовыfind_package()для этой зависимости будут использовать перенаправленный файл конфигурации независимо от требований к версии. CMake не может автоматически определить версию произвольной зависимости, поэтому не может установитьPACKAGE_VERSION. Когда на следующем шаге зависимость добавляется с помощьюadd_subdirectory(), она может перезаписать сгенерированный файл версии конфигурации вCMAKE_FIND_PACKAGE_REDIRECTS_DIRфайлом, который также устанавливаетPACKAGE_VERSION. Зависимость также может записать файл<lowercaseName>-extra.cmakeили<name>Extra.cmakeдля выполнения пользовательской обработки либо определить любые переменные, которые обычно определял бы её стандартный файл конфигурации пакета (установленный). Многие проекты не выполняют пользовательскую обработку и не задают переменные, поэтому им это не требуется. При необходимости основной проект может создать эти файлы сам, если проект зависимости этого не делает. Это позволяет основному проекту добавить недостающие сведения для старых зависимостей, которые не были или не могут быть обновлены для поддержки этой функциональности. Примеры см. в разделе Интеграция с find_package(). -
Если верхний каталог заполненного содержимого содержит файл
CMakeLists.txt, вызовитеadd_subdirectory(), чтобы добавить его в основную сборку. Отсутствие файлаCMakeLists.txtне является ошибкой; это позволяет использовать команду для зависимостей, предоставляющих загруженное содержимое в известном расположении, но не требующих или не поддерживающих непосредственное добавление в сборку.Добавлено в версии 3.18: В объявленные сведения можно передать параметр
SOURCE_SUBDIR, чтобы искать каталог ниже верхнего каталога (то есть так же, какSOURCE_SUBDIRиспользуется командойExternalProject_Add()). Путь, указанный с помощьюSOURCE_SUBDIR, должен быть относительным и будет рассматриваться относительно верхнего каталога. Он также может указывать на каталог, не содержащий файлCMakeLists.txt, или даже на несуществующий каталог. Это можно использовать, чтобы не добавлять проект, содержащий файлCMakeLists.txtв своём верхнем каталоге.Добавлено в версии 3.25: Если при вызове
FetchContent_Declare()было включено ключевое словоSYSTEM, в командуadd_subdirectory()будет добавлено ключевое словоSYSTEM.Добавлено в версии 3.28: Если при вызове
FetchContent_Declare()было включено ключевое словоEXCLUDE_FROM_ALL, в командуadd_subdirectory()будет добавлено ключевое словоEXCLUDE_FROM_ALL.Добавлено в версии 3.29: Перед вызовом
add_subdirectory()переменнойCMAKE_EXPORT_FIND_PACKAGE_NAMEприсваивается имя зависимости.
Проектам следует объявлять сведения обо всех зависимостях, которые они могут использовать, до вызова
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_MakeAvailable()переменнымCMAKE_VERIFY_INTERFACE_HEADER_SETSиCMAKE_VERIFY_PRIVATE_HEADER_SETSявно присваивается значение false, а перед возвратом команды восстанавливаются их исходные значения. Обычно разработчики хотят проверять наборы заголовков только основного проекта, а не его зависимостей. Такое локальное изменение переменныхCMAKE_VERIFY_INTERFACE_HEADER_SETSиCMAKE_VERIFY_PRIVATE_HEADER_SETSобеспечивает такое ожидаемое поведение. Можно использовать переменные, такие какCMAKE_PROJECT_INCLUDEилиCMAKE_PROJECT_<PROJECT-NAME>_INCLUDE, чтобы снова включить проверку для всех или некоторых зависимостей. Также можно задать свойстваVERIFY_INTERFACE_HEADER_SETSиVERIFY_PRIVATE_HEADER_SETSотдельных целей. -
-
FetchContent_Populate -
Команда
FetchContent_Populate()— это автономный вызов, который можно использовать для заполнения содержимого как отдельной операции. Обычно эту команду использовать не следует; почти всегда проектам нужно применять вместо неёFetchContent_Declare()иFetchContent_MakeAvailable(). Основной сценарий использованияFetchContent_Populate()— режим сценария CMake при реализации другой высокоуровневой пользовательской функциональности.FetchContent_Populate( <name> [QUIET] [SUBBUILD_DIR <subBuildDir>] [SOURCE_DIR <srcDir>] [BINARY_DIR <binDir>] ... )
После
<name>необходимо указать хотя бы один параметр, иначе вызов будет интерпретирован иначе (см. ниже). Поддерживаемые параметрыFetchContent_Populate()совпадают с параметрамиFetchContent_Declare(), за несколькими исключениями. Следующие параметры не относятся к заполнению содержимого с помощьюFetchContent_Populate()и поэтому не поддерживаются:EXCLUDE_FROM_ALLSYSTEMOVERRIDE_FIND_PACKAGEFIND_PACKAGE_ARGS
Несколько параметров, указанных выше в сигнатуре, либо относятся только к
FetchContent_Populate(), либо работают несколько иначе, чем в командеExternalProject_Add():-
QUIET -
Параметр
QUIETможно указать, чтобы скрыть вывод, связанный с заполнением указанного содержимого. Если заполнение завершится с ошибкой, вывод будет показан независимо от того, был ли указан этот параметр, чтобы можно было диагностировать причину сбоя. ПеременнаяFETCHCONTENT_QUIETне влияет на вызовыFetchContent_Populate()этой формы, в которых сведения о содержимом передаются напрямую.Изменено в версии 3.30: Параметр
QUIETи переменнаяFETCHCONTENT_QUIETне влияют на поведение, если политикаCMP0168установлена вNEW. В этом случае вывод по-прежнему по умолчанию скрыт, но его подробность определяется уровнем журналирования сообщений (см.CMAKE_MESSAGE_LOG_LEVELи--log-level). -
SUBBUILD_DIR -
Аргумент
SUBBUILD_DIRможно задать, чтобы изменить расположение под-сборки, создаваемой для заполнения содержимого. Значение по умолчанию —${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-subbuild; обычно переопределять его не требуется. Если указан относительный путь, он будет рассматриваться относительноCMAKE_CURRENT_BINARY_DIR. Не следует путать этот параметр с параметромSOURCE_SUBDIR, который влияет только на командуFetchContent_MakeAvailable().Изменено в версии 3.30:
SUBBUILD_DIRигнорируется, если политикаCMP0168установлена вNEW, поскольку в этом случае под-сборка не создаётся. -
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_FULLY_DISCONNECTEDиFETCHCONTENT_UPDATES_DISCONNECTED, а также политикаCMP0170игнорируются.После возврата команды
FetchContent_Populate()в этой форме в области видимости вызывающего кода будут установлены следующие переменные:-
<lowercaseName>_SOURCE_DIR -
Расположение заполненного содержимого на момент возврата команды.
-
<lowercaseName>_BINARY_DIR -
Каталог, изначально предназначенный для соответствующего каталога сборки, но, вероятно, не имеющий значения при использовании этой формы команды.
При использовании
FetchContent_Populate()в режиме сценария CMake учитывайте, что реализация настраивает под-сборку, для которой необходимы генератор CMake и инструмент сборки. Если их не удаётся найти автоматически, переменнуюCMAKE_GENERATORи, возможно, переменнуюCMAKE_MAKE_PROGRAMпотребуется соответствующим образом задать в командной строке, запускающей сценарий.Изменено в версии 3.30: Если политика
CMP0168установлена вNEW, под-сборка не используется. В режиме сценария CMake это позволяет вызыватьFetchContent_Populate()без инструмента сборки или генератора CMake.Добавлено в версии 3.18: Добавлена поддержка параметра
DOWNLOAD_NO_EXTRACT.
Команда поддерживает ещё одну форму, хотя её больше не следует использовать:
FetchContent_Populate(<name>)
Изменено в версии 3.30: Эта форма устарела. Политика CMP0169 обеспечивает обратную совместимость для проектов, которым всё ещё нужно использовать эту форму, однако проекты следует обновить и вместо неё использовать FetchContent_MakeAvailable().
В этой форме единственный аргумент, передаваемый в FetchContent_Populate(), — это <name>. При таком использовании команда предполагает, что сведения о содержимом были сохранены предыдущим вызовом FetchContent_Declare(). Сведения хранятся в глобальном свойстве, поэтому на них не влияют такие вещи, как область видимости переменных или каталогов. Следовательно, не имеет значения, где в проекте ранее были объявлены сведения, если это произошло до вызова FetchContent_Populate(). Затем эти сохранённые сведения используются для заполнения содержимого методом, основанным на ExternalProject_Add() (важные особенности поведения этого процесса см. в политике CMP0168).
После возврата команды FetchContent_Populate() в этой форме в области видимости вызывающего кода будут установлены следующие переменные:
-
<lowercaseName>_POPULATED -
Вызов всегда устанавливает для неё значение
TRUE. -
<lowercaseName>_SOURCE_DIR -
Расположение заполненного содержимого на момент возврата команды.
-
<lowercaseName>_BINARY_DIR -
Каталог, предназначенный для соответствующего каталога сборки.
Значения трёх переменных также можно получить из любой точки иерархии проекта с помощью команды FetchContent_GetProperties().
Реализация гарантирует, что если содержимое уже было заполнено при предыдущем запуске CMake, оно будет использовано повторно, а не заполнено заново. В обычном случае, когда заполнение подразумевает загрузку содержимого, затраты на загрузку возникают только один раз. Однако вызов FetchContent_Populate(<name>) с одним и тем же <name> более одного раза за один запуск CMake является ошибкой. Информацию о том, как определить, выполнялось ли заполнение <name> в текущем запуске, см. в разделе FetchContent_GetProperties().
-
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). Обратите внимание: значенияSOURCE_DIRиBINARY_DIRмогут быть пустыми, если вызов обработан поставщиком зависимостей.При использовании
FetchContent_MakeAvailable()эта команда требуется редко. Чаще её используют при реализации устаревшего шаблона с помощьюFetchContent_Populate(), чтобы соответствующие переменные всегда были определены независимо от того, выполнялось ли заполнение ранее в другом месте проекта:# WARNING: This pattern is deprecated, don't use it! # # 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_SetPopulated -
Добавлено в версии 3.24.
Примечание
Эту команду следует вызывать только поставщикам зависимостей. Её вызов в любом другом контексте не поддерживается; в таких случаях будущие версии CMake могут завершаться с критической ошибкой.
FetchContent_SetPopulated( <name> [SOURCE_DIR <srcDir>] [BINARY_DIR <binDir>] )
Если команда поставщика выполняет запрос
FETCHCONTENT_MAKEAVAILABLE_SERIAL, она должна вызвать эту функцию до возврата. АргументыSOURCE_DIRиBINARY_DIRможно использовать, чтобы задать значения, которыеFetchContent_GetProperties()должна возвращать для соответствующих аргументов. УказывайтеSOURCE_DIRиBINARY_DIRтолько в том случае, если они имеют тот же смысл, что и при заполнении встроенной реализациейFetchContent_MakeAvailable().
Переменные
На поведение могут влиять несколько переменных кэша, когда для заполнения содержимого используются сведения из вызова FetchContent_Declare().
Примечание
Все эти переменные предназначены для настройки поведения разработчиком. Обычно их не следует задавать в проекте.
-
FETCHCONTENT_BASE_DIR -
В большинстве случаев сохранённые сведения не указывают параметры каталогов для внутренней под-сборки, конечных исходных файлов и областей сборки. Как правило, лучше предоставить модулю
FetchContentвозможность принимать эти решения от имени проекта. Переменная кэшаFETCHCONTENT_BASE_DIRзадаёт каталог, в котором собираются все каталоги для получения содержимого, но в большинстве случаев разработчикам не потребуется её изменять. По умолчанию используется путь${CMAKE_BINARY_DIR}/_deps, но если разработчики изменят это значение, им следует выбрать короткий путь непосредственно под каталогом верхнего уровня дерева сборки, чтобы избежать проблем с длиной путей в Windows.
-
FETCHCONTENT_QUIET -
Вывод журнала во время получения содержимого может быть довольно многословным, из-за чего этап конфигурирования становится очень шумным. Этот параметр кэша (по умолчанию
ON) скрывает весь вывод получения содержимого, если не возникает ошибка. Если загрузки зависают, временное отключение этого параметра может помочь определить, при получении какого содержимого возникает проблема.Изменено в версии 3.30:
FETCHCONTENT_QUIETигнорируется, если для политикиCMP0168задано значениеNEW. В этом случае вывод по-прежнему по умолчанию скрыт, но подробность вывода определяется уровнем ведения журнала сообщений (см.CMAKE_MESSAGE_LOG_LEVELи--log-level).
-
FETCHCONTENT_FULLY_DISCONNECTED -
Если этот параметр включён, загрузка или обновление содержимого не выполняется. Предполагается, что всё содержимое уже было получено при предыдущем запуске либо каталоги исходных файлов указывают на существующее содержимое, предоставленное разработчиком вручную (с помощью параметров, описанных ниже). Если разработчик уверен, что сведения о содержимом не менялись, включение этого параметра
ONможет ускорить этап конфигурирования. По умолчанию онOFF.Примечание
Переменная
FETCHCONTENT_FULLY_DISCONNECTEDне подходит для предотвращения сетевого доступа при первом запуске в каталоге сборки. Это может нарушить работу проектов, привести к вводящим в заблуждение сообщениям об ошибках и скрыть незаметные сбои при получении содержимого. Эта переменная предназначена именно для включения после первого запуска CMake. Чтобы предотвратить сетевой доступ даже при первом запуске, используйте поставщик зависимостей и получайте зависимость из локального содержимого.Изменено в версии 3.30: Теперь проверяется, что каталог исходных файлов уже заполнен, если
FETCHCONTENT_FULLY_DISCONNECTEDимеет значение true. См. политикуCMP0170.
-
FETCHCONTENT_UPDATES_DISCONNECTED -
Это менее строгий параметр управления загрузками и обновлениями по сравнению с
FETCHCONTENT_FULLY_DISCONNECTED. Вместо отключения всей логики загрузки и обновления,FETCHCONTENT_UPDATES_DISCONNECTEDзапрещает этапу обновления устанавливать соединения с удалёнными серверами при использовании способов загрузки git или hg. Обновления по-прежнему выполняются, если сведения об этапе обновления изменились, однако при этом используются только данные, уже доступные локально (поэтому переход на другой тег или коммит, уже загруженный локально, будет успешным, а переход на неизвестный хеш коммита завершится ошибкой). На этап загрузки это не влияет: если содержимое ещё не загружалось, оно будет загружено и при включённом параметре. Это может ускорить этап конфигурирования, но не так сильно, какFETCHCONTENT_FULLY_DISCONNECTED. По умолчаниюFETCHCONTENT_UPDATES_DISCONNECTEDимеет значениеOFF.
-
FETCHCONTENT_TRY_FIND_PACKAGE_MODE -
Добавлено в версии 3.24.
Эта переменная изменяет сведения, которые
FetchContent_Declare()записывает для указанной зависимости. Хотя в конечном счёте она управляет поведениемFetchContent_MakeAvailable(), используется значение переменной на момент вызоваFetchContent_Declare(). Значение переменной при вызовеFetchContent_MakeAvailable()значения не имеет. Поскольку переменную должен задавать только пользователь, а не сами проекты, обычно её значение остаётся неизменным, поэтому это различие, как правило, незаметно.В конечном счёте
FETCHCONTENT_TRY_FIND_PACKAGE_MODEуправляет тем, разрешено лиFetchContent_MakeAvailable()вызыватьfind_package()для удовлетворения зависимости. Переменной можно присвоить одно из следующих значений:-
OPT_IN -
FetchContent_MakeAvailable()вызоветfind_package(), только если вызовFetchContent_Declare()содержал ключевое словоFIND_PACKAGE_ARGS. Это также поведение по умолчанию, еслиFETCHCONTENT_TRY_FIND_PACKAGE_MODEне задана. -
ALWAYS -
find_package()может быть вызван командойFetchContent_MakeAvailable()независимо от того, содержал ли вызовFetchContent_Declare()ключевое словоFIND_PACKAGE_ARGS. Если ключевое словоFIND_PACKAGE_ARGSне указано, поведение будет таким, как если бы было заданоFIND_PACKAGE_ARGSбез последующих дополнительных аргументов. -
NEVER -
FetchContent_MakeAvailable()не будет вызыватьfind_package(). Любой аргументFIND_PACKAGE_ARGS, указанный в вызовеFetchContent_Declare(), будет проигнорирован.
В качестве особого случая: если переменная
FETCHCONTENT_SOURCE_DIR_<uppercaseName>имеет непустое значение для зависимости, предполагается, что пользователь переопределяет все остальные способы предоставления этой зависимости.FETCHCONTENT_TRY_FIND_PACKAGE_MODEне повлияет на эту зависимость, иFetchContent_MakeAvailable()не будет пытаться вызвать для неёfind_package(). -
Кроме того, для каждого имени содержимого определяются следующие переменные:
-
FETCHCONTENT_SOURCE_DIR_<uppercaseName> -
Если эта переменная задана, этапы загрузки и обновления указанного содержимого не выполняются, а возвращаемая вызывающей стороне переменная
<lowercaseName>_SOURCE_DIRуказывает на это расположение. Это позволяет разработчикам иметь отдельную копию содержимого, которую они могут свободно изменять без влияния на сборку. Сборка просто использует существующие исходные файлы, но при этом переменная<lowercaseName>_BINARY_DIRпо-прежнему указывает внутрь собственной области сборки. Разработчикам настоятельно рекомендуется использовать этот механизм вместо редактирования исходных файлов, полученных в расположении по умолчанию: изменения в этом расположении могут быть потеряны, если проект изменит сведения о получении содержимого.
-
FETCHCONTENT_UPDATES_DISCONNECTED_<uppercaseName> -
Это аналог
FETCHCONTENT_UPDATES_DISCONNECTEDдля отдельного содержимого. Если глобальный параметр или этот параметр имеет значениеON, то при обновлении указанного содержимого способами git и hg соединения с удалёнными серверами устанавливаться не будут. Будут использоваться только данные, уже доступные локально. Отключение обновлений для отдельных элементов содержимого может быть полезно, если сведения о них меняются редко, при этом обновления для часто меняющегося содержимого останутся включёнными.
Примеры
Типичный случай
В этом первом, довольно простом примере обеспечивается доступность нескольких популярных платформ тестирования для основной сборки:
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 605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1 ) # 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)
Интеграция с find_package()
В предыдущем примере, если пользователь хочет сначала попытаться найти googletest и Catch2 с помощью find_package(), а уже затем загрузить и собрать их из исходного кода, он может присвоить переменной FETCHCONTENT_TRY_FIND_PACKAGE_MODE значение ALWAYS. Это также повлияет на все остальные вызовы FetchContent_Declare() в проекте, что может быть неприемлемо. Вместо этого такое поведение можно включить только для этих двух зависимостей, добавив FIND_PACKAGE_ARGS к объявленным сведениям и оставив FETCHCONTENT_TRY_FIND_PACKAGE_MODE незаданной или присвоив ей значение OPT_IN:
include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 FIND_PACKAGE_ARGS NAMES GTest ) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG 605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1 FIND_PACKAGE_ARGS ) # This will try calling find_package() first for both dependencies FetchContent_MakeAvailable(googletest Catch2)
Для Catch2 дополнительные аргументы для find_package() не нужны, поэтому после ключевого слова FIND_PACKAGE_ARGS аргументы не указываются. Пакет googletest чаще называют GTest, поэтому добавлены аргументы, позволяющие найти его под этим именем.
Если пользователь хочет запретить FetchContent_MakeAvailable() вызывать find_package() для любых зависимостей, даже если в объявленных сведениях для них указано FIND_PACKAGE_ARGS, он может присвоить переменной FETCHCONTENT_TRY_FIND_PACKAGE_MODE значение NEVER.
Если проект хочет указать, что эти две зависимости следует загружать и собирать из исходного кода, а вызовы find_package() следует перенаправлять на использование собранных зависимостей, при объявлении сведений о содержимом нужно использовать параметр OVERRIDE_FIND_PACKAGE:
include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 OVERRIDE_FIND_PACKAGE ) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG 605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1 OVERRIDE_FIND_PACKAGE ) # The following will automatically forward through to FetchContent_MakeAvailable() find_package(googletest) find_package(Catch2)
CMake предоставляет модуль FindGTest, который определяет несколько переменных, используемых в старых проектах вместо связывания с импортированными целями. Чтобы поддержать такие случаи, можно предоставить дополнительный файл. Следуя принципу «первым определил — победил» в FetchContent, мы создаём этот файл, только если его ещё не создал кто-то другой.
FetchContent_MakeAvailable(googletest)
if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-extra.cmake AND
NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletestExtra.cmake)
file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-extra.cmake
[=[
if("${GTEST_LIBRARIES}" STREQUAL "" AND TARGET GTest::gtest)
set(GTEST_LIBRARIES GTest::gtest)
endif()
if("${GTEST_MAIN_LIBRARIES}" STREQUAL "" AND TARGET GTest::gtest_main)
set(GTEST_MAIN_LIBRARIES GTest::gtest_main)
endif()
if("${GTEST_BOTH_LIBRARIES}" STREQUAL "")
set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
endif()
]=])
endif()
Проекты также, вероятно, будут использовать find_package(GTest) вместо find_package(googletest), однако можно воспользоваться каталогом CMAKE_FIND_PACKAGE_REDIRECTS_DIR, чтобы подключить последнее как зависимость первого. Этого, скорее всего, будет достаточно для удовлетворения типичного вызова find_package(GTest).
FetchContent_MakeAvailable(googletest)
if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config.cmake AND
NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/GTestConfig.cmake)
file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config.cmake
[=[
include(CMakeFindDependencyMacro)
find_dependency(googletest)
]=])
endif()
if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config-version.cmake AND
NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/GTestConfigVersion.cmake)
file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config-version.cmake
[=[
include(${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-config-version.cmake OPTIONAL)
if(NOT PACKAGE_VERSION_COMPATIBLE)
include(${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletestConfigVersion.cmake OPTIONAL)
endif()
]=])
endif()
Переопределение расположения CMakeLists.txt
Если файл CMakeLists.txt подпроекта находится не в корне дерева его исходных файлов, можно использовать параметр SOURCE_SUBDIR, чтобы указать FetchContent, где его искать. В следующем примере показано использование этого параметра; кроме того, перед добавлением подпроекта в основную сборку задаётся значимая для него переменная (как переменная кэша INTERNAL, чтобы избежать проблем с политикой CMP0077):
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 CACHE INTERNAL "") FetchContent_MakeAvailable(protobuf)
Сложные иерархии зависимостей
В более сложных иерархиях проектов связи между зависимостями могут быть запутаннее. Рассмотрим иерархию, в которой projA — проект верхнего уровня, напрямую зависящий от проектов projB и projC. Оба проекта, projB и projC, можно собирать отдельно, и оба они также зависят от другого проекта — projD. Кроме того, projB зависит от projE. В этом примере предполагается, что все пять проектов доступны на корпоративном сервере git. Файл CMakeLists.txt каждого проекта может содержать разделы следующего вида:
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)
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)
include(FetchContent) FetchContent_Declare( projD GIT_REPOSITORY git@mycompany.com:git/projD.git GIT_TAG 7d9a17ad2c962aa13e2fbb8043fb6b8a ) FetchContent_MakeAvailable(projD)
Следует отметить несколько важных моментов:
-
projBиprojCзадают разные сведения о содержимом дляprojD, ноprojAтакже задаёт набор сведений о содержимом дляprojD. ПосколькуprojAзадаст их первым, сведения изprojBиprojCиспользоваться не будут. Переопределяющие сведения, заданныеprojA, не обязаны совпадать с данными изprojBилиprojC, однако проект верхнего уровня должен убедиться, что заданные им сведения по-прежнему подходят дочерним проектам. - В вызове
FetchContent_MakeAvailable()из проектаprojAэлементprojDуказан передprojBиprojC, поэтому его содержимое будет получено раньше, чем содержимоеprojBилиprojC. ПроектуprojAне обязательно поступать так, но это гарантирует, чтоprojAполностью контролирует среду, в которойprojDвключается в сборку (особенно важны свойства каталогов). - Хотя
projAзадаёт сведения о содержимом дляprojE, ему не нужно явно вызыватьFetchContent_MakeAvailable(projE)илиFetchContent_Populate(projD). Вместо этого он предоставляет это дочернему проектуprojB. Для проектов верхнего уровня часто достаточно просто задать переопределяющие сведения о содержимом, оставив фактическое получение дочерним проектам. Так не приходится без необходимости повторять одно и то же на каждом уровне иерархии проекта, однако это следует делать только в том случае, если ожидается, что свойства каталогов, заданные зависимостями, не повлияют на получение общей зависимости (в данном случаеprojE).
Получение содержимого без добавления его в сборку
Проектам не всегда нужно добавлять полученное содержимое в сборку. Иногда проекту требуется лишь разместить загруженное содержимое в предсказуемом месте. Следующий пример обеспечивает доступность набора стандартных файлов цепочки инструментов компании (и, возможно, даже самих исполняемых файлов цепочки инструментов) достаточно рано, чтобы использовать их в той же сборке.
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
При обработке файла CMakeLists.txt CMake загрузит и распакует архив tar в _deps/mycompany_toolchains-src относительно каталога сборки. Переменная CMAKE_TOOLCHAIN_FILE используется только при достижении команды project(). В этот момент CMake ищет указанный файл цепочки инструментов относительно каталога сборки. К этому времени архив уже загружен и распакован, поэтому файл цепочки инструментов будет на месте даже при самом первом запуске cmake в каталоге сборки.
Получение содержимого в режиме сценариев CMake
В последнем примере показано, как загрузить и распаковать архив прошивки с помощью режима сценариев CMake. Вызов FetchContent_Populate() задаёт все сведения о содержимом, а распакованная прошивка помещается в каталог 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–2026 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/latest/module/FetchContent.html