CMakeLists.txt: Preserve header directory structure when installing library target.

This commit adds FILE_SET features to target_sources and install(TARGETS)
in order to associate a set of headers and their containing include
directory with a target.

Installing the target installs the headers in the same layout,
and provides the include directory to consumers.

Signed-off-by: Elvis Dowson <elvis.dowson@gmail.com>
This commit is contained in:
Elvis Dowson 2026-02-21 23:00:24 +04:00
parent b0af6d5cd2
commit b59550f67e

View File

@ -8,20 +8,24 @@ set(CMAKE_CXX_STANDARD 20)
set(LIBRARY_TARGET_NAME ${PROJECT_NAME})
# define source and install directories
set(${LIBRARY_TARGET_NAME}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(${LIBRARY_TARGET_NAME}_BACKENDS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/backends")
set(${LIBRARY_TARGET_NAME}_HEADER_FILES
imgui.h
imgui_internal.h
imconfig.h
imstb_rectpack.h
imstb_truetype.h
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui.h
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui_internal.h
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imconfig.h
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imstb_rectpack.h
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imstb_truetype.h
)
set(${LIBRARY_TARGET_NAME}_SOURCE_FILES
imgui.cpp
imgui_demo.cpp
imgui_draw.cpp
imgui_tables.cpp
imgui_widgets.cpp
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui.cpp
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui_demo.cpp
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui_draw.cpp
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui_tables.cpp
${${LIBRARY_TARGET_NAME}_SOURCE_DIR}/imgui_widgets.cpp
)
# set options for backends
@ -31,68 +35,68 @@ option(IMGUI_BACKEND_OPENGL3 "Use OpenGL3 backend" OFF)
option(IMGUI_BACKEND_VULKAN "Use Vulkan backend" ON)
set(${LIBRARY_TARGET_NAME}_BACKEND_GLFW_HEADER_FILES
backends/imgui_impl_glfw.h
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_glfw.h
)
set(${LIBRARY_TARGET_NAME}_BACKEND_GLFW_SOURCE_FILES
backends/imgui_impl_glfw.cpp
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_glfw.cpp
)
set(${LIBRARY_TARGET_NAME}_BACKEND_GLUT_HEADER_FILES
backends/imgui_impl_glut.h
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_glut.h
)
set(${LIBRARY_TARGET_NAME}_BACKEND_GLUT_SOURCE_FILES
backends/imgui_impl_glut.cpp
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_glut.cpp
)
set(${LIBRARY_TARGET_NAME}_BACKEND_OPENGL3_HEADER_FILES
backends/imgui_impl_opengl3.h
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_opengl3.h
)
set(${LIBRARY_TARGET_NAME}_BACKEND_OPENGL3_SOURCE_FILES
backends/imgui_impl_opengl3.cpp
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_opengl3.cpp
)
set(${LIBRARY_TARGET_NAME}_BACKEND_VULKAN_HEADER_FILES
backends/imgui_impl_vulkan.h
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_vulkan.h
)
set(${LIBRARY_TARGET_NAME}_BACKEND_VULKAN_SOURCE_FILES
backends/imgui_impl_vulkan.cpp
${${LIBRARY_TARGET_NAME}_BACKENDS_DIR}/imgui_impl_vulkan.cpp
)
# conditionally inlcude backends
if(IMGUI_BACKEND_GLFW)
find_package(glfw3 CONFIG REQUIRED)
list(APPEND ${LIBRARY_TARGET_NAME}_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLFW_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLFW_SOURCE_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLFW_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLFW_SOURCE_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_LINK_LIBRARIES glfw)
endif()
if(IMGUI_BACKEND_GLUT)
list(APPEND ${LIBRARY_TARGET_NAME}_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLUT_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLUT_SOURCE_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLUT_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_GLUT_SOURCE_FILES})
endif()
if(IMGUI_BACKEND_OPENGL3)
list(APPEND ${LIBRARY_TARGET_NAME}_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_OPENGL3_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_OPENGL3_SOURCE_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_OPENGL3_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_OPENGL3_SOURCE_FILES})
endif()
if(IMGUI_BACKEND_VULKAN)
find_package(Vulkan REQUIRED)
list(APPEND ${LIBRARY_TARGET_NAME}_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_VULKAN_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_VULKAN_SOURCE_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_HEADER_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_VULKAN_HEADER_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_BACKEND_SOURCE_FILES ${${LIBRARY_TARGET_NAME}_BACKEND_VULKAN_SOURCE_FILES})
list(APPEND ${LIBRARY_TARGET_NAME}_LINK_LIBRARIES Vulkan::Vulkan)
endif()
add_library(
${LIBRARY_TARGET_NAME}
${${LIBRARY_TARGET_NAME}_SOURCE_FILES}
${${LIBRARY_TARGET_NAME}_HEADER_FILES})
${${LIBRARY_TARGET_NAME}_BACKEND_SOURCE_FILES})
add_library(
${PROJECT_NAME}::${LIBRARY_TARGET_NAME}
@ -112,6 +116,16 @@ else()
set(CONDA_FOUND 0)
endif()
# use target_sources with PUBLIC FILE_SET HEADERS to manage headers.
# the BASE_DIRS argument is crucial for preserving the directory structure relative to that base.
# a BASE_DIR cannot be a sub-directory of an existing BASE_DIR.
target_sources(${LIBRARY_TARGET_NAME} PUBLIC FILE_SET HEADERS
BASE_DIRS
"${${LIBRARY_TARGET_NAME}_SOURCE_DIR}"
FILES
"${${LIBRARY_TARGET_NAME}_HEADER_FILES}"
"${${LIBRARY_TARGET_NAME}_BACKEND_HEADER_FILES}")
# specify include directories for both compilation and installation process.
target_include_directories(${LIBRARY_TARGET_NAME}
PUBLIC
@ -139,15 +153,16 @@ include(GNUInstallDirs)
# specify installation targets, typology and destination folders.
install(TARGETS ${LIBRARY_TARGET_NAME}
EXPORT ${LIBRARY_TARGET_NAME} # associates this target with an export name
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBRARY_TARGET_NAME}" COMPONENT dev)
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBRARY_TARGET_NAME}" COMPONENT dev
FILE_SET HEADERS DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBRARY_TARGET_NAME}" COMPONENT dev)
# specify export configuration to make the library discoverable by other cmake project using find_package()
install(EXPORT ${LIBRARY_TARGET_NAME}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
NAMESPACE ${PROJECT_NAME}::
)
message(STATUS "Created target ${LIBRARY_TARGET_NAME} for ${PROJECT_NAME}.")