1include(GNUInstallDirs) 2include(CMakePackageConfigHelpers) 3 4# Install all passed libraries including <PROJECT_NAME>Config.cmake and <PROJECT_NAME>ConfigVersion.cmake 5# Assumes that your headers are in 'include/' 6# Uses GNUInstallDirs to determine install locations 7# Note: Use of BUILD_INTERFACE for headers is not required as it will be fixed up 8# Arguments: 9# - TARGETS: List of targets to install 10# - NAMESPACE: Namespace to use (Installed libraries will be available as "Namespace::Name") 11# - CONFIG_FILE: If passed, this will be used to configure the *Config.cmake, 12# else a reasonable default will be used which is enough if there are no dependencies 13# - VERSION_COMPATIBILITY: Compatibility with requested version. Defaults to SemVer semantics (SameMajorVersion) 14function(install_targets) 15 cmake_parse_arguments(PARSE_ARGV 0 ARG "" "NAMESPACE;CONFIG_FILE;VERSION_COMPATIBILITY" "TARGETS") 16 if(ARG_UNPARSED_ARGUMENTS) 17 message(FATAL_ERROR "Invalid argument(s): ${ARG_UNPARSED_ARGUMENTS}") 18 endif() 19 if(ARG_NAMESPACE) 20 string(APPEND ARG_NAMESPACE "::") 21 endif() 22 if(NOT ARG_CONFIG_FILE) 23 set(ARG_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake.in") 24 file(WRITE ${ARG_CONFIG_FILE} 25 "@PACKAGE_INIT@\n" 26 "include(\"\${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake\")\n" 27 "check_required_components(\"@PROJECT_NAME@\")\n" 28 ) 29 endif() 30 if(NOT ARG_VERSION_COMPATIBILITY) 31 set(ARG_VERSION_COMPATIBILITY SameMajorVersion) 32 endif() 33 34 # Fixup INTERFACE_INCLUDE_DIRECTORIES: 35 # Wrap source includes into BUILD_INTERFACE 36 foreach(tgt IN LISTS ARG_TARGETS) 37 get_target_property(old_inc_dirs ${tgt} INTERFACE_INCLUDE_DIRECTORIES) 38 set(inc_dirs "") 39 foreach(dir IN LISTS old_inc_dirs) 40 string(FIND "${dir}" "${PROJECT_SOURCE_DIR}" pos) 41 string(FIND "${dir}" "${PROJECT_BINARY_DIR}" pos2) 42 if(pos EQUAL 0 OR pos2 EQUAL 0) 43 set(dir "$<BUILD_INTERFACE:${dir}>") 44 endif() 45 list(APPEND inc_dirs "${dir}") 46 endforeach() 47 set_target_properties(${tgt} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${inc_dirs}") 48 endforeach() 49 50 install(TARGETS ${ARG_TARGETS} 51 EXPORT ${PROJECT_NAME}Targets 52 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 53 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 54 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 55 INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 56 ) 57 install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 58 59 set(configFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake) 60 set(versionFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake) 61 set(configInstallDestination lib/cmake/${PROJECT_NAME}) 62 63 configure_package_config_file(${ARG_CONFIG_FILE} ${configFile} INSTALL_DESTINATION ${configInstallDestination}) 64 write_basic_package_version_file(${versionFile} COMPATIBILITY ${ARG_VERSION_COMPATIBILITY}) 65 66 install(FILES ${configFile} ${versionFile} DESTINATION ${configInstallDestination}) 67 68 install( 69 EXPORT ${PROJECT_NAME}Targets 70 NAMESPACE ${ARG_NAMESPACE} 71 DESTINATION ${configInstallDestination} 72 ) 73endfunction() 74