# Installing dependencies imported with FetchContent()

**URL:** https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550
**Category:** Usage
**Created:** [April 1, 2024, 11:51pm UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550 "2024-04-01T23:51:25Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Hilton\_Marques\_Santa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hilton_marques_santa/32/4447_2.png) [@Hilton\_Marques\_Santa](https://discourse.cmake.org/u/Hilton_Marques_Santa)
#### Post date: [April 1, 2024, 11:51pm UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/1 "2024-04-01T23:51:25Z")

</div>

Say that I that I have two private projects: A and B. The project B is imported to project A by the FetchContent command, say:

```auto
#project_B.cmake in project A
FetchContent_Declare(project_B
      GIT_REPOSITORY "git@project_B.git"
      GIT_TAG main
)

```

The project\_B was created with the good practices of consumable projects. Including the following guard for installation:

```auto
#CMakeLists.txt in project B
if (PROJECT_IS_TOPLEVEL)
  include(Install.cmake)
endif()

```

Where Install.cmake contains all the necessary configurations for project B installation.  
Now, I am intended to install project A, how should I proceed to install project\_B from project\_A?  
I mean, should I repeat all the configurations written in install.cmake in the subsequent part of the previous code?

```auto
#project_B.cmake in project A
FetchContent_Declare(project_B
      GIT_REPOSITORY "git@project_B.git"
      GIT_TAG main
)
...
#rewrite install.cmake from project B here?

```

---

<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: [April 2, 2024, 10:19pm UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/2 "2024-04-02T22:19:18Z")

</div>

If you have control over both A and B, I would define their install logic such that they always specify components for things they install, and those components should have project-specific names. Then a higher level parent project can pick and choose which components it deems relevant and only install those when it is creating a package. Take a look at the [`CPACK_COMPONENTS_ALL`](https://cmake.org/cmake/help/latest/module/CPackComponent.html#variable:CPACK_COMPONENTS_ALL) variable for how to specify which components to include in a package.

---

<div class="post-metadata">

### Author: ![Hilton\_Marques\_Santa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hilton_marques_santa/32/4447_2.png) [@Hilton\_Marques\_Santa](https://discourse.cmake.org/u/Hilton_Marques_Santa)
#### Post date: [April 3, 2024, 12:44am UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/3 "2024-04-03T00:44:33Z")

</div>

Thank you for your quick reply. Yes, I am in control of both projects. According to your instructions, should I proceed with the installation of B from A as follows?

```auto
#project_B.cmake in project A
FetchContent_Declare(project_B
      GIT_REPOSITORY "git@project_B.git"
      GIT_TAG main
)
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME project_B_lib)
install(TARGETS project_B EXPORT Project_BTargets)
install(DIRECTORY ${project_B_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
...

```

---

<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: [April 3, 2024, 6:50am UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/4 "2024-04-03T06:50:00Z")

</div>

I tend to look at it as each project should be responsible for `install()` commands for its own targets and files. Hopefully you can avoid having to write `install()` commands for your dependencies, but if you do, try to only add those if you know you’re the top level project. That makes composing more complex projects with many dependencies easier to manage at the top level consuming project.

---

<div class="post-metadata">

### Author: ![Hilton\_Marques\_Santa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hilton_marques_santa/32/4447_2.png) [@Hilton\_Marques\_Santa](https://discourse.cmake.org/u/Hilton_Marques_Santa)
#### Post date: [April 3, 2024, 8:19am UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/5 "2024-04-03T08:19:13Z")

</div>

> I tend to look at it as each project should be responsible for `install()` commands for its own targets and files.

I would like to do that too, but in the best practices of consumable projects say that we should put the following guard in the installation of project B.

```auto
#CMakeLists.txt in project B
if (PROJECT_IS_TOPLEVEL)
  include(Install.cmake)
endif()

```

So how can I call the install configurations in project B’s install.cmake from inside project A (where project B is no longer toplevel)?

---

<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: [April 4, 2024, 9:52pm UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/6 "2024-04-04T21:52:38Z")

</div>

> …but in the best practices of consumable projects say that we should put the following guard in the installation of project B…

I don’t know where you’re getting that advice, but I wouldn’t agree with it. I would generally recommend you always want to have the `install(...)` commands, just make sure they use project-specific component names. Then a parent consumer project can decide for itself which components it wants and which it will ignore.

The part that you _do_ want to only include if you’re the top level project is the packaging logic. By this I mean the things related specifically to CPack. That’s mostly setting `CPACK_...` variables and eventually including the `CPack` module.

---

<div class="post-metadata">

### Author: ![Hilton\_Marques\_Santa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hilton_marques_santa/32/4447_2.png) [@Hilton\_Marques\_Santa](https://discourse.cmake.org/u/Hilton_Marques_Santa)
#### Post date: [April 5, 2024, 1:51am UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/7 "2024-04-05T01:51:18Z")

</div>

I mean, some of my reference projects like [Lagrange](https://github.com/adobe/lagrange/blob/72f9a5447b6803245d43a37a18b76e59c16fbda8/CMakeLists.txt#L135C1-L136C28) and [GSL](https://github.com/microsoft/GSL/blob/main/CMakeLists.txt#L27) do this approach. I use them as a model, what do you think about this strategy in these projects?  
I realize that a simple solution to this situation is just defining the `<project-name>_INSTALL` as true before the `FetchContent_MakeAvailable()`.

```auto
FetchContent_Declare(GSL
	    GIT_REPOSITORY "https://github.com/microsoft/GSL"
	        GIT_TAG "v4.0.0"
		    GIT_SHALLOW ON
)
set(GSL_INSTALL YES)
FetchContent_MakeAvailable(GSL)

```

seems ok?

---

<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: [April 11, 2024, 4:23pm UTC](https://discourse.cmake.org/t/installing-dependencies-imported-with-fetchcontent/10550/8 "2024-04-11T16:23:06Z")

</div>

Making it conditional on a user variable makes more sense to me than a state (`PROJECT_IS_TOPLEVEL`). That’s mostly to say “I don’t need to install you” rather than “I’ll redo installation for you, don’t do anything yourself”.
