[CMake] using `install()` with EXPORT and COMPONENT

Craig Scott craig.scott at crascit.com
Sun Sep 29 05:13:05 EDT 2019


On Sun, Sep 29, 2019 at 6:38 AM Stefan Seefeld <stefan at seefeld.name> wrote:

> Hello,
>
> I'm working on a library project that will be packaged in multiple
> components. A "runtime" component will contain the (shared) library, an a
> "dev" component the associated headers (and perhaps other development-only
> artefacts).
>
> I have successfully used the `install()` command to install these two sets
> of artefacts, i.e. calling `install(... COMPONENT runtime)`, as well as
> `install(... COMPONENT dev)`.
>
> However, I'm now looking into calling `install(TARGETS ... EXPORT ...)`.
> The documentation explains how the list of installed headerfiles can
> actually be inferred from the target itself (if the
> target_include_directories have been appropriately set). However, I can't
> call that function more than once on the same target, and thus I seem to
> have no way to split the installation into multiple components.
>
> Does anyone know what I'm missing ? What is the suggested way to package a
> project into the usual "runtime" and "dev" components ?
>

If all of your headers should be installed to a single directory, then you
can list the headers in the target's PUBLIC_HEADER or PRIVATE_HEADER target
property, then make sure you add those destinations in the install(TARGETS
...) command. For example:

include(GNUInstallDirs)
install(TARGETS myLib
    EXPORT SomeProj_Targets
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
            COMPONENT SomeProj_Runtime
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
            COMPONENT          SomeProj_Runtime
            NAMELINK_COMPONENT SomeProj_Development   # Requires CMake 3.12
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
            COMPONENT SomeProj_Development
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
            COMPONENT SomeProj_Development
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

If you need to install headers into more than one directory (i.e. your
headers have some sort of directory hierarchy), then the above doesn't work
because it flattens all of the headers into a single location. Instead, you
have to use install(FILES ...) to install the headers directly for such
cases. Also, the target_include_directories() command has nothing to do
with what header files get installed. Rather, it only controls the header
search paths attached to a target.

FYI, part of my CppCon talk "Deep CMake For Library Authors" from a couple
of weeks ago has a fair amount of overlap with this topic (specifically
install components and destinations). I'm waiting for the YouTube clip to
be made available and then I'll be posting a blog article on my website
with links and the slides. When it goes up, you'll be able to find it at
https://crascit.com (hopefully sometime this week, but depends how quickly
the production people get the video done).


-- 
Craig Scott
Melbourne, Australia
https://crascit.com

Get the hand-book for every CMake user: Professional CMake: A Practical
Guide <https://crascit.com/professional-cmake/>
Consulting services (CMake, C++, build/release processes):
https://crascit.com/services
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20190929/f18e4966/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .signature.png
Type: image/png
Size: 2754 bytes
Desc: not available
URL: <https://cmake.org/pipermail/cmake/attachments/20190929/f18e4966/attachment.png>


More information about the CMake mailing list