-
Notifications
You must be signed in to change notification settings - Fork 73
/
BasisBootstrapping.cmake
225 lines (209 loc) · 10.7 KB
/
BasisBootstrapping.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
# ============================================================================
# Copyright (c) 2014 <provider-name>
# All rights reserved.
#
# See COPYING file for license information.
# ============================================================================
##############################################################################
# @file BasisBootstrapping.cmake
# @brief Auxiliary function to bootstrap the build of CMake BASIS.
##############################################################################
include (CMakeParseArguments)
# ----------------------------------------------------------------------------
## @brief Boostrap build of CMake BASIS during configuration of project.
#
# This function downloads, configures, and builds CMake BASIS. If the (cached)
# variable @c BASIS_INSTALL_PREFIX is set, it also installs BASIS into the
# specified directory. This is only required if the project uses the
# BASIS Utilities. Otherwise, the BASIS build tree can be used directly to
# build the software project which bootstrapped BASIS. It is not required
# during runtime of the software.
#
# @param[in] ARGN The list of arguments is parsed as follows:
# @par
# <table border=0>
# <tr>
# @tp @b VERSION major.minor.patch|commit @endtp
# <td>Release, commit, or branch of CMake BASIS to download.</td>
# </tr>
# <tr>
# @tp @b DOWNLOAD_URL url @endtp
# <td>URL from which to download the CMake BASIS source distribution package.
# The given URL can be either a complete download URL which includes the
# package name (which must end with .tar.gz or .zip), the path of
# a remote directory which contains the CMake BASIS packages named
# cmake-basis-version.zip (for Windows) and cmake-basis-version.tar.gz
# (for Unix), or the URL of a Git repository.
# (default: http://opensource.andreasschuh.com/cmake-basis/_downloads
# or [email protected]:schuhschuh/cmake-basis.git)</td>
# </tr>
# <tr>
# @tp @b INFORM_USER @endtp
# <td>This option causes this function to abort the initial configure step
# of CMake. It informs the user that this project required BASIS for
# the build configuration and that it upon the next configure run it
# will attempt to download and build BASIS automatically. It further
# notes that the user can set the @c BASIS_DIR variable prior to the
# next configure run in order to use an existing BASIS installation.
# (default: off)</td>
# </tr>
# <tr>
# @tp @b BASIS_VARIABLE_NAME value @endtp
# <td>Adds a build configuration to the CMake command used to configure
# the build of CMake BASIS using the -D option of @c cmake. The
# @c BASIS_VARIABLE_NAME can be any CMake option or variable that
# is normally used to configure a BASIS build using CMake. For example,
# USE_PythonInterp, USE_BASH, USE_DOXYGEN.</td>
# </tr>
# </table>
#
# @returns Sets the @c BASIS_DIR variable to the bootstrapped BASIS build.
function (basis_bootstrap)
# parse arguments -- unparsed arguments are passed on to CMake using -D
CMAKE_PARSE_ARGUMENTS (BASIS "INFORM_USER" "VERSION;DOWNLOAD_URL" "" ${ARGN})
if (NOT BASIS_VERSION)
message (FATAL_ERROR "No CMake BASIS version specified! Use 'VERSION 3.0.0', for example.")
endif ()
# abort the first time to give users a chance to specify where their
# CMake BASIS installation is located by setting BASIS_DIR in the GUI
if (BASIS_INFORM_USER)
if (DEFINED BASIS_DIR AND NOT DEFINED BASIS_INSTALL_PREFIX)
set (BASIS_INSTALL_PREFIX "" CACHE PATH "Installation prefix for CMake BASIS.")
message (FATAL_ERROR "Could not find an existing CMake BASIS installation!\n"
"This project uses CMake BASIS for the build configuration."
" Next time you configure this build by running CMake again,"
" BASIS version ${BASIS_VERSION} will be automatically downloaded"
" and build as part of the build configuration of this project."
" If you want to install this version permanently,"
" specify an installation prefix for CMake BASIS using"
" BASIS_INSTALL_PREFIX. Otherwise, leave it blank.\n"
"If you installed CMake BASIS already on your system, please"
" specify its location by setting the BASIS_DIR variable"
" before you re-configure the build system of this project.\n"
"Visit http://opensource.andreasschuh.com/cmake-basis for"
" more information about the CMake BASIS package.\n")
endif ()
endif ()
set (DOWNLOAD_PATH "${CMAKE_CURRENT_BINARY_DIR}")
if (BASIS_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]*)?$")
if (WIN32)
set (BASIS_ARCHIVE "cmake-basis-${BASIS_VERSION}.zip")
else ()
set (BASIS_ARCHIVE "cmake-basis-${BASIS_VERSION}.tar.gz")
endif ()
if (NOT BASIS_DOWNLOAD_URL)
set (BASIS_DOWNLOAD_URL "http://opensource.andreasschuh.com/cmake-basis/_downloads")
endif ()
if (NOT BASIS_DOWNLOAD_URL MATCHES "\\.(zip|tar\\.gz)$")
set (BASIS_DOWNLOAD_URL "${BASIS_DOWNLOAD_URL}/${BASIS_ARCHIVE}")
endif ()
else ()
set (BASIS_DOWNLOAD_URL "[email protected]:schuhschuh/cmake-basis.git")
endif ()
set (BASIS_SOURCE_DIR "${DOWNLOAD_PATH}/cmake-basis-${BASIS_VERSION}")
set (BASIS_BINARY_DIR "${DOWNLOAD_PATH}/cmake-basis-${BASIS_VERSION}/build")
# bootstrap BASIS build/installation only if not done before
# or when BASIS_INSTALL_PREFIX has changed
if ( NOT IS_DIRECTORY "${BASIS_BINARY_DIR}"
OR NOT DEFINED BASIS_INSTALL_PREFIX_CONFIGURED
OR NOT BASIS_INSTALL_PREFIX_CONFIGURED STREQUAL "${BASIS_INSTALL_PREFIX}")
# download and extract source code if not done before
if (NOT EXISTS "${BASIS_SOURCE_DIR}/BasisProject.cmake")
# clone Git repository and checkout specified commit/branch
if (BASIS_DOWNLOAD_URL MATCHES ".git$")
find_package (Git QUIET)
if (NOT GIT_FOUND)
set (ERRMSG "Git client not found: GIT_EXECUTABLE")
else ()
mark_as_advanced (GIT_EXECUTABLE)
message (STATUS "Cloning CMake BASIS repository...")
execute_process (
COMMAND "${GIT_EXECUTABLE}" clone "${BASIS_DOWNLOAD_URL}" "${BASIS_SOURCE_DIR}"
RESULT_VARIABLE RETVAL
ERROR_VARIABLE ERRMSG
)
if (RETVAL EQUAL 0)
execute_process (
COMMAND "${GIT_EXECUTABLE}" checkout --detach "${BASIS_VERSION}"
WORKING_DIRECTORY "${BASIS_SOURCE_DIR}"
RESULT_VARIABLE RETVAL
ERROR_VARIABLE ERRMSG
)
if (RETVAL EQUAL 0)
set (ERRMSG)
message (STATUS "Cloning CMake BASIS repository... - done")
endif ()
endif ()
endif ()
if (ERRMSG)
message (FATAL_ERROR "Failed to clone CMake BASIS ${BASIS_VERSION} from\n"
"\t${BASIS_DOWNLOAD_URL}\n"
"Error: ${ERRMSG}\n"
"Ensure GIT_EXECUTABLE is set and try again or follow the instructions at\n"
"\thttp://opensource.andreasschuh.com/cmake-basis/\n"
"to download and install it manually before configuring this project.\n")
endif ()
else ()
# download source code distribution package
if (NOT EXISTS "${DOWNLOAD_PATH}/${BASIS_ARCHIVE}")
message (STATUS "Downloading CMake BASIS v${BASIS_VERSION}...")
file (DOWNLOAD "${BASIS_DOWNLOAD_URL}" "${DOWNLOAD_PATH}/${BASIS_ARCHIVE}" STATUS RETVAL)
list (GET RETVAL 1 ERRMSG)
list (GET RETVAL 0 RETVAL)
if (NOT RETVAL EQUAL 0)
message (FATAL_ERROR "Failed to download CMake BASIS v${BASIS_VERSION} from\n"
"\t${BASIS_DOWNLOAD_URL}\n"
"Error: ${ERRMSG}\n"
"Either try again or follow the instructions at\n"
"\thttp://opensource.andreasschuh.com/cmake-basis/\n"
"to download and install it manually before configuring this project.\n")
endif ()
message (STATUS "Downloading CMake BASIS v${BASIS_VERSION}... - done")
endif ()
# extract source package
message (STATUS "Extracting CMake BASIS...")
execute_process (COMMAND ${CMAKE_COMMAND} -E tar -xvzf "${DOWNLOAD_PATH}/${BASIS_ARCHIVE}" RESULT_VARIABLE RETVAL)
if (NOT RETVAL EQUAL 0)
file (REMOVE_RECURSE "${BASIS_SOURCE_DIR}")
message (FATAL_ERROR "Failed to extract the downloaded archive file ${DOWNLOAD_PATH}/${BASIS_ARCHIVE}!")
endif ()
message (STATUS "Extracting CMake BASIS... - done")
endif ()
endif ()
# configure
file (MAKE_DIRECTORY "${BASIS_BINARY_DIR}")
set (CMAKE_ARGUMENTS "-DBASIS_REGISTER:BOOL=OFF") # do not register this BASIS build/installation
# as it should only be used by this project
if (BASIS_INSTALL_PREFIX)
list (APPEND CMAKE_ARGUMENTS "-DCMAKE_INSTALL_PREFIX=${BASIS_INSTALL_PREFIX}")
endif ()
list (LENGTH BASIS_UNPARSED_ARGUMENTS N)
while (N GREATER 0)
list (GET BASIS_UNPARSED_ARGUMENTS 0 VARIABLE_NAME)
list (GET BASIS_UNPARSED_ARGUMENTS 1 VARIABLE_VALUE)
list (APPEND CMAKE_ARGUMENTS "-D${VARIABLE_NAME}=${VARIABLE_VALUE}")
list (REMOVE_AT BASIS_UNPARSED_ARGUMENTS 0 1)
math (EXPR N "${N} - 2")
endwhile ()
execute_process (
COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" ${CMAKE_ARGUMENTS} "${BASIS_SOURCE_DIR}"
WORKING_DIRECTORY "${BASIS_BINARY_DIR}"
)
# build
execute_process (COMMAND "${CMAKE_COMMAND}" --build "${BASIS_BINARY_DIR}" --config Release)
# install
if (BASIS_INSTALL_PREFIX)
execute_process (COMMAND "${CMAKE_COMMAND}" --build "${BASIS_BINARY_DIR}" --config Release --target install)
set (BASIS_DIR "${BASIS_INSTALL_PREFIX}" PARENT_SCOPE)
else ()
set (BASIS_DIR "${BASIS_BINARY_DIR}" PARENT_SCOPE)
endif ()
# remember in which directory BASIS was installed to avoid re-running
# the bootstrapping every time the project needs to be re-configured
set (BASIS_INSTALL_PREFIX_CONFIGURED "${BASIS_INSTALL_PREFIX}" CACHE INTERNAL "" FORCE)
elseif (BASIS_INSTALL_PREFIX_CONFIGURED)
set (BASIS_DIR "${BASIS_INSTALL_PREFIX_CONFIGURED}" PARENT_SCOPE)
else ()
set (BASIS_DIR "${BASIS_BINARY_DIR}" PARENT_SCOPE)
endif ()
endfunction (basis_bootstrap)