-
Notifications
You must be signed in to change notification settings - Fork 0
/
SuperbuildPackageMacros.cmake
269 lines (230 loc) · 9.68 KB
/
SuperbuildPackageMacros.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#[==[.md
# Packaging support
One use case of the superbuild is to build packages for projects in order to
distribute for use as release binaries. The superbuild creates these packages
as tests. The reason it isn't done as a CPack step of the build is because
CPack only supports a single package per build. Multiple formats are supported,
but not distinct packages. Another reason is that CPack runs the `install` step
of a project which redoes a build of all targets. The superbuild may have "use
master" sources and when making a package, we don't want to change what is
being packaged.
The general strategy for the tests is to have a CMake project generated in the
build tree which includes the necessary `.bundle.cmake` files. These files
contain install code and can use CPack variables to change the generated
package.
#]==]
set(_superbuild_packaging_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
# TODO: link to the right section in SuperbuildVariables.md
#[==[.md
## Adding a package test
The `superbuild_add_extra_package_test` function handles the logic for adding a
test which builds the package. Due to the way CPack works, only one packaging
test may be run concurrently.
```
superbuild_add_extra_package_test(<NAME> <GENERATOR>
[<PROPERTY> <VALUE>]...)
```
Adds a test with the name `cpack-NAME-GENERATOR`. The packaging rules are
handled by including a `NAME.bundle.cmake` file. The same include paths used in
the build are available in the packaging steps. By default, only the variables
in the [SuperbuildVariables][] packaging section are available. Other variables
may be passed to the packaging step by adding the variable name to the
`superbuild_export_variables` list. The value of the variable available when
adding the test is used.
All other arguments are set as properties on the tests. The only reserved
property is the `RESOURCE_LOCK` property.
[SuperbuildVariables]: SuperbuildVariables.md
#]==]
# TODO: use a PROPERTIES argument
# TODO: use a VARIABLES argument
function (superbuild_add_extra_package_test name generator)
set(superbuild_extra_variables)
foreach (variable IN LISTS superbuild_export_variables)
string(APPEND superbuild_extra_variables
"set(\"${variable}\" \"${${variable}}\")\n")
endforeach ()
get_property(projects_with_plugins GLOBAL PROPERTY sb_projects_with_plugins)
string(APPEND superbuild_extra_variables
"set(\"projects_with_plugins\" \"${projects_with_plugins}\")\n")
foreach (project IN LISTS projects_with_plugins)
get_property(plugin_files GLOBAL PROPERTY "${project}_plugin_files")
get_property(plugin_omit GLOBAL PROPERTY "${project}_plugins_omit")
string(APPEND superbuild_extra_variables
"set(\"${project}_plugin_files\" \"${plugin_files}\")\n")
if (plugin_omit)
string(APPEND superbuild_extra_variables
"set(\"${project}_plugin_omit\" \"${plugin_omit}\")\n")
endif ()
endforeach ()
set(cpack_source_dir "${CMAKE_BINARY_DIR}/cpack/${name}/${generator}")
# Create a build directory so that the installation variant doesn't conflict.
set(cpack_build_dir "${cpack_source_dir}/build")
configure_file(
"${_superbuild_packaging_cmake_dir}/superbuild_package_cmakelists.cmake.in"
"${cpack_source_dir}/CMakeLists.txt"
@ONLY)
file(MAKE_DIRECTORY "${cpack_build_dir}")
set_property(GLOBAL APPEND
PROPERTY
_superbuild_packages "${name}/${generator}")
add_test(
NAME "cpack-${name}-${generator}"
COMMAND "${CMAKE_COMMAND}"
-Dname=${name}
-Dcmake_generator=${CMAKE_GENERATOR}
-Dcpack_generator=${generator}
-Doutput_directory=${CMAKE_BINARY_DIR}
-Dsource_directory=${cpack_source_dir}
-Dbuild_directory=${cpack_build_dir}
-P "${_superbuild_packaging_cmake_dir}/scripts/package_test.cmake"
WORKING_DIRECTORY "${cpack_build_dir}")
set_tests_properties("cpack-${name}-${generator}"
PROPERTIES
RESOURCE_LOCK cpack
${ARGN})
endfunction ()
function (superbuild_package_suffix package_suffix)
# Set suffix to be used for generating archives. This ensures that the package
# files have decent names that we can directly upload to the website.
set(package_suffix_items)
if (APPLE)
list(APPEND package_suffix_items
"OSX${CMAKE_OSX_DEPLOYMENT_TARGET}")
else ()
list(APPEND package_suffix_items
"${CMAKE_SYSTEM_NAME}")
endif ()
list(APPEND package_suffix_items
"${CMAKE_SYSTEM_PROCESSOR}")
string(REPLACE ";" "-" package_suffix_default "${package_suffix_items}")
# package_suffix: A string that can be set to the suffix you want to use
# for all the generated packages. By default, it is determined by the features
# enabled.
set("${package_suffix}" "<default>"
CACHE STRING "String to use as a suffix for generated packages")
mark_as_advanced("${package_suffix}")
if (NOT package_suffix OR "${${package_suffix}}" STREQUAL "<default>")
set("${package_suffix}" ${package_suffix_default} PARENT_SCOPE)
elseif (NOT "${${package_suffix}}" STREQUAL package_suffix_default)
message(WARNING
"The suffix for the package (${${package_suffix}}) does not match the "
"suggested suffix based on build options (${package_suffix_default}). "
"Set it to '<default>' or an empty string to use the default suffix. "
"Using the provided suffix.")
endif ()
endfunction()
#[==[.md
In addition to packages, a package may be used as a template for the `install`
target of the superbuild.
```
superbuild_enable_install_target(<DEFAULT>)
```
This uses a user-selectable `.bundle.cmake` to control the `install` target of
the superbuild. The default should be in the form `<NAME>/<GENERATOR>`. An
error is produced if the test for the package does not exist.
#]==]
function (superbuild_enable_install_target default)
get_property(all_packages GLOBAL
PROPERTY _superbuild_packages)
set(SUPERBUILD_DEFAULT_INSTALL "${default}"
CACHE STRING "The package to install by default")
set_property(CACHE SUPERBUILD_DEFAULT_INSTALL
PROPERTY
STRINGS "${all_packages}")
if (SUPERBUILD_DEFAULT_INSTALL)
set(cpack_source_dir "${CMAKE_BINARY_DIR}/cpack/${SUPERBUILD_DEFAULT_INSTALL}")
set(cpack_build_dir "${cpack_source_dir}/install")
file(MAKE_DIRECTORY "${cpack_build_dir}")
if (NOT EXISTS "${cpack_source_dir}")
message(FATAL_ERROR
"The ${SUPERBUILD_DEFAULT_INSTALL} package does not exist; it cannot "
"be used as the default \"install\" target.")
endif ()
install(CODE
"file(MAKE_DIRECTORY \"${cpack_build_dir}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\"
\"-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}\"
\"-Dsuperbuild_is_install_target:BOOL=ON\"
\"${cpack_source_dir}\"
RESULT_VARIABLE res
WORKING_DIRECTORY \"${cpack_build_dir}\")
if (res)
message(FATAL_ERROR \"Failed to configure the ${SUPERBUILD_DEFAULT_INSTALL} package.\")
endif ()
execute_process(
COMMAND \"${CMAKE_COMMAND}\"
--build \"${cpack_build_dir}\"
--target install
RESULT_VARIABLE res)
if (res)
message(FATAL_ERROR \"Failed to install the ${SUPERBUILD_DEFAULT_INSTALL} package.\")
endif ()"
COMPONENT install)
endif ()
endfunction ()
function (_superbuild_package_discover)
set(_superbuild_package_list)
set(_duplicate_package_list)
set(_package_path)
foreach (root IN LISTS superbuild_package_roots)
list(APPEND _package_path "${root}")
file(GLOB children RELATIVE "${root}" "${root}/*")
foreach (child IN LISTS children)
if (IS_DIRECTORY "${root}/${child}")
if (NOT child IN_LIST _superbuild_package_list)
message(STATUS "found package: ${child}")
list(PREPEND _superbuild_package_list "${child}")
list(APPEND _package_path "${root}/${child}")
foreach (platform IN LISTS platforms)
list(APPEND _package_path "${root}/${child}/${platform}")
endforeach ()
else ()
list(APPEND _duplicate_package_list "${child}")
endif ()
endif ()
endforeach ()
endforeach ()
if (_duplicate_package_list)
list(REMOVE_DUPLICATES _duplicate_package_list)
string(REPLACE ";" " " dup_list "${_duplicate_package_list}")
message(FATAL_ERROR "Detected duplicate packages: ${dup_list}")
endif ()
set(_superbuild_package_list
"${_superbuild_package_list}"
PARENT_SCOPE)
set(_superbuild_package_roots
"${_package_path}"
PARENT_SCOPE)
endfunction ()
macro (_superbuild_package_select)
if (_superbuild_package_list)
list(INSERT CMAKE_MODULE_PATH 0
"${_superbuild_package_roots}")
# Select a default if there was not one set
if (NOT _superbuild_package_default)
set(_superbuild_package_default "<none>")
endif ()
message(STATUS "Default package: ${_superbuild_package_default}")
if (_superbuild_package_list)
list(APPEND _superbuild_package_list "<custom>;<none>")
endif ()
set(SUPERBUILD_PACKAGE_MODE "${_superbuild_package_default}"
CACHE STRING "Superbuild packaging mode")
if (NOT SUPERBUILD_PACKAGE_MODE IN_LIST _superbuild_package_list)
message(FATAL_ERROR "SUPERBUILD_PACKAGE_MODE is not valid: ${SUPERBUILD_PACKAGE_MODE}")
endif ()
set_property(CACHE SUPERBUILD_PACKAGE_MODE
PROPERTY
STRINGS "${_superbuild_package_list}")
# TODO: Allow custom combinations of packages
if (SUPERBUILD_PACKAGE_MODE STREQUAL "<custom>")
set(SUPERBUILD_PACKAGE_MODE "<none>")
message(WARNING
"<custom> is currently not enabled for SUPERBUILD_PACKAGE_MODE. Setting it to <none>")
endif ()
if (NOT SUPERBUILD_PACKAGE_MODE STREQUAL "<none>")
include("${SUPERBUILD_PACKAGE_MODE}.configure" OPTIONAL)
endif ()
endif ()
endmacro ()