# Pull in CMake Files via FetchContent

**URL:** https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315
**Category:** Code
**Created:** [December 8, 2020, 11:12am UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315 "2020-12-08T11:12:04Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![Leon0402](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/l/ccd318/32.png) [@Leon0402](https://discourse.cmake.org/u/Leon0402)
#### Post date: [December 8, 2020, 11:12am UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315/1 "2020-12-08T11:12:04Z")

</div>

Hi,

I wanted to use cmake scripts provided by Catch2 and used the following code:

```auto
FetchContent_GetProperties(Catch2)
if(NOT catch2_POPULATED)
    FetchContent_Populate(Catch2)
    add_subdirectory(${catch2_SOURCE_DIR} ${catch2_BINARY_DIR})
    list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/contrib/)
endif()

```

In general this works, but there is the problem that CMAKE\_MODULE\_PATH is not set globally. But I put the code into it’s own directory dependencies/catch2 to create a seperate scope (Where I could override Variables controlling the fetched project), therefore CMAKE\_MODULE\_PATH is empty in my test folder, where I need it.  
Is there any way to fix this?

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [December 8, 2020, 11:26am UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315/2 "2020-12-08T11:26:16Z")

</div>

Your best bet is to set a `CACHE` variable with the location of the fetched module, and write your other `CMakeLists.txt` files to expect that variable. e.g.

In `dependencies/catch2/CMakeLists.txt`:

```cmake
# instead of list(APPEND CMAKE_MODULE_PATH...)
set(CATCH2_MODULE_PATH ${catch2_SOURCE_DIR}/contrib/
  CACHE INTERNAL
  "Path to downloaded Catch2 modules"
  FORCE)

```

In your `test` directory:

```cmake
list(APPEND CMAKE_MODULE_PATH ${CATCH2_MODULE_PATH})

```

~~You can also `mark_as_advanced(CATCH2_MODULE_PATH)` if you don’t want it showing up by default in e.g. CMake GUI configuration tools. (Probably wise, since you’re going to ignore and forcibly override whatever variable the user might set in there.)~~ Even better, I changed it to type `INTERNAL` so it will never show up in a GUI.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [December 9, 2020, 8:54pm UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315/3 "2020-12-09T20:54:22Z")

</div>

Another variant would be to use `FetchContent_MakeAvailable()` (it’s shorter and makes this suggestion simpler) and call it in both places (`dependencies` and `tests`). The call in `dependencies` will do the actual download. The call in `tests` will do nothing because the download has already been done, but it will still set the output variables that give the locations of the source dir (and others). Then you use the source dir location to populate the `CMAKE_MODULE_PATH` variable just like you were before, but now you’re doing it in the directory scope where you actually want/need it. It’s pretty short and clear:

```cmake
# In the tests directory
FetchContent_MakeAvailable(catch2)
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/contrib)

```

---

<div class="post-metadata">

### Author: ![Leon0402](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/l/ccd318/32.png) [@Leon0402](https://discourse.cmake.org/u/Leon0402)
#### Post date: [December 10, 2020, 9:16am UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315/4 "2020-12-10T09:16:01Z")

</div>

@ferdnyc Thanks for the suggestion! That’s a good idea

@craig.scott Nice 🙂 I didn’t know that this FetchContent\_MakeAvailable does populate the options as well. Maybe add that note to your book for the next version? (Or did I not see it in there?). I was already disappointed that I couldn’t use MakeAvailable.

I think though, it would still be great to have a global version of CMAKE\_MODULE\_PATH? Just like targets are globally available it seems logical to me to make the script globally available as well. Obviously there might be reasons where you want local scope. What would you think of a new feature to allow both? (Perhaps just a second variable, or a general mechanism to have parts of a list that are global and others that are local?)

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [December 11, 2020, 12:50pm UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315/5 "2020-12-11T12:50:44Z")

</div>

> [@craig.scott](#):
>
> Another variant would be to use `FetchContent_MakeAvailable()` (it’s shorter and makes this suggestion simpler) and call it in both places (`dependencies` and `tests`). The call in `dependencies` will do the actual download. The call in `tests` will do nothing because the download has already been done, but it will still set the output variables that give the locations of the source dir (and others).

Oh, neat — so, like `find_package()` output variables, the module’s results are cached and re-used in subsequent calls/runs? (I assume that would mean it also avoids the download on a subsequent `cmake` run in an existing build dir, since the files are already present?)

Hey, turns out Modern CMake [has a section on `FetchContent`](https://cliutils.gitlab.io/modern-cmake/chapters/projects/fetch.html), including macros to work around the lack of `FetchContent_MakeAvailable` in CMake 3.11-3.13. …Which I now see are also in the module documentation as well.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [December 12, 2020, 9:24pm UTC](https://discourse.cmake.org/t/pull-in-cmake-files-via-fetchcontent/2315/6 "2020-12-12T21:24:00Z")

</div>

> [@ferdnyc](#):
>
> Oh, neat — so, like `find_package()` output variables, the module’s results are cached and re-used in subsequent calls/runs? (I assume that would mean it also avoids the download on a subsequent `cmake` run in an existing build dir, since the files are already present?)

Not cached, but essentially the behavior looks similar. The first declared details for a dependency fully determine everything, so the relevant variables are computed from that. `FetchContent_MakeAvailable()` makes a call to `FetchContent_GetProperties()` internally which populates them. Actually, you could just call that in the `tests` directory instead of `FetchContent_MakeAvailable()`, now that I think about it. This has the advantage that `FetchContent_GetProperties()` is available from CMake 3.11, whereas `FetchContent_MakeAvailable()` is only available from 3.14.

And yes, once a download has been performed by FetchContent, subsequent runs should re-use that rather than re-download it again. Note that there might still be an update step performed though, depending on what sort of `GIT_TAG` you use (or whatever other download method you use).
