CMake cannot deduce the set of header files to be installed from the target. This makes sense, as the target may contain both private and public header files, but CMake does not differentiate between those. As a consequence, you have to list the header files explicitly in an INSTALL(FILES ...)
command:
install(FILES ${MY_HEADER_FILES} DESTINATION include)
Update for CMake 3.23 and later:
CMake version 3.23 introduced File Sets, which allow handling header files in a more elegant way. This way header files only need to be listed once in the CMakeLists.txt
to get both integrated in the IDE and also installed correctly:
cmake_minimum_required(VERSION 3.23)
# example library with sources and headers located at ${MY_LIB_SOURCE_DIR}
add_library(my_lib)
target_include_directories(my_lib PUBLIC ${MY_LIB_SOURCE_DIR})
# source files get added as before
target_sources(my_lib PUBLIC ${MY_LIB_SOURCE_DIR}/my_lib/my_lib.cpp)
# header files get added via FILE_SET
# BASE_DIR should point to the same directory that is used as the
# target_include_directory, otherwise the install paths may be off.
target_sources(my_lib PUBLIC FILE_SET HEADERS
BASE_DIRS ${MY_LIB_SOURCE_DIR}
FILES ${MY_LIB_SOURCE_DIR}/my_lib/my_lib.hpp)
# install command needs to reference the file set again
install(TARGETS my_lib FILE_SET HEADERS)
End of 3.23 update
The PUBLIC_HEADER
field that you stumbled upon is related to the OSX framework mechanism, which is its very own can of worms. I suggest you stay clear of it, unless you actually want to deploy your library as a .framework
on OSX.
Take special note of the INCLUDES DESTINATION
option to the INSTALL(TARGET ...)
command. While this does not actually copy any files itself, it allows the include directory to be added to the imported target provided by the config package script automatically. If you intend to provide a package config script to your users (which you probably should, at least if you expect your users to also use CMake), you probably want to set this option.
Since the install mechanism is quite complicated overall, I have a small github project of mine where you can observe all the elements in action.