-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExportPackageWizzard.cmake
188 lines (164 loc) · 9.89 KB
/
ExportPackageWizzard.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# ExportPackageWizzard.cmake
#
# Mark J. Olah ([email protected] DOT edu)
# Copyright 2017-2018
# Licensed under the Apache License, Version 2.0
# https://www.apache.org/licenses/LICENSE-2.0
# See: LICENSE file
#
# Prepare cmake package configuration and target export files so that
# this package can be found both from the install tree and the build tree
# This simple function provides enough flexibility to meet 90% of the use cases of small cmake projects.
# For more complex tasks it can be customized easily.
#
# Note by "Build Type" we mean the same thing as what cmake often calls "<CONFIG>" are the common build configurations
# RELEASE, DEBUG, RELWITHDEBINFO, MINSIZEREL. For Make generators this is the value of BUILD_TYPE. For now we only
# support useage on single build-type generators like Make.
#
# Respects options:
# OPT_EXPORT_BUILD_TREE - If defined and false, don't export build tree
#
#
# Options:
# DISABLE_EXPORT_BUILD_TREE - Disable the export of the build tree, if it would have otherwise been enabled.
# Single Argument Keywords
# NAME - [Default: ${PROJECT_NAME}] The name of the export. The name a client will use use to import with: find_package(NAME).
# NAMESPACE - [Default: $NAME}] The namespace in which to place the export.
# EXPORT_TARGETS_NAME - [Default: ${NAME}Targets] The name of the target export (the one used with the install(TARGET EXPORT) keyword)
# set to OFF to disable exporting Targets.cmake file.
# PACKAGE_CONFIG_TEMPLATE - The template file for package config.
# [Default: Look for PackageConfig.cmake.in under ${CMAKE_SOURCE_DIR}/cmake/<Templates|templatesModules|modules|>]
# VERSION_COMPATIBILITY - [Default:AnyNewerVersion] The argument required by write_basic_package_version_file()
# BUILD_TYPE_COMPATIBILITY - [Default:Exact]
# Exact - Require the BuildType of packages using this as a dependency to match build type exactly
# Any - Totally ignore BuildType
# CONFIG_INSTALL_DIR - [Default: lib/${NAME}/cmake/] Relative path from ${CMAKE_INSTALL_PREFIX} at which to install PackageConfig.cmake files
# SHARED_CMAKE_INSTALL_DIR - [Default: share/${NAME}/cmake/] Relative path from ${CMAKE_INSTALL_PREFIX} at which to install PackageConfig.cmake files
# SHARED_CMAKE_SOURCE_DIR - [Default: ${CMAKE_SOURCE_DIR}/cmake] Relative path from ${CMAKE_SOURCE_DIR} from which build-time useage of cmake files
# Multi-Argument Keywords
# PROVIDED_COMPONENTS - List of provided components which enables the version file to check for required components and reject builds with missing required components.
# If this variable is not set, the component check with PackageConfigVersion.cmake is disabled.
# FIND_MODULES - List of relative paths to provided custom find module files to propagate with export and install.
# EXPORTED_BUILD_TYPES - [default:${BUILD_TYPE}] The list of BUILD_TYPES this export will provide. Normally this should just
# be the current BUILD_TYPE for single build-type generators like Make.
include(CMakePackageConfigHelpers)
function(export_package_wizzard)
### Parse arguments and set defaults
set(options DISABLE_EXPORT_BUILD_TREE)
set(oneValueArgs NAME NAMESPACE EXPORT_TARGETS_NAME PACKAGE_CONFIG_TEMPLATE_PATH VERSION_COMPATIBILITY
BUILD_TYPE_COMPATIBILITY CONFIG_INSTALL_DIR SHARED_CMAKE_INSTALL_DIR SHARED_CMAKE_SOURCE_DIR)
set(multiValueArgs FIND_MODULES EXPORTED_BUILD_TYPES PROVIDED_COMPONENTS)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to export_package_wizzard(): \"${ARG_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT ARG_NAME)
set(ARG_NAME ${PROJECT_NAME})
endif()
if(NOT ARG_NAMESPACE)
set(ARG_NAMESPACE ${ARG_NAME})
endif()
if(NOT DEFINED ARG_EXPORT_TARGETS_NAME)
set(ARG_EXPORT_TARGETS_NAME ${ARG_NAME}Targets)
endif()
if(NOT ARG_PACKAGE_CONFIG_TEMPLATE)
find_file(ARG_PACKAGE_CONFIG_TEMPLATE PackageConfig.cmake.in PATHS "${CMAKE_SOURCE_DIR}/cmake"
PATH_SUFFIXES Modules modules Templates templates NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
mark_as_advanced(ARG_PACKAGE_CONFIG_TEMPLATE)
if(NOT ARG_PACKAGE_CONFIG_TEMPLATE)
message(FATAL_ERROR "Unable to find PackageConfig.cmake.in. Cannot configure exports.")
endif()
endif()
if(NOT ARG_VERSION_COMPATIBILITY)
set(ARG_VERSION_COMPATIBILITY AnyNewerVersion)
endif()
if(NOT ARG_BUILD_TYPE_COMPATIBILITY)
set(ARG_BUILD_TYPE_COMPATIBILITY Exact)
endif()
if(NOT ARG_EXPORTED_BUILD_TYPES)
string(TOLOWER "${CMAKE_BUILD_TYPE}" ARG_EXPORTED_BUILD_TYPES)
endif()
if(NOT ARG_EXPORTED_BUILD_TYPES)
message(FATAL_ERROR "No Exported build-types provided or EXPORTED_BUILD_TYPES is not set")
endif()
if(NOT ARG_CONFIG_INSTALL_DIR)
set(ARG_CONFIG_INSTALL_DIR lib/${ARG_NAME}/cmake) #Where to install project Config.cmake and ConfigVersion.cmake files
endif()
if(NOT ARG_SHARED_CMAKE_INSTALL_DIR)
set(ARG_SHARED_CMAKE_INSTALL_DIR share/${ARG_NAME}/cmake) #Where to install shared .cmake build scripts for downstream
endif()
if(NOT ARG_SHARED_CMAKE_SOURCE_DIR)
set(ARG_SHARED_CMAKE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/cmake) #Source for shared .cmake build scripts for build-tree exports
endif()
if(NOT ARG_FIND_MODULES)
set(ARG_FIND_MODULES)
endif()
if(DISABLE_EXPORT_BUILD_TREE OR CMAKE_CROSSCOMPILING OR CMAKE_EXPORT_NO_PACKAGE_REGISTRY OR (DEFINED OPT_EXPORT_BUILD_TREE AND NOT OPT_EXPORT_BUILD_TREE))
set(ARG_EXPORT_BUILD_TREE False)
else()
set(ARG_EXPORT_BUILD_TREE True)
endif()
if(ARG_UNPARSED_ARGUMENTS)
message(WARNING "export_package_wizzard: Unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
endif()
set(ARG_CONFIG_DIR ${CMAKE_BINARY_DIR}) #Directory for generated .cmake config file. Use CMAKE_CURRENT_BINARY_DIR to allow export of build dir.
set(ARG_PACKAGE_CONFIG_FILE ${ARG_NAME}Config.cmake) #<Package>Config.cmake name
set(ARG_VERSION_CONFIG_FILE ${ARG_NAME}ConfigVersion.cmake)
if(ARG_EXPORT_BUILD_TREE)
set(ARG_PACKAGE_CONFIG_INSTALL_TREE_FILE ${ARG_NAME}Config.cmake.install_tree) #Generated <Package>Config.cmake Version meant for the install tree but name mangled to prevent use in build tree
else()
set(ARG_PACKAGE_CONFIG_INSTALL_TREE_FILE ${ARG_PACKAGE_CONFIG_FILE}) #Generated <Package>Config.cmake Version meant for the install tree but name mangled to prevent use in build tree
endif()
### Generate Package Config files for downstream projects to utilize
#Generate and install ${PROJECT_NAME}ConfigVersion.cmake and related files to also check for BUILD_TYPE compatability
include(SmarterPackageVersionFile)
install_smarter_package_version_file(CONFIG_DIR ${ARG_CONFIG_DIR}
INSTALL_DIR ${ARG_CONFIG_INSTALL_DIR}
VERSION_COMPATIBILITY ${ARG_VERSION_COMPATIBILITY}
BUILD_TYPE_COMPATIBILITY ${ARG_BUILD_TYPE_COMPATIBILITY}
EXPORTED_BUILD_TYPES ${ARG_EXPORTED_BUILD_TYPES}
PROVIDED_COMPONENTS ${ARG_PROVIDED_COMPONENTS})
#Generate: ${PROJECT_NAME}Config.cmake
#Copy modules PATH_VARS to easier to use names for use in PackageConfig.cmake.in
set(EXPORT_TARGETS_NAME ${ARG_EXPORT_TARGETS_NAME})
set(SHARED_CMAKE_DIR ${ARG_SHARED_CMAKE_INSTALL_DIR})
set(FIND_MODULES_PATH ${ARG_SHARED_CMAKE_INSTALL_DIR}) #Location to look for exported Find<XXX>.cmake modules provided by this package from install tree
configure_package_config_file(${ARG_PACKAGE_CONFIG_TEMPLATE} ${ARG_CONFIG_DIR}/${ARG_PACKAGE_CONFIG_INSTALL_TREE_FILE}
INSTALL_DESTINATION ${ARG_CONFIG_INSTALL_DIR}
PATH_VARS FIND_MODULES_PATH SHARED_CMAKE_DIR)
### Install tree export
#<Package>Config.cmake
install(FILES ${ARG_CONFIG_DIR}/${ARG_PACKAGE_CONFIG_INSTALL_TREE_FILE} RENAME ${ARG_PACKAGE_CONFIG_FILE}
DESTINATION ${ARG_CONFIG_INSTALL_DIR} COMPONENT Development)
#<Package>Targets.cmake
if(ARG_EXPORT_TARGETS_NAME) #set to OFF to disable exporting Targets.cmake file
install(EXPORT ${ARG_EXPORT_TARGETS_NAME}
NAMESPACE ${ARG_NAMESPACE}::
DESTINATION ${ARG_CONFIG_INSTALL_DIR}/${CMAKE_SYSTEM_NAME} #Allows per-system targets in the same prefix.
COMPONENT Development)
endif()
#install provided Find<XXX>.cmake modules into the install tree
install(FILES ${ARG_FIND_MODULES} DESTINATION ${ARG_SHARED_CMAKE_INSTALL_DIR} COMPONENT Development)
### Build tree export
if(ARG_EXPORT_BUILD_TREE)
#Generate: ${PROJECT_NAME}Config.cmake for use in exporting from the build-tree
set(FIND_MODULES_PATH ${ARG_CONFIG_DIR}) #Location to look for exported Find<XXX>.cmake modules provided by this package from install tree
#Note setting INSTALL_DESTINATION to ${ARG_CONFIG_DIR} for build tree PackageConfig.cmake as it is never installed to install tree
set(SHARED_CMAKE_DIR ${ARG_SHARED_CMAKE_SOURCE_DIR})
configure_package_config_file(${ARG_PACKAGE_CONFIG_TEMPLATE} ${ARG_CONFIG_DIR}/${ARG_PACKAGE_CONFIG_FILE}
INSTALL_DESTINATION .
INSTALL_PREFIX ${ARG_CONFIG_DIR}
PATH_VARS FIND_MODULES_PATH SHARED_CMAKE_DIR)
#copy provided Find<XXX>.cmake modules into the build tree
foreach(module_path ${ARG_FIND_MODULES})
get_filename_component(module_name ${module_path} NAME)
configure_file(${module_path} ${ARG_CONFIG_DIR}/${module_name} COPYONLY)
endforeach()
#Make a ProjectTargets file for use in the build tree
export(EXPORT ${ARG_EXPORT_TARGETS_NAME}
FILE ${ARG_CONFIG_DIR}/${CMAKE_SYSTEM_NAME}/${ARG_EXPORT_TARGETS_NAME}.cmake #Match the ${CMAKE_SYSTEM_NAME} subdir used by install-tree variant
NAMESPACE ${ARG_NAMESPACE}::)
#Add this project build tree to the CMake user package registry
export(PACKAGE ${ARG_NAME})
endif()
endfunction()