# INTERFACE library not getting installed and no error reported

**URL:** <https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185>\
**Category:** Usage\
**Tags:** os:linux\
**Created:** [November 17, 2020, 2:46am UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185 "2020-11-17T02:46:04Z")\
**Posts on this page:** 14\
**Page:** 2

<div class="post-metadata">

**Author:** ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)\
**Post date:** [December 3, 2020, 3:08pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/21 "2020-12-03T15:08:56Z")

</div>

> [@craig.scott](#):
>
> if it makes sense for interface libraries to now honour the `PUBLIC_HEADERS` and `PRIVATE_HEADERS` target properties and install destinations?

That has been supported since CMake 3.15. It was added by [CMake MR 3181](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/3181).

The first-class INTERFACE library support in CMake 3.19 was added by [CMake MR 5078](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5078), and includes a test for `PUBLIC_HEADER` installation [here](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.19.1/Tests/ExportImport/Export/Interface/CMakeLists.txt#L17-22) and [here](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.19.1/Tests/ExportImport/Export/Interface/CMakeLists.txt#L74).

---

<div class="post-metadata">

**Author:** ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)\
**Post date:** [December 3, 2020, 5:15pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/22 "2020-12-03T17:15:52Z")

</div>

So [this example](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.19.1/Tests/ExportImport/Export/Interface/CMakeLists.txt#L17-22) demonstrates that cmake supports INTERFACE library installation in the same way as STATIC or SHARED library installation of its headers via install(TARGETS headergen…) without use of install(FILES…) is supported. However there is only one header file in headergen (and it is generated by cmake so it knows all its properties). So could you please advise on the following:

- Should cmake support INTERFACE library install via install(TARGETS … PUBLIC\_HEADER DESTINATION installIncludeDir) without direct FILES/DIRECTORIES install for libraries that have their header files under a) a Directory with sub-directories or b) a list of directories or c) a list of files. It seems documentation does not preclude such possibilities by using plurals “these headers” or “header files”. I assume in case of a) this would result in installation of library inlcude directory under installIncludeDir.

- Could PUBLIC\_HEADER be set to include all INTERFACE library files (cases above) not by explicit `set_property(TARGET headergen PROPERTY PUBLIC_HEADER..publicHdrDir)` or set\_target\_property listing all INTERFACE library files, but via other target properties since cmake gets all INTERFACE library files passed within the add\_library or via INTERFACE\_INCLUDE\_DIRECTORIES and settings of `"$<BUILD_INTERFACE:...." and "$<INSTALL_INTERFACE: ..."` ?

- Does @brad.king example require 3.19 as minimum or 3.17 would support the above functionality? Why is the condition “if they have sources”? Which Sources? I assume interface library is a collection of source code /header files under 1 directory in simple case.

- In [@brad.king example](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.19.1/Tests/ExportImport/Export/Interface/CMakeLists.txt#L17-22), why the headeronly INTERFACE library headeronly\_headers installed directly via FILES but not via TARGETS? `install(TARGETS headeronly…) ?

---

<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 3, 2020, 11:45pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/23 "2020-12-03T23:45:21Z")

</div>

> [@brad.king](#):
>
> That has been supported since CMake 3.15. It was added by [CMake MR 3181](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/3181).
> 
> The first-class INTERFACE library support in CMake 3.19 was added by [CMake MR 5078](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5078), and includes a test for `PUBLIC_HEADER` installation [here](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.19.1/Tests/ExportImport/Export/Interface/CMakeLists.txt#L17-22) and [here](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.19.1/Tests/ExportImport/Export/Interface/CMakeLists.txt#L74).

Thanks, I’d forgotten about those MRs adding support for this for interface libs.

> [@yisseamake](#):
>
> Should cmake support INTERFACE library install via install(TARGETS … PUBLIC\_HEADER DESTINATION installIncludeDir) without direct FILES/DIRECTORIES install for libraries that have their header files under a) a Directory with sub-directories or b) a list of directories or c) a list of files. It seems documentation does not preclude such possibilities by using plurals “these headers” or “header files”. I assume in case of a) this would result in installation of library inlcude directory under installIncludeDir.

Yes, although I might be misinterpreting what you mean in (a) and (b). The PUBLIC\_HEADER target property accepts a list of _files_, you cannot put directory names in there (if it does work, that’s by chance and isn’t meant to be supported). All of the files, regardless of their source directory structure, will be installed into a single directory which you specify in the `install(TARGETS)` command.

> [@yisseamake](#):
>
> Could PUBLIC\_HEADER be set to include all INTERFACE library files (cases above) not by explicit `set_property(TARGET headergen PROPERTY PUBLIC_HEADER..publicHdrDir)` or set\_target\_property listing all INTERFACE library files, but via other target properties since cmake gets all INTERFACE library files passed within the add\_library or via INTERFACE\_INCLUDE\_DIRECTORIES and settings of `"$<BUILD_INTERFACE:...." and "$<INSTALL_INTERFACE: ..."` ?

No, CMake has no way to know whether the source files added to the interface library via `add_library()` or `target_sources()` should go in `PUBLIC_HEADER` or `PRIVATE_HEADER`. A potential enhancement might be to have `PUBLIC_HEADER` and `PRIVATE_HEADER` support generator expressions. That would then allow you to at least do something like the following if it made sense for your particular project:

```cmake
set_target_properties(SomeTarget PROPERTIES
    # Not currently supported, this property doesn't yet support generator expressions.
    PUBLIC_HEADER "$<TARGET_PROPERTY:SOURCES>"
)

```

> [@yisseamake](#):
>
> Does @brad.king example require 3.19 as minimum or 3.17 would support the above functionality? Why is the condition “if they have sources”? Which Sources? I assume interface library is a collection of source code /header files under 1 directory in simple case.

CMake 3.15 provides the minimum capabilities you need for using `PUBLIC_HEADER` and `PRIVATE_HEADER` to install headers when installing an interface library using `install(TARGETS)`. The other CMake 3.19 links Brad provided relate to adding files as sources to an interface target and that target then showing up as a target in the build system. Your use case doesn’t seem to need that.

As for “Why the condition “if they have sources”? Which Sources?”, this refers to whether any sources have been added to the interface library via `add_library()` or `target_sources()`. If every interface library was added as a build system target regardless of whether it had any such sources or not, there may be lots of targets showing up in IDEs, etc. that the user really isn’t interested in. But if an interface library has sources attached to it, then there may be some build rules associated with it (to generate the sources) and that means it is a genuine target that will build something. Or the sources might just be attached to make them show up in an IDE and again, that means you want it to show as a build system target so the sources have a target to sit under.

---

<div class="post-metadata">

**Author:** ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)\
**Post date:** [December 7, 2020, 11:51pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/24 "2020-12-07T23:51:49Z")

</div>

> [@craig.scott](#):
>
> No, CMake has no way to know whether the source files added to the interface library via `add_library()` or `target_sources()` should go in `PUBLIC_HEADER` or `PRIVATE_HEADER`.

Why cant cmake use INTERFACE\_INCLUDE\_DIRECTORIES property which give list of of dirs set by target\_include\_directories and other commands?

---

<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 8, 2020, 2:52am UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/25 "2020-12-08T02:52:23Z")

</div>

How would that help determine whether `public.h` should be installed and `private.h` should not?

---

<div class="post-metadata">

**Author:** ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)\
**Post date:** [December 9, 2020, 8:19pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/26 "2020-12-09T20:19:29Z")

</div>

- By using PRIVATE\_HEADER to override the default. So it would install the whole directory excluding list of files specified in PRIVATE\_HEADER.

---

<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 9, 2020, 10:33pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/27 "2020-12-09T22:33:01Z")

</div>

Well, files maching header extensions (there are “only” a dozen in use these days) at least 🙂 . Currently it seems that `PRIVATE_HEADER` only applies to `FRAMEWORK` targets. Expanding its semantics would require a code change (and my gut says a policy as well).

---

<div class="post-metadata">

**Author:** ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)\
**Post date:** [December 9, 2020, 11:06pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/28 "2020-12-09T23:06:10Z")

</div>

> [@ben.boeckel](#):
>
> `PRIVATE_HEADER`

but [cmake man page](https://cmake.org/cmake/help/latest/prop_tgt/PRIVATE_HEADER.html) reads “On non-Apple platforms these headers may be installed using the `PRIVATE_HEADER` option to the [`install(TARGETS)`](https://cmake.org/cmake/help/latest/command/install.html#command:install) command.”  
Also recall that only INTERFACE library are having issue with not being installed, so which mechanism is used for installing export SHARED or STATIC libs? What sis preventing from using it as cmake creates all build files for the build with INTERFACE library?

---

<div class="post-metadata">

**Author:** ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)\
**Post date:** [February 24, 2021, 5:15pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/29 "2021-02-24T17:15:49Z")

</div>

Any updates @ben.boeckel

---

<div class="post-metadata">

**Author:** ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)\
**Post date:** [March 31, 2022, 9:48am UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/30 "2022-03-31T09:48:09Z")

</div>

I can agree that `INTERFACE` libraries not installing their `INTERFACE_INCLUDE_DIRECTORIES` automagically is very confusing. Even more so for a chain of interface libraries depending on one another, some of which can be imported. Not only I need to manually copy destination directory, I also need to find all dependencies and copy their headers too. When dependencies are conditional it makes it even harder.

---

<div class="post-metadata">

**Author:** ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)\
**Post date:** [March 31, 2022, 10:03am UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/31 "2022-03-31T10:03:09Z")

</div>

@ben.boeckel , reading about FILE\_SET it feels like it is something which can help here, but I do not yet understand how 🙂

---

<div class="post-metadata">

**Author:** ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)\
**Post date:** [March 31, 2022, 4:22pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/32 "2022-03-31T16:22:17Z")

</div>

@yisseamake , I have tested new FILE\_SET feature and it seems to be doing exactly what you wanted. It both populates INTERFACE\_INCLUDE\_DIRECTORIES with BUILD\_INTERFACE-like value and installs them on `install(TARGETS ... )`

---

<div class="post-metadata">

**Author:** ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)\
**Post date:** [March 31, 2022, 10:00pm UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/33 "2022-03-31T22:00:53Z")

</div>

Great. Thank you Maxim @redbaron, which version will it be available ? I am still on 3.17 and upgrade validation of our projects with newer version goes painfully slow

---

<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, 2022, 12:28am UTC](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185/34 "2022-04-02T00:28:59Z")

</div>

[File sets](https://cmake.org/cmake/help/latest/command/target_sources.html#file-sets) are a new feature added in CMake 3.23.0

[Previous page](https://discourse.cmake.org/t/interface-library-not-getting-installed-and-no-error-reported/2185.md?page=1)
