summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2020-05-16 06:57:01 (GMT)
committerCraig Scott <craig.scott@crascit.com>2020-05-16 07:01:10 (GMT)
commit592085b94bb9b9c55f20fa6b13c2a3c0a7ab5d33 (patch)
tree2acf99a864db78f0e0a07d742b931b8fcafe69f5 /Modules
parentec1b3992dbfb54edb777988766440295f1f1f1d3 (diff)
downloadCMake-592085b94bb9b9c55f20fa6b13c2a3c0a7ab5d33.zip
CMake-592085b94bb9b9c55f20fa6b13c2a3c0a7ab5d33.tar.gz
CMake-592085b94bb9b9c55f20fa6b13c2a3c0a7ab5d33.tar.bz2
FetchContent: Add support for SOURCE_SUBDIR
Fixes: #19875
Diffstat (limited to 'Modules')
-rw-r--r--Modules/FetchContent.cmake70
1 files changed, 58 insertions, 12 deletions
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 400754c..45b50d4 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -108,9 +108,13 @@ Declaring Content Details
The ``<contentOptions>`` can be any of the download or update/patch options
that the :command:`ExternalProject_Add` command understands. The configure,
build, install and test steps are explicitly disabled and therefore options
- related to them will be ignored. In most cases, ``<contentOptions>`` will
- just be a couple of options defining the download method and method-specific
- details like a commit tag or archive hash. For example:
+ related to them will be ignored. The ``SOURCE_SUBDIR`` option is an
+ exception, see :command:`FetchContent_MakeAvailable` for details on how that
+ affects behavior.
+
+ In most cases, ``<contentOptions>`` will just be a couple of options defining
+ the download method and method-specific details like a commit tag or archive
+ hash. For example:
.. code-block:: cmake
@@ -164,8 +168,9 @@ approach. The former generally follows this canonical pattern:
The above is such a common pattern that, where no custom steps are needed
between the calls to :command:`FetchContent_Populate` and
:command:`add_subdirectory`, equivalent logic can be obtained by calling
-:command:`FetchContent_MakeAvailable` instead (and should be preferred where
-it meets the needs of the project).
+:command:`FetchContent_MakeAvailable` instead. Where it meets the needs of
+the project, :command:`FetchContent_MakeAvailable` should be preferred, as it
+is simpler and provides additional features over the pattern above.
.. command:: FetchContent_Populate
@@ -335,6 +340,8 @@ it meets the needs of the project).
``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual
to need to override this default. If a relative path is specified, it will
be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ This option should not be confused with the ``SOURCE_SUBDIR`` option which
+ only affects the :command:`FetchContent_MakeAvailable` command.
``SOURCE_DIR``, ``BINARY_DIR``
The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by
@@ -409,15 +416,22 @@ it meets the needs of the project).
This command implements the common pattern typically needed for most
dependencies. It iterates over each of the named dependencies in turn
- and for each one it loosely follows the same
+ and for each one it loosely follows the
:ref:`canonical pattern <fetch-content-canonical-pattern>` as
- presented at the beginning of this section. One small difference to
- that pattern is that it will only call :command:`add_subdirectory` on the
+ presented at the beginning of this section. An important difference is
+ that :command:`add_subdirectory` will only be called on the
populated content if there is a ``CMakeLists.txt`` file in its top level
source directory. This allows the command to be used for dependencies
that make downloaded content available at a known location but which do
not need or support being added directly to the build.
+ The ``SOURCE_SUBDIR`` option can be given in the declared details to
+ instruct ``FetchContent_MakeAvailable()`` to look for a ``CMakeLists.txt``
+ file in a subdirectory below the top level (i.e. the same way that
+ ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add` command).
+ ``SOURCE_SUBDIR`` must always be a relative path. See the next section
+ for an example of this option.
+
.. _`fetch-content-examples`:
@@ -445,6 +459,23 @@ frameworks are available to the main build:
# Catch2 will be defined and available to the rest of the build
FetchContent_MakeAvailable(googletest Catch2)
+If the sub-project's ``CMakeLists.txt`` file is not at the top level of its
+source tree, the ``SOURCE_SUBDIR`` option can be used to tell ``FetchContent``
+where to find it. The following example shows how to use that option and
+it also sets a variable which is meaningful to the subproject before pulling
+it into the main build:
+
+.. code-block:: cmake
+
+ include(FetchContent)
+ FetchContent_Declare(
+ protobuf
+ GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
+ GIT_TAG v3.12.0
+ SOURCE_SUBDIR cmake
+ )
+ set(protobuf_BUILD_TESTS OFF)
+ FetchContent_MakeAvailable(protobuf)
In more complex project hierarchies, the dependency relationships can be more
complicated. Consider a hierarchy where ``projA`` is the top level project and
@@ -1072,11 +1103,26 @@ macro(FetchContent_MakeAvailable)
# can be treated that way. Protecting the call with the check
# allows this function to be used for projects that just want
# to ensure the content exists, such as to provide content at
- # a known location.
- if(EXISTS ${${contentNameLower}_SOURCE_DIR}/CMakeLists.txt)
- add_subdirectory(${${contentNameLower}_SOURCE_DIR}
- ${${contentNameLower}_BINARY_DIR})
+ # a known location. We check the saved details for an optional
+ # SOURCE_SUBDIR which can be used in the same way as its meaning
+ # for ExternalProject. It won't matter if it was passed through
+ # to the ExternalProject sub-build, since it would have been
+ # ignored there.
+ set(__fc_srcdir "${${contentNameLower}_SOURCE_DIR}")
+ __FetchContent_getSavedDetails(${contentName} contentDetails)
+ if("${contentDetails}" STREQUAL "")
+ message(FATAL_ERROR "No details have been set for content: ${contentName}")
+ endif()
+ cmake_parse_arguments(__fc_arg "" "SOURCE_SUBDIR" "" ${contentDetails})
+ if(NOT "${__fc_arg_SOURCE_SUBDIR}" STREQUAL "")
+ string(APPEND __fc_srcdir "/${__fc_arg_SOURCE_SUBDIR}")
endif()
+
+ if(EXISTS ${__fc_srcdir}/CMakeLists.txt)
+ add_subdirectory(${__fc_srcdir} ${${contentNameLower}_BINARY_DIR})
+ endif()
+
+ unset(__fc_srcdir)
endif()
endforeach()