Private headers are installed without PRIVATE_HEADER install rule if ARCHIVE has no DESTINATION
On CMake 3.21.3 on Windows 10 (21H1 Build 19043.1288), if a STATIC library target has the PUBLIC_HEADER and PRIVATE_HEADER properties set and has an install rule that has an ARCHIVE Output Artifact with no DESTINATION specified (expected to fallback to the default value) and only a PUBLIC_HEADER Output Artifact, then both public and private headers will be installed. For example:
include(GNUInstallDirs)
set(foo_SOURCES libfoo/foo.c)
set(foo_PUBLIC_HEADERS include/foo/foo_public_header.h)
set(foo_PRIVATE_HEADERS libfoo/foo_private_header.h)
add_library(foo STATIC)
target_sources(foo PRIVATE "${foo_SOURCES}" "${foo_PUBLIC_HEADERS}"
"${foo_PRIVATE_HEADERS}")
set_target_properties(foo PROPERTIES PUBLIC_HEADER "${foo_PUBLIC_HEADERS}")
set_target_properties(foo PROPERTIES PRIVATE_HEADER "${foo_PRIVATE_HEADERS}")
target_include_directories(
foo BEFORE
PRIVATE "libfoo"
PUBLIC "include")
Adding this install rule will install the .lib file and both public and private headers, despite not specifying a PRIVATE_HEADER Output Artifact at all:
install(
TARGETS foo
ARCHIVE
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/foo")
Whereas this install rule will only install the .lib and the public headers, which is what I expected the above install rule to do:
install(
TARGETS foo
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/foo")
See attached test case: foo-source-dir.zip
Edited by Ryan Foster