INTERFACE library not getting installed and no error reported

That has been supported since CMake 3.15. It was added by CMake MR 3181.

The first-class INTERFACE library support in CMake 3.19 was added by CMake MR 5078, and includes a test for PUBLIC_HEADER installation here and here.

So this example 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, why the headeronly INTERFACE library headeronly_headers installed directly via FILES but not via TARGETS? `install(TARGETS headeronly…) ?

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

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.

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:

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

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.

Why cant cmake use INTERFACE_INCLUDE_DIRECTORIES property which give list of of dirs set by target_include_directories and other commands?

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

  • By using PRIVATE_HEADER to override the default. So it would install the whole directory excluding list of files specified in PRIVATE_HEADER.

Well, files maching header extensions (there are “only” a dozen in use these days) at least :slight_smile: . 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).

but cmake man page reads “On non-Apple platforms these headers may be installed using the PRIVATE_HEADER option to the install(TARGETS) 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?

Any updates @ben.boeckel