# A dependency uses FetchContent in a tricky way, and I can't figure out how to add CMake install code to this dependency

**URL:** <https://discourse.cmake.org/t/a-dependency-uses-fetchcontent-in-a-tricky-way-and-i-cant-figure-out-how-to-add-cmake-install-code-to-this-dependency/9541>\
**Category:** Code\
**Tags:** os:windows\
**Created:** [December 2, 2023, 3:25am UTC](https://discourse.cmake.org/t/a-dependency-uses-fetchcontent-in-a-tricky-way-and-i-cant-figure-out-how-to-add-cmake-install-code-to-this-dependency/9541 "2023-12-02T03:25:22Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dennis\_Ferron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dennis_ferron/32/2953_2.png) [@Dennis\_Ferron](https://discourse.cmake.org/u/Dennis_Ferron)\
**Post date:** [December 2, 2023, 3:25am UTC](https://discourse.cmake.org/t/a-dependency-uses-fetchcontent-in-a-tricky-way-and-i-cant-figure-out-how-to-add-cmake-install-code-to-this-dependency/9541/1 "2023-12-02T03:25:22Z")

</div>

The project, WebGPU-Distribution ([GitHub - eliemichel/WebGPU-distribution: Distributions of WebGPU for native and web development, easy to integrate and interchangeable.](https://github.com/eliemichel/WebGPU-distribution)), is designed to be used in your project via add\_subdirectory. The “main” branch conditionally selects a more specific branch _of the same repository_ to download via FetchContent, based on whether the build is Emscripten or not and whether you want wgpu or Dawn implementation on native. That fetched content in turn may download a pre-compiled wgpu distribution. (I am using wgpu for native and Emscripten for web.)

The batteries-included / one-touch method the project author designed works well for the tutorial of which that project is a component, however I organize my development environment differently. To avoid duplication of large game engine dependency libraries and to enforce a uniform standard, I install all of the dependencies of my projects to a common prefix directory, and use find\_package to get them. Whenever a 3rd party library does not support this, I fork it and add that install code myself.

I think I understand the basic steps of adding CMake install code, and this has worked for me for several dependencies so far. In my own words:

1. Change `target_include_directories` to use generator expressions.

2. List the header files in a variable and pass that to `install(FILES ...)`.

3. Add `install(TARGETS ...)` for each target with exports and install destination.

4. Generate config files and pass that to `install(FILES ...)`.

5. Use `install(EXPORT ...)` to install exports created during step three.

However when I got to WebGPU-Distribution, I couldn’t figure out how to adapt these steps to the way that project works. (I invite you to simply read the cmake file I’m talking about that I couldn’t figure out how to add install code to; it’s not very long: [https://github.com/eliemichel/WebGPU-distribution/blob/main/webgpu.cmake](https://github.com/eliemichel/WebGPU-distribution/blob/main/webgpu.cmake)).

Should I write code in the main branch of (my fork of) the WebGPU-Distribution project that reaches into ${CMAKE\_CURRENT\_BINARY\_DIR} to hoist the downloaded wgpu DLLs with install(FILES …) into my common install directory? Should I add install code to each non-main branch (but then how do I kick off the install from main?) Should I convert the project from using FetchContent to use ExternalProject instead? Should I “git clone” each branch as a separate top-level folder (in my projects folder) and manually install each for just the one target configuration each applies to?

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [December 27, 2023, 1:38am UTC](https://discourse.cmake.org/t/a-dependency-uses-fetchcontent-in-a-tricky-way-and-i-cant-figure-out-how-to-add-cmake-install-code-to-this-dependency/9541/2 "2023-12-27T01:38:22Z")

</div>

You might want to take some inspiration from Qt here. Have an “umbrella” project where you find the components via `COMPONENTS` arguments. So you might say:

```cmake
find_package(WebGPU-Distribution COMPONENTS Dawn)
# or
find_package(WebGPU-Distribution COMPONENTS wgpu)

```

This project internally does a `find_package` for the “real” thing and provides convenience targets (or the individual projects do this). Then each “variant” of WebGPU-Distribution can use its own package name and avoid collisions. You can also do the `find_package(WebGPU-Distribution-wgpu)` (or whatever) directly.

However, I would look to getting upstream to support this so that you don’t conflict if some other pattern arises.

---

<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 27, 2023, 2:20am UTC](https://discourse.cmake.org/t/a-dependency-uses-fetchcontent-in-a-tricky-way-and-i-cant-figure-out-how-to-add-cmake-install-code-to-this-dependency/9541/3 "2023-12-27T02:20:37Z")

</div>

> [@Dennis\_Ferron](#):
>
> The “main” branch conditionally selects a more specific branch _of the same repository_ to download via FetchContent,

Yeah, the craziness of storing completely different code on each branch of the same repo… well, I didn’t like it when GitHub decided that’s how `gh-pages` would be implemented, and I don’t much like it here. But that’s really just a distraction. Your downstream project could just as easily choose a specific branch and include _that_ `FetchContent()` command instead.

(Of course, there are no guarantees the branches’ contents won’t change at any moment, or even get deleted and replaced with a completely different set of branches that have different names. Which is why branches are the worst choice for organizing something like this, vs. non-ephemeral tags or releases.)

But regardless, the issue you’re facing is that no matter what path you go down, none of those _secondary_ branches actually compiles anything for itself, either.

- The `wgpu-static` branch includes pre-built static library binaries, which it exposes as an `IMPORTED` target.
- The `wgpu` branch includes pre-built _shared_ libraries – again, as `IMPORTED` targets.
- The `dawn` branch does a **SECOND** `FetchContent` of its own, in order to download and build the dawn sources from Google. They’re compiled, and then published by the outer wrapper as an `INTERFACE` target.

And the thing is, you **can’t** `install()` `IMPORTED` or `INTERFACE` targets, and you can’t `install(EXPORT ...)` their configuration.

I’m not sure there’s a path to making that setup properly installable as its own package. It’s really designed solely as a convenience for sucking pre-built components into self-contained projects.

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [December 27, 2023, 3:29am UTC](https://discourse.cmake.org/t/a-dependency-uses-fetchcontent-in-a-tricky-way-and-i-cant-figure-out-how-to-add-cmake-install-code-to-this-dependency/9541/4 "2023-12-27T03:29:40Z")

</div>

> [@ferdnyc](#):
>
> And the thing is, you **can’t** `install()` `IMPORTED` or `INTERFACE` targets

You can install `INTERFACE` targets (cf. header-only libraries). But yes, `IMPORTED` targets aren’t going to work.
