FetchContent.cmake (38023B)
1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 # file Copyright.txt or https://cmake.org/licensing for details. 3 4 #[=======================================================================[.rst: 5 FetchContent 6 ------------------ 7 8 .. only:: html 9 10 .. contents:: 11 12 Overview 13 ^^^^^^^^ 14 15 This module enables populating content at configure time via any method 16 supported by the :module:`ExternalProject` module. Whereas 17 :command:`ExternalProject_Add` downloads at build time, the 18 ``FetchContent`` module makes content available immediately, allowing the 19 configure step to use the content in commands like :command:`add_subdirectory`, 20 :command:`include` or :command:`file` operations. 21 22 Content population details would normally be defined separately from the 23 command that performs the actual population. Projects should also 24 check whether the content has already been populated somewhere else in the 25 project hierarchy. Typical usage would look something like this: 26 27 .. code-block:: cmake 28 29 FetchContent_Declare( 30 googletest 31 GIT_REPOSITORY https://github.com/google/googletest.git 32 GIT_TAG release-1.8.0 33 ) 34 35 FetchContent_GetProperties(googletest) 36 if(NOT googletest_POPULATED) 37 FetchContent_Populate(googletest) 38 add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) 39 endif() 40 41 When using the above pattern with a hierarchical project arrangement, 42 projects at higher levels in the hierarchy are able to define or override 43 the population details of content specified anywhere lower in the project 44 hierarchy. The ability to detect whether content has already been 45 populated ensures that even if multiple child projects want certain content 46 to be available, the first one to populate it wins. The other child project 47 can simply make use of the already available content instead of repeating 48 the population for itself. See the 49 :ref:`Examples <fetch-content-examples>` section which demonstrates 50 this scenario. 51 52 The ``FetchContent`` module also supports defining and populating 53 content in a single call, with no check for whether the content has been 54 populated elsewhere in the project already. This is a more low level 55 operation and would not normally be the way the module is used, but it is 56 sometimes useful as part of implementing some higher level feature or to 57 populate some content in CMake's script mode. 58 59 60 Declaring Content Details 61 ^^^^^^^^^^^^^^^^^^^^^^^^^ 62 63 .. command:: FetchContent_Declare 64 65 .. code-block:: cmake 66 67 FetchContent_Declare(<name> <contentOptions>...) 68 69 The ``FetchContent_Declare()`` function records the options that describe 70 how to populate the specified content, but if such details have already 71 been recorded earlier in this project (regardless of where in the project 72 hierarchy), this and all later calls for the same content ``<name>`` are 73 ignored. This "first to record, wins" approach is what allows hierarchical 74 projects to have parent projects override content details of child projects. 75 76 The content ``<name>`` can be any string without spaces, but good practice 77 would be to use only letters, numbers and underscores. The name will be 78 treated case-insensitively and it should be obvious for the content it 79 represents, often being the name of the child project or the value given 80 to its top level :command:`project` command (if it is a CMake project). 81 For well-known public projects, the name should generally be the official 82 name of the project. Choosing an unusual name makes it unlikely that other 83 projects needing that same content will use the same name, leading to 84 the content being populated multiple times. 85 86 The ``<contentOptions>`` can be any of the download or update/patch options 87 that the :command:`ExternalProject_Add` command understands. The configure, 88 build, install and test steps are explicitly disabled and therefore options 89 related to them will be ignored. In most cases, ``<contentOptions>`` will 90 just be a couple of options defining the download method and method-specific 91 details like a commit tag or archive hash. For example: 92 93 .. code-block:: cmake 94 95 FetchContent_Declare( 96 googletest 97 GIT_REPOSITORY https://github.com/google/googletest.git 98 GIT_TAG release-1.8.0 99 ) 100 101 FetchContent_Declare( 102 myCompanyIcons 103 URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz 104 URL_HASH 5588a7b18261c20068beabfb4f530b87 105 ) 106 107 FetchContent_Declare( 108 myCompanyCertificates 109 SVN_REPOSITORY svn+ssh://svn.mycompany.com/srv/svn/trunk/certs 110 SVN_REVISION -r12345 111 ) 112 113 Populating The Content 114 ^^^^^^^^^^^^^^^^^^^^^^ 115 116 .. command:: FetchContent_Populate 117 118 .. code-block:: cmake 119 120 FetchContent_Populate( <name> ) 121 122 In most cases, the only argument given to ``FetchContent_Populate()`` is the 123 ``<name>``. When used this way, the command assumes the content details have 124 been recorded by an earlier call to :command:`FetchContent_Declare`. The 125 details are stored in a global property, so they are unaffected by things 126 like variable or directory scope. Therefore, it doesn't matter where in the 127 project the details were previously declared, as long as they have been 128 declared before the call to ``FetchContent_Populate()``. Those saved details 129 are then used to construct a call to :command:`ExternalProject_Add` in a 130 private sub-build to perform the content population immediately. The 131 implementation of ``ExternalProject_Add()`` ensures that if the content has 132 already been populated in a previous CMake run, that content will be reused 133 rather than repopulating them again. For the common case where population 134 involves downloading content, the cost of the download is only paid once. 135 136 An internal global property records when a particular content population 137 request has been processed. If ``FetchContent_Populate()`` is called more 138 than once for the same content name within a configure run, the second call 139 will halt with an error. Projects can and should check whether content 140 population has already been processed with the 141 :command:`FetchContent_GetProperties` command before calling 142 ``FetchContent_Populate()``. 143 144 ``FetchContent_Populate()`` will set three variables in the scope of the 145 caller; ``<lcName>_POPULATED``, ``<lcName>_SOURCE_DIR`` and 146 ``<lcName>_BINARY_DIR``, where ``<lcName>`` is the lowercased ``<name>``. 147 ``<lcName>_POPULATED`` will always be set to ``True`` by the call. 148 ``<lcName>_SOURCE_DIR`` is the location where the 149 content can be found upon return (it will have already been populated), while 150 ``<lcName>_BINARY_DIR`` is a directory intended for use as a corresponding 151 build directory. The main use case for the two directory variables is to 152 call :command:`add_subdirectory` immediately after population, i.e.: 153 154 .. code-block:: cmake 155 156 FetchContent_Populate(FooBar ...) 157 add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) 158 159 The values of the three variables can also be retrieved from anywhere in the 160 project hierarchy using the :command:`FetchContent_GetProperties` command. 161 162 A number of cache variables influence the behavior of all content population 163 performed using details saved from a :command:`FetchContent_Declare` call: 164 165 ``FETCHCONTENT_BASE_DIR`` 166 In most cases, the saved details do not specify any options relating to the 167 directories to use for the internal sub-build, final source and build areas. 168 It is generally best to leave these decisions up to the ``FetchContent`` 169 module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` 170 cache variable controls the point under which all content population 171 directories are collected, but in most cases developers would not need to 172 change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if 173 developers change this value, they should aim to keep the path short and 174 just below the top level of the build tree to avoid running into path 175 length problems on Windows. 176 177 ``FETCHCONTENT_QUIET`` 178 The logging output during population can be quite verbose, making the 179 configure stage quite noisy. This cache option (``ON`` by default) hides 180 all population output unless an error is encountered. If experiencing 181 problems with hung downloads, temporarily switching this option off may 182 help diagnose which content population is causing the issue. 183 184 ``FETCHCONTENT_FULLY_DISCONNECTED`` 185 When this option is enabled, no attempt is made to download or update 186 any content. It is assumed that all content has already been populated in 187 a previous run or the source directories have been pointed at existing 188 contents the developer has provided manually (using options described 189 further below). When the developer knows that no changes have been made to 190 any content details, turning this option ``ON`` can significantly speed up 191 the configure stage. It is ``OFF`` by default. 192 193 ``FETCHCONTENT_UPDATES_DISCONNECTED`` 194 This is a less severe download/update control compared to 195 ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and 196 update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the 197 update stage. Therefore, if content has not been downloaded previously, 198 it will still be downloaded when this option is enabled. This can speed up 199 the configure stage, but not as much as 200 ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default. 201 202 In addition to the above cache variables, the following cache variables are 203 also defined for each content name (``<ucName>`` is the uppercased value of 204 ``<name>``): 205 206 ``FETCHCONTENT_SOURCE_DIR_<ucName>`` 207 If this is set, no download or update steps are performed for the specified 208 content and the ``<lcName>_SOURCE_DIR`` variable returned to the caller is 209 pointed at this location. This gives developers a way to have a separate 210 checkout of the content that they can modify freely without interference 211 from the build. The build simply uses that existing source, but it still 212 defines ``<lcName>_BINARY_DIR`` to point inside its own build area. 213 Developers are strongly encouraged to use this mechanism rather than 214 editing the sources populated in the default location, as changes to 215 sources in the default location can be lost when content population details 216 are changed by the project. 217 218 ``FETCHCONTENT_UPDATES_DISCONNECTED_<ucName>`` 219 This is the per-content equivalent of 220 ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option 221 is ``ON``, then updates will be disabled for the named content. 222 Disabling updates for individual content can be useful for content whose 223 details rarely change, while still leaving other frequently changing 224 content with updates enabled. 225 226 227 The ``FetchContent_Populate()`` command also supports a syntax allowing the 228 content details to be specified directly rather than using any saved 229 details. This is more low-level and use of this form is generally to be 230 avoided in favour of using saved content details as outlined above. 231 Nevertheless, in certain situations it can be useful to invoke the content 232 population as an isolated operation (typically as part of implementing some 233 other higher level feature or when using CMake in script mode): 234 235 .. code-block:: cmake 236 237 FetchContent_Populate( <name> 238 [QUIET] 239 [SUBBUILD_DIR <subBuildDir>] 240 [SOURCE_DIR <srcDir>] 241 [BINARY_DIR <binDir>] 242 ... 243 ) 244 245 This form has a number of key differences to that where only ``<name>`` is 246 provided: 247 248 - All required population details are assumed to have been provided directly 249 in the call to ``FetchContent_Populate()``. Any saved details for 250 ``<name>`` are ignored. 251 - No check is made for whether content for ``<name>`` has already been 252 populated. 253 - No global property is set to record that the population has occurred. 254 - No global properties record the source or binary directories used for the 255 populated content. 256 - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and 257 ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored. 258 259 The ``<lcName>_SOURCE_DIR`` and ``<lcName>_BINARY_DIR`` variables are still 260 returned to the caller, but since these locations are not stored as global 261 properties when this form is used, they are only available to the calling 262 scope and below rather than the entire project hierarchy. No 263 ``<lcName>_POPULATED`` variable is set in the caller's scope with this form. 264 265 The supported options for ``FetchContent_Populate()`` are the same as those 266 for :command:`FetchContent_Declare()`. Those few options shown just 267 above are either specific to ``FetchContent_Populate()`` or their behavior is 268 slightly modified from how :command:`ExternalProject_Add` treats them. 269 270 ``QUIET`` 271 The ``QUIET`` option can be given to hide the output associated with 272 populating the specified content. If the population fails, the output will 273 be shown regardless of whether this option was given or not so that the 274 cause of the failure can be diagnosed. The global ``FETCHCONTENT_QUIET`` 275 cache variable has no effect on ``FetchContent_Populate()`` calls where the 276 content details are provided directly. 277 278 ``SUBBUILD_DIR`` 279 The ``SUBBUILD_DIR`` argument can be provided to change the location of the 280 sub-build created to perform the population. The default value is 281 ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual 282 to need to override this default. If a relative path is specified, it will 283 be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. 284 285 ``SOURCE_DIR``, ``BINARY_DIR`` 286 The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by 287 :command:`ExternalProject_Add`, but different default values are used by 288 ``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to 289 ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-src`` and ``BINARY_DIR`` defaults to 290 ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build``. If a relative path is 291 specified, it will be interpreted as relative to 292 :variable:`CMAKE_CURRENT_BINARY_DIR`. 293 294 In addition to the above explicit options, any other unrecognized options are 295 passed through unmodified to :command:`ExternalProject_Add` to perform the 296 download, patch and update steps. The following options are explicitly 297 prohibited (they are disabled by the ``FetchContent_Populate()`` command): 298 299 - ``CONFIGURE_COMMAND`` 300 - ``BUILD_COMMAND`` 301 - ``INSTALL_COMMAND`` 302 - ``TEST_COMMAND`` 303 304 If using ``FetchContent_Populate()`` within CMake's script mode, be aware 305 that the implementation sets up a sub-build which therefore requires a CMake 306 generator and build tool to be available. If these cannot be found by 307 default, then the :variable:`CMAKE_GENERATOR` and/or 308 :variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately 309 on the command line invoking the script. 310 311 312 Retrieve Population Properties 313 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 314 315 .. command:: FetchContent_GetProperties 316 317 When using saved content details, a call to :command:`FetchContent_Populate` 318 records information in global properties which can be queried at any time. 319 This information includes the source and binary directories associated with 320 the content and also whether or not the content population has been processed 321 during the current configure run. 322 323 .. code-block:: cmake 324 325 FetchContent_GetProperties( <name> 326 [SOURCE_DIR <srcDirVar>] 327 [BINARY_DIR <binDirVar>] 328 [POPULATED <doneVar>] 329 ) 330 331 The ``SOURCE_DIR``, ``BINARY_DIR`` and ``POPULATED`` options can be used to 332 specify which properties should be retrieved. Each option accepts a value 333 which is the name of the variable in which to store that property. Most of 334 the time though, only ``<name>`` is given, in which case the call will then 335 set the same variables as a call to 336 :command:`FetchContent_Populate(name) <FetchContent_Populate>`. This allows 337 the following canonical pattern to be used, which ensures that the relevant 338 variables will always be defined regardless of whether or not the population 339 has been performed elsewhere in the project already: 340 341 .. code-block:: cmake 342 343 FetchContent_GetProperties(foobar) 344 if(NOT foobar_POPULATED) 345 FetchContent_Populate(foobar) 346 347 # Set any custom variables, etc. here, then 348 # populate the content as part of this build 349 350 add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) 351 endif() 352 353 The above pattern allows other parts of the overall project hierarchy to 354 re-use the same content and ensure that it is only populated once. 355 356 357 .. _`fetch-content-examples`: 358 359 Examples 360 ^^^^^^^^ 361 362 Consider a project hierarchy where ``projA`` is the top level project and it 363 depends on projects ``projB`` and ``projC``. Both ``projB`` and ``projC`` 364 can be built standalone and they also both depend on another project 365 ``projD``. For simplicity, this example will assume that all four projects 366 are available on a company git server. The ``CMakeLists.txt`` of each project 367 might have sections like the following: 368 369 *projA*: 370 371 .. code-block:: cmake 372 373 include(FetchContent) 374 FetchContent_Declare( 375 projB 376 GIT_REPOSITORY git@mycompany.com/git/projB.git 377 GIT_TAG 4a89dc7e24ff212a7b5167bef7ab079d 378 ) 379 FetchContent_Declare( 380 projC 381 GIT_REPOSITORY git@mycompany.com/git/projC.git 382 GIT_TAG 4ad4016bd1d8d5412d135cf8ceea1bb9 383 ) 384 FetchContent_Declare( 385 projD 386 GIT_REPOSITORY git@mycompany.com/git/projD.git 387 GIT_TAG origin/integrationBranch 388 ) 389 390 FetchContent_GetProperties(projB) 391 if(NOT projb_POPULATED) 392 FetchContent_Populate(projB) 393 add_subdirectory(${projb_SOURCE_DIR} ${projb_BINARY_DIR}) 394 endif() 395 396 FetchContent_GetProperties(projC) 397 if(NOT projc_POPULATED) 398 FetchContent_Populate(projC) 399 add_subdirectory(${projc_SOURCE_DIR} ${projc_BINARY_DIR}) 400 endif() 401 402 *projB*: 403 404 .. code-block:: cmake 405 406 include(FetchContent) 407 FetchContent_Declare( 408 projD 409 GIT_REPOSITORY git@mycompany.com/git/projD.git 410 GIT_TAG 20b415f9034bbd2a2e8216e9a5c9e632 411 ) 412 413 FetchContent_GetProperties(projD) 414 if(NOT projd_POPULATED) 415 FetchContent_Populate(projD) 416 add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) 417 endif() 418 419 420 *projC*: 421 422 .. code-block:: cmake 423 424 include(FetchContent) 425 FetchContent_Declare( 426 projD 427 GIT_REPOSITORY git@mycompany.com/git/projD.git 428 GIT_TAG 7d9a17ad2c962aa13e2fbb8043fb6b8a 429 ) 430 431 FetchContent_GetProperties(projD) 432 if(NOT projd_POPULATED) 433 FetchContent_Populate(projD) 434 add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) 435 endif() 436 437 A few key points should be noted in the above: 438 439 - ``projB`` and ``projC`` define different content details for ``projD``, 440 but ``projA`` also defines a set of content details for ``projD`` and 441 because ``projA`` will define them first, the details from ``projB`` and 442 ``projC`` will not be used. The override details defined by ``projA`` 443 are not required to match either of those from ``projB`` or ``projC``, but 444 it is up to the higher level project to ensure that the details it does 445 define still make sense for the child projects. 446 - While ``projA`` defined content details for ``projD``, it did not need 447 to explicitly call ``FetchContent_Populate(projD)`` itself. Instead, it 448 leaves that to a child project to do (in this case it will be ``projB`` 449 since it is added to the build ahead of ``projC``). If ``projA`` needed to 450 customize how the ``projD`` content was brought into the build as well 451 (e.g. define some CMake variables before calling 452 :command:`add_subdirectory` after populating), it would do the call to 453 ``FetchContent_Populate()``, etc. just as it did for the ``projB`` and 454 ``projC`` content. For higher level projects, it is usually enough to 455 just define the override content details and leave the actual population 456 to the child projects. This saves repeating the same thing at each level 457 of the project hierarchy unnecessarily. 458 - Even though ``projA`` is the top level project in this example, it still 459 checks whether ``projB`` and ``projC`` have already been populated before 460 going ahead to do those populations. This makes ``projA`` able to be more 461 easily incorporated as a child of some other higher level project in the 462 future if required. Always protect a call to 463 :command:`FetchContent_Populate` with a check to 464 :command:`FetchContent_GetProperties`, even in what may be considered a top 465 level project at the time. 466 467 468 The following example demonstrates how one might download and unpack a 469 firmware tarball using CMake's :manual:`script mode <cmake(1)>`. The call to 470 :command:`FetchContent_Populate` specifies all the content details and the 471 unpacked firmware will be placed in a ``firmware`` directory below the 472 current working directory. 473 474 *getFirmware.cmake*: 475 476 .. code-block:: cmake 477 478 # NOTE: Intended to be run in script mode with cmake -P 479 include(FetchContent) 480 FetchContent_Populate( 481 firmware 482 URL https://mycompany.com/assets/firmware-1.23-arm.tar.gz 483 URL_HASH MD5=68247684da89b608d466253762b0ff11 484 SOURCE_DIR firmware 485 ) 486 487 #]=======================================================================] 488 489 490 set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent") 491 492 #======================================================================= 493 # Recording and retrieving content details for later population 494 #======================================================================= 495 496 # Internal use, projects must not call this directly. It is 497 # intended for use by FetchContent_Declare() only. 498 # 499 # Sets a content-specific global property (not meant for use 500 # outside of functions defined here in this file) which can later 501 # be retrieved using __FetchContent_getSavedDetails() with just the 502 # same content name. If there is already a value stored in the 503 # property, it is left unchanged and this call has no effect. 504 # This allows parent projects to define the content details, 505 # overriding anything a child project may try to set (properties 506 # are not cached between runs, so the first thing to set it in a 507 # build will be in control). 508 function(__FetchContent_declareDetails contentName) 509 510 string(TOLOWER ${contentName} contentNameLower) 511 set(propertyName "_FetchContent_${contentNameLower}_savedDetails") 512 get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) 513 if(NOT alreadyDefined) 514 define_property(GLOBAL PROPERTY ${propertyName} 515 BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" 516 FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" 517 ) 518 set_property(GLOBAL PROPERTY ${propertyName} ${ARGN}) 519 endif() 520 521 endfunction() 522 523 524 # Internal use, projects must not call this directly. It is 525 # intended for use by the FetchContent_Declare() function. 526 # 527 # Retrieves details saved for the specified content in an 528 # earlier call to __FetchContent_declareDetails(). 529 function(__FetchContent_getSavedDetails contentName outVar) 530 531 string(TOLOWER ${contentName} contentNameLower) 532 set(propertyName "_FetchContent_${contentNameLower}_savedDetails") 533 get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) 534 if(NOT alreadyDefined) 535 message(FATAL_ERROR "No content details recorded for ${contentName}") 536 endif() 537 get_property(propertyValue GLOBAL PROPERTY ${propertyName}) 538 set(${outVar} "${propertyValue}" PARENT_SCOPE) 539 540 endfunction() 541 542 543 # Saves population details of the content, sets defaults for the 544 # SOURCE_DIR and BUILD_DIR. 545 function(FetchContent_Declare contentName) 546 547 set(options "") 548 set(oneValueArgs SVN_REPOSITORY) 549 set(multiValueArgs "") 550 551 cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 552 553 unset(srcDirSuffix) 554 unset(svnRepoArgs) 555 if(ARG_SVN_REPOSITORY) 556 # Add a hash of the svn repository URL to the source dir. This works 557 # around the problem where if the URL changes, the download would 558 # fail because it tries to checkout/update rather than switch the 559 # old URL to the new one. We limit the hash to the first 7 characters 560 # so that the source path doesn't get overly long (which can be a 561 # problem on windows due to path length limits). 562 string(SHA1 urlSHA ${ARG_SVN_REPOSITORY}) 563 string(SUBSTRING ${urlSHA} 0 7 urlSHA) 564 set(srcDirSuffix "-${urlSHA}") 565 set(svnRepoArgs SVN_REPOSITORY ${ARG_SVN_REPOSITORY}) 566 endif() 567 568 string(TOLOWER ${contentName} contentNameLower) 569 __FetchContent_declareDetails( 570 ${contentNameLower} 571 SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}" 572 BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" 573 ${svnRepoArgs} 574 # List these last so they can override things we set above 575 ${ARG_UNPARSED_ARGUMENTS} 576 ) 577 578 endfunction() 579 580 581 #======================================================================= 582 # Set/get whether the specified content has been populated yet. 583 # The setter also records the source and binary dirs used. 584 #======================================================================= 585 586 # Internal use, projects must not call this directly. It is 587 # intended for use by the FetchContent_Populate() function to 588 # record when FetchContent_Populate() is called for a particular 589 # content name. 590 function(__FetchContent_setPopulated contentName sourceDir binaryDir) 591 592 string(TOLOWER ${contentName} contentNameLower) 593 set(prefix "_FetchContent_${contentNameLower}") 594 595 set(propertyName "${prefix}_sourceDir") 596 define_property(GLOBAL PROPERTY ${propertyName} 597 BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" 598 FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" 599 ) 600 set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir}) 601 602 set(propertyName "${prefix}_binaryDir") 603 define_property(GLOBAL PROPERTY ${propertyName} 604 BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" 605 FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" 606 ) 607 set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir}) 608 609 set(propertyName "${prefix}_populated") 610 define_property(GLOBAL PROPERTY ${propertyName} 611 BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" 612 FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" 613 ) 614 set_property(GLOBAL PROPERTY ${propertyName} True) 615 616 endfunction() 617 618 619 # Set variables in the calling scope for any of the retrievable 620 # properties. If no specific properties are requested, variables 621 # will be set for all retrievable properties. 622 # 623 # This function is intended to also be used by projects as the canonical 624 # way to detect whether they should call FetchContent_Populate() 625 # and pull the populated source into the build with add_subdirectory(), 626 # if they are using the populated content in that way. 627 function(FetchContent_GetProperties contentName) 628 629 string(TOLOWER ${contentName} contentNameLower) 630 631 set(options "") 632 set(oneValueArgs SOURCE_DIR BINARY_DIR POPULATED) 633 set(multiValueArgs "") 634 635 cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 636 637 if(NOT ARG_SOURCE_DIR AND 638 NOT ARG_BINARY_DIR AND 639 NOT ARG_POPULATED) 640 # No specific properties requested, provide them all 641 set(ARG_SOURCE_DIR ${contentNameLower}_SOURCE_DIR) 642 set(ARG_BINARY_DIR ${contentNameLower}_BINARY_DIR) 643 set(ARG_POPULATED ${contentNameLower}_POPULATED) 644 endif() 645 646 set(prefix "_FetchContent_${contentNameLower}") 647 648 if(ARG_SOURCE_DIR) 649 set(propertyName "${prefix}_sourceDir") 650 get_property(value GLOBAL PROPERTY ${propertyName}) 651 if(value) 652 set(${ARG_SOURCE_DIR} ${value} PARENT_SCOPE) 653 endif() 654 endif() 655 656 if(ARG_BINARY_DIR) 657 set(propertyName "${prefix}_binaryDir") 658 get_property(value GLOBAL PROPERTY ${propertyName}) 659 if(value) 660 set(${ARG_BINARY_DIR} ${value} PARENT_SCOPE) 661 endif() 662 endif() 663 664 if(ARG_POPULATED) 665 set(propertyName "${prefix}_populated") 666 get_property(value GLOBAL PROPERTY ${propertyName} DEFINED) 667 set(${ARG_POPULATED} ${value} PARENT_SCOPE) 668 endif() 669 670 endfunction() 671 672 673 #======================================================================= 674 # Performing the population 675 #======================================================================= 676 677 # The value of contentName will always have been lowercased by the caller. 678 # All other arguments are assumed to be options that are understood by 679 # ExternalProject_Add(), except for QUIET and SUBBUILD_DIR. 680 function(__FetchContent_directPopulate contentName) 681 682 set(options 683 QUIET 684 ) 685 set(oneValueArgs 686 SUBBUILD_DIR 687 SOURCE_DIR 688 BINARY_DIR 689 # Prevent the following from being passed through 690 CONFIGURE_COMMAND 691 BUILD_COMMAND 692 INSTALL_COMMAND 693 TEST_COMMAND 694 ) 695 set(multiValueArgs "") 696 697 cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 698 699 if(NOT ARG_SUBBUILD_DIR) 700 message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set") 701 elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}") 702 set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}") 703 endif() 704 705 if(NOT ARG_SOURCE_DIR) 706 message(FATAL_ERROR "Internal error: SOURCE_DIR not set") 707 elseif(NOT IS_ABSOLUTE "${ARG_SOURCE_DIR}") 708 set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SOURCE_DIR}") 709 endif() 710 711 if(NOT ARG_BINARY_DIR) 712 message(FATAL_ERROR "Internal error: BINARY_DIR not set") 713 elseif(NOT IS_ABSOLUTE "${ARG_BINARY_DIR}") 714 set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY_DIR}") 715 endif() 716 717 # Ensure the caller can know where to find the source and build directories 718 # with some convenient variables. Doing this here ensures the caller sees 719 # the correct result in the case where the default values are overridden by 720 # the content details set by the project. 721 set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE) 722 set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE) 723 724 # The unparsed arguments may contain spaces, so build up ARG_EXTRA 725 # in such a way that it correctly substitutes into the generated 726 # CMakeLists.txt file with each argument quoted. 727 unset(ARG_EXTRA) 728 foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS) 729 set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"") 730 endforeach() 731 732 # Hide output if requested, but save it to a variable in case there's an 733 # error so we can show the output upon failure. When not quiet, don't 734 # capture the output to a variable because the user may want to see the 735 # output as it happens (e.g. progress during long downloads). Combine both 736 # stdout and stderr in the one capture variable so the output stays in order. 737 if (ARG_QUIET) 738 set(outputOptions 739 OUTPUT_VARIABLE capturedOutput 740 ERROR_VARIABLE capturedOutput 741 ) 742 else() 743 set(capturedOutput) 744 set(outputOptions) 745 message(STATUS "Populating ${contentName}") 746 endif() 747 748 if(CMAKE_GENERATOR) 749 set(generatorOpts "-G${CMAKE_GENERATOR}") 750 if(CMAKE_GENERATOR_PLATFORM) 751 list(APPEND generatorOpts "-A${CMAKE_GENERATOR_PLATFORM}") 752 endif() 753 if(CMAKE_GENERATOR_TOOLSET) 754 list(APPEND generatorOpts "-T${CMAKE_GENERATOR_TOOLSET}") 755 endif() 756 757 if(CMAKE_MAKE_PROGRAM) 758 list(APPEND generatorOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") 759 endif() 760 761 else() 762 # Likely we've been invoked via CMake's script mode where no 763 # generator is set (and hence CMAKE_MAKE_PROGRAM could not be 764 # trusted even if provided). We will have to rely on being 765 # able to find the default generator and build tool. 766 unset(generatorOpts) 767 endif() 768 769 # Create and build a separate CMake project to carry out the population. 770 # If we've already previously done these steps, they will not cause 771 # anything to be updated, so extra rebuilds of the project won't occur. 772 # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project 773 # has this set to something not findable on the PATH. 774 configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in" 775 "${ARG_SUBBUILD_DIR}/CMakeLists.txt") 776 execute_process( 777 COMMAND ${CMAKE_COMMAND} ${generatorOpts} . 778 RESULT_VARIABLE result 779 ${outputOptions} 780 WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" 781 ) 782 if(result) 783 if(capturedOutput) 784 message("${capturedOutput}") 785 endif() 786 message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") 787 endif() 788 execute_process( 789 COMMAND ${CMAKE_COMMAND} --build . 790 RESULT_VARIABLE result 791 ${outputOptions} 792 WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" 793 ) 794 if(result) 795 if(capturedOutput) 796 message("${capturedOutput}") 797 endif() 798 message(FATAL_ERROR "Build step for ${contentName} failed: ${result}") 799 endif() 800 801 endfunction() 802 803 804 option(FETCHCONTENT_FULLY_DISCONNECTED "Disables all attempts to download or update content and assumes source dirs already exist") 805 option(FETCHCONTENT_UPDATES_DISCONNECTED "Enables UPDATE_DISCONNECTED behavior for all content population") 806 option(FETCHCONTENT_QUIET "Enables QUIET option for all content population" ON) 807 set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/_deps" CACHE PATH "Directory under which to collect all populated content") 808 809 # Populate the specified content using details stored from 810 # an earlier call to FetchContent_Declare(). 811 function(FetchContent_Populate contentName) 812 813 if(NOT contentName) 814 message(FATAL_ERROR "Empty contentName not allowed for FetchContent_Populate()") 815 endif() 816 817 string(TOLOWER ${contentName} contentNameLower) 818 819 if(ARGN) 820 # This is the direct population form with details fully specified 821 # as part of the call, so we already have everything we need 822 __FetchContent_directPopulate( 823 ${contentNameLower} 824 SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild" 825 SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src" 826 BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-build" 827 ${ARGN} # Could override any of the above ..._DIR variables 828 ) 829 830 # Pass source and binary dir variables back to the caller 831 set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) 832 set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) 833 834 # Don't set global properties, or record that we did this population, since 835 # this was a direct call outside of the normal declared details form. 836 # We only want to save values in the global properties for content that 837 # honours the hierarchical details mechanism so that projects are not 838 # robbed of the ability to override details set in nested projects. 839 return() 840 endif() 841 842 # No details provided, so assume they were saved from an earlier call 843 # to FetchContent_Declare(). Do a check that we haven't already 844 # populated this content before in case the caller forgot to check. 845 FetchContent_GetProperties(${contentName}) 846 if(${contentNameLower}_POPULATED) 847 message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") 848 endif() 849 850 string(TOUPPER ${contentName} contentNameUpper) 851 set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper} 852 "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}" 853 CACHE PATH "When not empty, overrides where to find pre-populated content for ${contentName}") 854 855 if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}) 856 # The source directory has been explicitly provided in the cache, 857 # so no population is required 858 set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") 859 set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") 860 861 elseif(FETCHCONTENT_FULLY_DISCONNECTED) 862 # Bypass population and assume source is already there from a previous run 863 set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") 864 set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") 865 866 else() 867 # Support both a global "disconnect all updates" and a per-content 868 # update test (either one being set disables updates for this content). 869 option(FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper} 870 "Enables UPDATE_DISCONNECTED behavior just for population of ${contentName}") 871 if(FETCHCONTENT_UPDATES_DISCONNECTED OR 872 FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper}) 873 set(disconnectUpdates True) 874 else() 875 set(disconnectUpdates False) 876 endif() 877 878 if(FETCHCONTENT_QUIET) 879 set(quietFlag QUIET) 880 else() 881 unset(quietFlag) 882 endif() 883 884 __FetchContent_getSavedDetails(${contentName} contentDetails) 885 if("${contentDetails}" STREQUAL "") 886 message(FATAL_ERROR "No details have been set for content: ${contentName}") 887 endif() 888 889 __FetchContent_directPopulate( 890 ${contentNameLower} 891 ${quietFlag} 892 UPDATE_DISCONNECTED ${disconnectUpdates} 893 SUBBUILD_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-subbuild" 894 SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src" 895 BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" 896 # Put the saved details last so they can override any of the 897 # the options we set above (this can include SOURCE_DIR or 898 # BUILD_DIR) 899 ${contentDetails} 900 ) 901 endif() 902 903 __FetchContent_setPopulated( 904 ${contentName} 905 ${${contentNameLower}_SOURCE_DIR} 906 ${${contentNameLower}_BINARY_DIR} 907 ) 908 909 # Pass variables back to the caller. The variables passed back here 910 # must match what FetchContent_GetProperties() sets when it is called 911 # with just the content name. 912 set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) 913 set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) 914 set(${contentNameLower}_POPULATED True PARENT_SCOPE) 915 916 endfunction()