1
0
Fork 0
mirror of https://github.com/TheLartians/ModernCppStarter.git synced 2025-08-30 21:51:12 +02:00
ModernCppStarter/cmake/PackageProject.cmake
ClausKlein a3bc933175 Modernize cmake project files
Fix install target

Update cmake-format config file

Format all cmake files.

Update CPM.cmake version.

Use FILE_SET HEADER to verify and install the header files.

Prevent build problems caused by CPM_USE_LOCAL_PACKAGES

Prevent problems with doctest if local found
2025-03-06 07:00:40 +01:00

244 lines
8 KiB
CMake

cmake_minimum_required(VERSION 3.14...3.31)
set(PACKAGE_PROJECT_ROOT_PATH
"${CMAKE_CURRENT_LIST_DIR}"
CACHE INTERNAL "The path to the PackageProject directory"
)
# if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.31.0") cmake_policy(SET CMP0177 NEW) endif()
function(packageProject)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
cmake_parse_arguments(
PROJECT
""
"NAME;VERSION;INCLUDE_DIR;INCLUDE_DESTINATION;BINARY_DIR;COMPATIBILITY;EXPORT_HEADER;VERSION_HEADER;NAMESPACE;DISABLE_VERSION_SUFFIX;ARCH_INDEPENDENT;INCLUDE_HEADER_PATTERN;CPACK;RUNTIME_DESTINATION"
"DEPENDENCIES;HEADER_SETS"
${ARGN}
)
# optional feature: TRUE or FALSE or UNDEFINED! These variables will then hold the respective
# value from the argument list or be undefined if the associated one_value_keyword could not be
# found.
if(PROJECT_DISABLE_VERSION_SUFFIX)
unset(PROJECT_VERSION_SUFFIX)
else()
set(PROJECT_VERSION_SUFFIX -${PROJECT_VERSION})
endif()
if(NOT DEFINED PROJECT_COMPATIBILITY)
set(PROJECT_COMPATIBILITY AnyNewerVersion)
endif()
# we want to automatically add :: to our namespace, so only append if a namespace was given in the
# first place we also provide an alias to ensure that local and installed versions have the same
# name
if(DEFINED PROJECT_NAMESPACE)
if(PROJECT_CPACK)
set(CPACK_PACKAGE_NAMESPACE ${PROJECT_NAMESPACE})
endif()
set(PROJECT_NAMESPACE ${PROJECT_NAMESPACE}::)
add_library(${PROJECT_NAMESPACE}${PROJECT_NAME} ALIAS ${PROJECT_NAME})
endif()
if(DEFINED PROJECT_VERSION_HEADER OR DEFINED PROJECT_EXPORT_HEADER)
set(PROJECT_VERSION_INCLUDE_DIR ${PROJECT_BINARY_DIR}/PackageProjectInclude)
if(DEFINED PROJECT_EXPORT_HEADER)
include(GenerateExportHeader)
generate_export_header(
${PROJECT_NAME} EXPORT_FILE_NAME ${PROJECT_VERSION_INCLUDE_DIR}/${PROJECT_EXPORT_HEADER}
)
endif()
if(DEFINED PROJECT_VERSION_HEADER)
# clear previous matches
unset(CMAKE_MATCH_1)
unset(CMAKE_MATCH_3)
unset(CMAKE_MATCH_5)
unset(CMAKE_MATCH_7)
string(REGEX MATCH "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?$" _
"${PROJECT_VERSION}"
)
set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1})
set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_3})
set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_5})
set(PROJECT_VERSION_TWEAK ${CMAKE_MATCH_7})
if(NOT DEFINED PROJECT_VERSION_MAJOR)
set(PROJECT_VERSION_MAJOR "0")
endif()
if(NOT DEFINED PROJECT_VERSION_MINOR)
set(PROJECT_VERSION_MINOR "0")
endif()
if(NOT DEFINED PROJECT_VERSION_PATCH)
set(PROJECT_VERSION_PATCH "0")
endif()
if(NOT DEFINED PROJECT_VERSION_TWEAK)
set(PROJECT_VERSION_TWEAK "0")
endif()
string(TOUPPER ${PROJECT_NAME} UPPERCASE_PROJECT_NAME)
# ensure that the generated macro does not include invalid characters
string(REGEX REPLACE [^a-zA-Z0-9] _ UPPERCASE_PROJECT_NAME ${UPPERCASE_PROJECT_NAME})
configure_file(
${PACKAGE_PROJECT_ROOT_PATH}/version.h.in
${PROJECT_VERSION_INCLUDE_DIR}/${PROJECT_VERSION_HEADER} @ONLY
)
endif()
get_target_property(target_type ${PROJECT_NAME} TYPE)
if(target_type STREQUAL "INTERFACE_LIBRARY")
set(VISIBILITY INTERFACE)
else()
set(VISIBILITY PUBLIC)
endif()
target_include_directories(
${PROJECT_NAME} ${VISIBILITY} "$<BUILD_INTERFACE:${PROJECT_VERSION_INCLUDE_DIR}>"
)
install(
DIRECTORY ${PROJECT_VERSION_INCLUDE_DIR}/
DESTINATION ${PROJECT_INCLUDE_DESTINATION}
COMPONENT "${PROJECT_NAME}_Development"
)
endif()
set(wbpvf_extra_args "")
if(NOT DEFINED PROJECT_ARCH_INDEPENDENT)
get_target_property(target_type "${PROJECT_NAME}" TYPE)
if(target_type STREQUAL "INTERFACE_LIBRARY")
set(PROJECT_ARCH_INDEPENDENT YES)
endif()
endif()
if(PROJECT_ARCH_INDEPENDENT)
set(wbpvf_extra_args ARCH_INDEPENDENT)
# install to architecture independent (share) directory
set(INSTALL_DIR_FOR_CMAKE_CONFIGS ${CMAKE_INSTALL_DATADIR})
else()
# if x32 or multilib->x32 , install to (lib) directory. if x64, install to (lib64) directory
set(INSTALL_DIR_FOR_CMAKE_CONFIGS ${CMAKE_INSTALL_LIBDIR})
endif()
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY ${PROJECT_COMPATIBILITY} ${wbpvf_extra_args}
)
# set default runtime install subdirectory (RUNTIME_DESTINATION)
if(NOT DEFINED PROJECT_RUNTIME_DESTINATION)
set(PROJECT_RUNTIME_DESTINATION ${PROJECT_NAME}${PROJECT_VERSION_SUFFIX})
endif()
if(PROJECT_HEADER_SETS)
# required to install if use in project target since CMake 3.23
set(FILE_SET_ARGS "FILE_SET" "${PROJECT_HEADER_SETS}")
endif()
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_RUNTIME_DESTINATION}
COMPONENT "${PROJECT_NAME}_Runtime"
NAMELINK_COMPONENT "${PROJECT_NAME}_Development"
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_RUNTIME_DESTINATION}
COMPONENT "${PROJECT_NAME}_Development"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_RUNTIME_DESTINATION}
COMPONENT "${PROJECT_NAME}_Runtime"
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_RUNTIME_DESTINATION}
COMPONENT "${PROJECT_NAME}_Runtime"
PUBLIC_HEADER
DESTINATION ${PROJECT_INCLUDE_DESTINATION}
COMPONENT "${PROJECT_NAME}_Development"
${FILE_SET_ARGS}
INCLUDES
DESTINATION "${PROJECT_INCLUDE_DESTINATION}"
)
set("${PROJECT_NAME}_INSTALL_CMAKEDIR"
"${INSTALL_DIR_FOR_CMAKE_CONFIGS}/cmake/${PROJECT_NAME}${PROJECT_VERSION_SUFFIX}"
CACHE PATH "CMake package config location relative to the install prefix"
)
mark_as_advanced("${PROJECT_NAME}_INSTALL_CMAKEDIR")
configure_file(
${PACKAGE_PROJECT_ROOT_PATH}/Config.cmake.in
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" @ONLY
)
install(
EXPORT ${PROJECT_NAME}Targets
DESTINATION "${${PROJECT_NAME}_INSTALL_CMAKEDIR}"
NAMESPACE ${PROJECT_NAMESPACE}
COMPONENT "${PROJECT_NAME}_Development"
)
install(
FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
DESTINATION "${${PROJECT_NAME}_INSTALL_CMAKEDIR}"
COMPONENT "${PROJECT_NAME}_Development"
)
if(NOT DEFINED PROJECT_INCLUDE_HEADER_PATTERN)
set(PROJECT_INCLUDE_HEADER_PATTERN "*")
endif()
if(PROJECT_INCLUDE_DESTINATION AND PROJECT_INCLUDE_DIR)
install(
DIRECTORY ${PROJECT_INCLUDE_DIR}/
DESTINATION ${PROJECT_INCLUDE_DESTINATION}
COMPONENT "${PROJECT_NAME}_Development"
FILES_MATCHING
PATTERN "${PROJECT_INCLUDE_HEADER_PATTERN}"
)
endif()
set(${PROJECT_NAME}_VERSION
${PROJECT_VERSION}
CACHE INTERNAL ""
)
if(PROJECT_CPACK)
if(CPACK_PACKAGE_NAMESPACE)
set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAMESPACE}-${PROJECT_NAME})
else()
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
endif()
if(NOT CPACK_PACKAGE_DESCRIPTION_SUMMARY)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
endif()
if(NOT CPACK_PACKAGE_HOMEPAGE_URL)
set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
endif()
set(CPACK_VERBATIM_VARIABLES YES)
set(CPACK_THREADS 0)
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
endif()
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
set(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
OWNER_READ
OWNER_WRITE
OWNER_EXECUTE
GROUP_READ
GROUP_EXECUTE
WORLD_READ
WORLD_EXECUTE
)
include(CPack)
endif()
endfunction()