• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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