CMake FILE_SET for HEADER when using DESTINATION

Hello,

I’m trying to migrate a multi-target library from CMake3.14 to CMake v3.23.1 to take advantage of the new FILE_SET feature. I’ve purchased a copy of the 14th edition of Professional CMake and followed along the new updates for file sets. This will replace my use of installing the entire include directory and using file matching, making it so I can build and install header files for each target respectively rather than all headers.

Directory structure:

include
----myProj
--------a.hpp
--------b.hpp
src
----a.cpp
----b.cpp

I have cmakelists in each of the folders, with targets A and B. Some parts removed for brevity.

include/myProj/CMakeLists.txt

target_sources(A
PUBLIC FILE_SET HEADERS
FILES
a.hpp
)
target_sources(B
PUBLIC FILE_SET HEADERS
FILES
b.hpp
)

CMakeLists.txt

add_library(A)
add_library(B)

add_subdirectory(include/myProj)
include(GNUInstallDirs)
install(TARGETS A B
EXPORT ${PROJECT_NAME}-export
DESTINATION ${CMAKE_INSTALL_LIBDIR}
FILE_SET HEADERS
)

When installing the build directory, I expect the headers to be in install/include/a.hpp, however I see install/lib/a.hpp instead (The install prefix is “install”)

cmake --install build --prefix install

As per the book, “Since no DESTINATION was specified after FILE_SET, the default destination provided by CMAKE_INSTALL_INCLUDEDIR for HEADERS file sets will be used.”, which is said to be include, not lib.

I also tried supplying the INCLUDES DESTINATION X/Y/Z which has zero effect on the output structure. It seems that by supplying the generic DESTINATION keyword, that overrides the headers.

Am I missing something?

After reading additional documentation, and realizing that the DESTINATION keyword above was applying in ways I had not considered, here is the corrected install command. The below command is a combination of the examples for install in CMake documentation as well as the example in Professional CMake.

install(TARGETS A B
EXPORT ${PROJECT_NAME}-export
FILE_SET HEADERS
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

The only thing left is changing it so if I only build “A”, that it will install “A”, and not fail that B is not built.