# Understanding the CMake \`COMPONENT\` keyword in the \`install\` command

**URL:** https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971
**Category:** Code
**Created:** [April 10, 2020, 2:38pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971 "2020-04-10T14:38:08Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![tomhh](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tomhh/32/493_2.png) [@tomhh](https://discourse.cmake.org/u/tomhh)
#### Post date: [April 10, 2020, 2:38pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/1 "2020-04-10T14:38:08Z")

</div>

Hello there,

I recently had a number of questions around the CMake `COMPONENT` keyword used in the CMake `install` command and using `COMPONENTS` in the CMake `find_package` command. After watching excellent talks by both Craig Scott and Deniz Bahadir I reached out to them directly via e-mail and got some very helpful responses. In case anyone else might find this useful I’m including the conversations here so it’s not just for my benefit.

> Tom question:
> 
> I am trying to understand what the `COMPONENT` keyword is in the CMake `install` command. I did a bunch of digging but can’t seem to find what it does. I wanted to use if for specifying components in the CMake `find_package` command, but I found it actually isn’t necessary at all and you can simply use careful naming of `-config.cmake` files.

> Craig Scott answer:
> 
> The COMPONENT keyword allows you to group installed things into separate “bags” that you can then use to refer to them later. These can be used to selectively pull in just a subset of available things into a package (e.g. with the “cmake --install --component ” command), or to create multiple packages based around those components. Some package generators also support a hierarchy of components through grouping, which is how you get things like optional install components in some GUI installers. Referring to the 5th edition of my book, Section 25.2 " _Installing Targets_ " explains what components are and gives an example of a typical usage (starting near the bottom of page 324). In the next chapter on packaging, Section 26.2 " _Components_ " covers how components in much more detail, covering how relationships between components can be expressed and how to use that for package generation.
> 
> For a more arm-chair coverage of this area, you might also want to watch my CppCon 2019 talk “Deep CMake For Library Authors”. The middle section talks a fair bit about install components and builds up an example with motivation for why you might put parts of a library in different components. My website has a link to that talk and accompanying slides here:
> 
> [CppCon 2019: Deep CMake For Library Authors - Crascit](https://crascit.com/2019/10/16/cppcon-2019-deep-cmake-for-library-authors/)

> Tom reply:
> 
> I think my confusion stemmed from the `COMPONENT` keyword in the `install` command and the `COMPONENTS` keyword in the `find_package` command. These appear to be entirely orthogonal concepts but I’d assumed they were tightly related.
> 
> The thing I was interested in doing was what Qt and Boost do by allowing users to list the components they want in their `find_package` command. There’s another interesting talk called ‘Oh No! More Modern CMake’ that recommends this but unfortunately doesn’t show exactly how to set it up.
> 
> In the example I linked in my first email I do now have things working and have locally experimented with the adding the `COMPONENT` keyword and using `cmake --install build --component <component>`. One hitch I found was you can only install one component at a time and the `Unspecified` component can’t be installed at the same time as a more specific one (a common component as it were). Maybe there’s a workaround for this I’m not sure, or you just have to run the command multiple times.

> Craig Scott reply:
> 
> Yes they are different things, but it would not be unusual for the package components to line up fairly closely to the install components. It would certainly make it easier to do so (for the person maintaining the project).
> 
> I used fairly poor wording in my initial reply (the result of various edits before sending the final version). The `cmake --install` command is meant only if you want to do a manual install of the project or individual components locally. You don’t need it for producing a package and shouldn’t try to do so. Define your package contents and install components within your project and let CPack take care of turning all that into a final package for you. Sorry if that wasn’t clear and it seems like I was suggesting that `cmake --install` should somehow be used within the project itself.
> 
> I rarely find a need to use `cmake --install`. I don’t recall if you can provide the --component option more than once or give it a list of components. You could try it and see.
> 
> Where possible, you should try to avoid having your project put things into the “Unspecified” component. That usually means you’ve got something being installed without any component specified. It often occurs when a third party dependency is brought into your build directly (e.g. with FetchContent) and that dependency doesn’t define install components. You can change the default component name just before you pull in that dependency though using the `CMAKE_INSTALL_DEFAULT_COMPONENT_NAME` variable (mentioned on page 325 of my book).

Deniz Bahadir’s response is harder to quote as he provided updated commands of an example `CMakeLists.txt` file I provided. I’ll include those as-is for now in case it’s useful.

> Tom question:
> 
> I am trying to understand how to add `COMPONENT`s to a CMake library so that I can list them in the `find_package` command of a consuming application and I can’t seem to find a clear idiomatic way of how to do this.
> 
> Suppose I have CMakeLists.txt file that looks like this:

```cmake
cmake_minimum_required(VERSION 3.15)
project(messages LANGUAGES CXX)

include(GNUInstallDirs)

add_library(hello)
target_sources(hello PRIVATE hello/hello.cpp)

target_include_directories(
    hello PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/hello/include/>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

install(
    TARGETS hello
    EXPORT ${PROJECT_NAME}-config
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

install(
    DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/hello/include/
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})

install(
    EXPORT ${PROJECT_NAME}-config
    NAMESPACE ${PROJECT_NAME}::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})

```

> It is a super simple project called `messages` with a single library called hello. I would like to make a COMPONENT called greetings so in my application, instead of just doing:

```cmake
find_package(messages REQUIRED CONFIG)
...
target_link_libraries(
    ${PROJECT_NAME} PRIVATE messages::hello)

```

> I can do this:

```cmake
find_package(messages REQUIRED CONFIG greetings)
...

target_link_libraries(
    ${PROJECT_NAME} PRIVATE messages::hello)

```

> But whenever I try and add any `COMPONENT` keyword to the `install` commands listed above, it seems to have no effect at all.
> 
> I’ve seen some examples where people have to manually create multiple `<project>-config` files but it seems to me there should be a simpler way.

> Deniz reply:

```cmake
...

install(
     # Install the target `hello`.
     TARGETS hello
     # Associate `hello` with export file `messages-config.cmake`.
     EXPORT ${PROJECT_NAME}-config
     # Only install `hello` if it is statically linked!
     ARCHIVE
     # Install it here:
     DESTINATION ${CMAKE_INSTALL_LIBDIR}
     # Associate `hello` with a component `greetings`.
     COMPONENT greetings
     # If we do not want to install `hello` when using the component-less
     # `find_package` call, we must uncomment the following line, too.
# EXCLUDE_FROM_ALL
)

install(
     # Install the (public) headers of `hello`.
     DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/hello/include/
     # Install them here:
     DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
     # Associate the (public) headers of `hello` with a component
`greetings`.
     COMPONENT greetings
     # If we do not want to install these headers when using the
component-less
     # `find_package` call, we must uncomment the following line, too.
     # EXCLUDE_FROM_ALL
)

# Install the export file:

install(
     # Generate and install the export file `messages-config.cmake`.
     EXPORT ${PROJECT_NAME}-config
     # Install it here:
     DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
     # Make sure all its targets will get the namespace `messages::`
prepended.
     NAMESPACE ${PROJECT_NAME}::
     # Optionally, we could add another component `conversation` which
depends
     # on all the other components from the export file and would install
all
     # of them.
     COMPONENT conversation
)

```

> Now, if you just want to install the `hello` target and its include  
> files you can do the following:

```cmake
find_package(messages REQUIRED COMPONENTS greetings CONFIG)
...
target_link_libraries(${PROJECT_NAME} PRIVATE messages::hello)

```

> If you want to install all components without explicitly mentioning all  
> of them, do the following:

```cmake
find_package(messages REQUIRED COMPONENTS conversation CONFIG)
...
target_link_libraries(${PROJECT_NAME} PRIVATE messages::hello)

```

> End

I have created an example application and library to demonstrate the effect I was after (ironically not yet actually using the `COMPONENT` keyword) - [cmake-examples/examples/more/components at main · pr0g/cmake-examples · GitHub](https://github.com/pr0g/cmake-examples/tree/master/examples/more/components).

I hope someone else found this exchange useful and a huge thank you to Craig and Deniz for taking the time to reply to me.

If anyone has anything more to add regarding this I’d be very grateful to hear! 🙂

Thanks!

Tom

---

<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, 2020, 11:21pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/2 "2020-04-11T23:21:25Z")

</div>

I haven’t had a chance to read it thoroughly myself yet, but I cleared the spam flag (probably added automatically due to length and/or link count).

Cc: @kyle.edwards @craig.scott

---

<div class="post-metadata">

### Author: ![dbahadir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dbahadir/32/197_2.png) [@dbahadir](https://discourse.cmake.org/u/dbahadir)
#### Post date: [April 13, 2020, 8:42pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/3 "2020-04-13T20:42:57Z")

</div>

I also got confused by the `COMPONENTS` and `COMPONENT` keywords and their relationship.

Forget the stuff I mentioned about `find_package`. As Craig wrote correctly the `COMPONENT` keyword in the `install` command only effects installing the specific components / targets but has no implicit effect on `find_package` or how it uses components.

The `COMPONENTS` keyword of `find_package` is just some kind of hint for the underlying export file and it is up to that file to decide what to do if a component is given to the `find_package` command for the specific library.

---

<div class="post-metadata">

### Author: ![tomhh](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tomhh/32/493_2.png) [@tomhh](https://discourse.cmake.org/u/tomhh)
#### Post date: [April 15, 2020, 7:57pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/4 "2020-04-15T19:57:02Z")

</div>

Thank you for following up @dbahadir. It does seem like something others might trip up on so hopefully this will be of use to other readers.

The example I’ve included above (and this Stack Overflow question [https://stackoverflow.com/q/54702582/1947066](https://stackoverflow.com/q/54702582/1947066) + repo ([https://github.com/markeastwood82/nomnoms](https://github.com/markeastwood82/nomnoms)) are useful references too.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 8, 2021, 11:16am UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/5 "2021-03-08T11:16:13Z")

</div>

@tomhh I am wondering about the variants to create component libraries.

see [GitHub - ClausKlein/cmake-example-component-lib: How to create a component library like boost](https://github.com/ClausKlein/cmake-example-component-lib)

I am still not sure what is the right way?

> <https://github.com/markeastwood82/nomnoms/pull/2>

---

<div class="post-metadata">

### Author: ![tomhh](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tomhh/32/493_2.png) [@tomhh](https://discourse.cmake.org/u/tomhh)
#### Post date: [March 8, 2021, 11:32am UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/6 "2021-03-08T11:32:57Z")

</div>

Hi @ClausKlein,

I don’t have time to look into it right now sorry but this example might prove useful to puzzle out how to get things working - [cmake-examples/examples/more/components at main · pr0g/cmake-examples · GitHub](https://github.com/pr0g/cmake-examples/tree/main/examples/more/components)

Let me know if that’s any help and I’ll try have a look at the link you shared this evening,

Cheers!

Tom

---

<div class="post-metadata">

### Author: ![tomhh](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tomhh/32/493_2.png) [@tomhh](https://discourse.cmake.org/u/tomhh)
#### Post date: [March 8, 2021, 10:05pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/7 "2021-03-08T22:05:54Z")

</div>

Hi @ClausKlein,

Was that any help at all? I have a [PR](https://github.com/markeastwood82/nomnoms/pull/1) open with nomnoms too but it doesn’t seem like that repo is maintained at all. It seems like your PR has conflicting changes, might be worth looking at my [fork](https://github.com/pr0g/nomnoms) too.

Cheers,

Tom

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 9, 2021, 9:04am UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/8 "2021-03-09T09:04:29Z")

</div>

Thanks, it works now. (And is much simpler and clear)

see [nomnoms/CMakeLists.txt at develop · ClausKlein/nomnoms · GitHub](https://github.com/ClausKlein/nomnoms/blob/develop/noms/CMakeLists.txt)

I am sorry to say, but your version is still not complete:

```bash
CMake Error at CMakeLists.txt:5 (find_package):
  Could not find a configuration file for package "noms" that is compatible
  with requested version "1".

  The following configuration files were considered but not accepted:

    /Users/clausklein/Workspace/cpp/nomnoms/noms/stage/lib/cmake/noms/noms-config.cmake, version: unknown

-- Configuring incomplete, errors occurred!

```

```diff
Claus-iMac:noms clausklein$ git diff
diff --git a/munch/CMakeLists.txt b/munch/CMakeLists.txt
index 5c4a23b..e7e28b4 100644
--- a/munch/CMakeLists.txt
+++ b/munch/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
 
 project(munch)
 
-find_package(noms REQUIRED CONFIG COMPONENTS veg fruit)
+find_package(noms 1 REQUIRED CONFIG COMPONENTS veg fruit)
 
 add_executable(${PROJECT_NAME})
 target_sources(${PROJECT_NAME} PRIVATE src/main.cpp)

```

```auto
Claus-iMac:noms clausklein$ tree stage/
stage/
├── include
│ └── noms
│ ├── fruit
│ │ └── apple.h
│ └── veg
│ └── asparagus.h
└── lib
    ├── cmake
    │ └── noms
    │ ├── noms-config.cmake
    │ ├── noms-fruit-config-debug.cmake
    │ ├── noms-fruit-config.cmake
    │ ├── noms-veg-config-debug.cmake
    │ └── noms-veg-config.cmake
    ├── libfruit.a
    └── libveg.a

7 directories, 9 files
Claus-iMac:noms clausklein$ 

```

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 9, 2021, 9:24am UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/9 "2021-03-09T09:24:58Z")

</div>

IMHO the installation should be like this:

```auto
Claus-iMac:noms clausklein$ tree stage/
stage/
├── include
│ └── noms
│ ├── fruit
│ │ └── apple.h
│ └── veg
│ └── asparagus.h
└── lib
    ├── cmake
    │ └── noms
    │ ├── noms-config-version.cmake
    │ ├── noms-config.cmake
    │ ├── noms-fruit-targets-debug.cmake
    │ ├── noms-fruit-targets.cmake
    │ ├── noms-targets-debug.cmake
    │ ├── noms-targets.cmake
    │ ├── noms-veg-targets-debug.cmake
    │ └── noms-veg-targets.cmake
    └── libfruit.a

7 directories, 11 files
Claus-iMac:noms clausklein$ 

```

---

<div class="post-metadata">

### Author: ![tomhh](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tomhh/32/493_2.png) [@tomhh](https://discourse.cmake.org/u/tomhh)
#### Post date: [March 10, 2021, 8:40pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/10 "2021-03-10T20:40:22Z")

</div>

Hi @ClausKlein,

Ah okay, I don’t think I’d included versioning. You may well be right that what you’ve suggested is better (though I guess with so many things there are multiple ways of doing it, some no doubt better than others! 😛)

One thing I don’t understand from your last folder structure is `libveg.a` seems to be missing? Is that just because you hadn’t built it that time?

Thanks,

Tom

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 10, 2021, 9:13pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/11 "2021-03-10T21:13:37Z")

</div>

I changed `libveg` to an `header only library`

---

<div class="post-metadata">

### Author: ![tomhh](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tomhh/32/493_2.png) [@tomhh](https://discourse.cmake.org/u/tomhh)
#### Post date: [March 10, 2021, 9:46pm UTC](https://discourse.cmake.org/t/understanding-the-cmake-component-keyword-in-the-install-command/971/12 "2021-03-10T21:46:51Z")

</div>

Ah okay got you 👍
