-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ezvcpkg.cmake
252 lines (215 loc) · 10.3 KB
/
ezvcpkg.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
#
# EZVCPKG: A CMake function for installing VCPKG dependencies
#
# Created by Bradley Austin Davis on 2019/07/28
# Website: https://github.com/jherico/ezvcpkg
#
# Arguments:
# PACKAGES a multi-value argument specifying the packages to install
# REPO The github repository organization and name, defaults to "microsoft/vcpkg"
# URL the URL of the git repository. Defaults to "https://github.com/${REPO}.git"
# COMMIT The commit ID of the git repository to select when building. Defaults to "f990dfaa5ba82155f95b75021453c075816fd4be"
# UPDATE_TOOLCHAIN if this flag is set, the function will populate the CMAKE_TOOLCHAIN_FILE variable. Note that this will
# only have an effect if done prior to the `project()` directive of the top level CMake project.
# BASEDIR The directory in which CMake will checkout and build vcpkg instances. Each vcpkg commit will have it's own
# subdirectory. If this is not specified, it will default to the location specified by the EZVCPKG_BASEDIR environment
# variable. If that doesn't exist, it will default to ~/.ezvcpkg on OSX, and %TEMP%/ezvcpkg everywhere else
# CLEAN a single argument parameter that tells the script to clean up out of date EZVCPKG folders. The value should be the
# number of days after which a folder should be removed if it hasn't been touched. (Not currently implemented)
#
# Output:
# If successful the function will populate EZVCPKG_DIR with the location of the installed triplet, for instance
# D:\ezvcpkg\f990dfaa5ba82155f95b75021453c075816fd4be\installed\x64-windows
set(EZVCPKG_VERSION 0.1)
macro(EZVCPKG_CALCULATE_PATHS)
if (NOT EZVCPKG_BASEDIR)
if (DEFINED ENV{EZVCPKG_BASEDIR})
set(EZVCPKG_BASEDIR $ENV{EZVCPKG_BASEDIR})
else()
if(APPLE)
# OSX wipes binaries from the temp directory over time, leaving the remaining files
# This causes the vcpkg folder to end up in an unusable state, so we default to the
# home directory instead
set(EZVCPKG_BASEDIR "$ENV{HOME}/.ezvcpkg")
else()
# Initially defaulted to $ENV{TEMP} but the github build hosts don't populate this
set(EZVCPKG_BASEDIR "$ENV{HOME}/.ezvcpkg")
endif()
# We want people to specify a base directory, either through the calling EZVCPKG_FETCH
# function or through an environment variable.
message(STATUS "EZVCPKG_BASEDIR envrionment variable not found and basedir not set, using default ${EZVCPKG_BASEDIR}")
endif()
endif()
file(TO_CMAKE_PATH "${EZVCPKG_BASEDIR}/${EZVCPKG_COMMIT}" EZVCPKG_DIR)
file(TO_CMAKE_PATH "${EZVCPKG_BASEDIR}/${EZVCPKG_COMMIT}.lock" EZVCPKG_LOCK)
if (EZVCPKG_USE_HOST_VCPKG)
find_program(EZVCPKG_HOST_VCPKG vcpkg)
if (EZVCPKG_HOST_VCPKG)
message(STATUS "EZVCPKG using host vcpkg binary ${EZVCPKG_HOST_VCPKG}")
endif()
endif()
if (WIN32)
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/vcpkg.exe" EZVCPKG_EXE)
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/bootstrap-vcpkg.bat" EZVCPKG_BOOTSTRAP)
else()
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/vcpkg" EZVCPKG_EXE)
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/bootstrap-vcpkg.sh" EZVCPKG_BOOTSTRAP)
endif()
# The tag file exists purely to be a touch target every time the ezvcpkg macro is called
# making it easy to find out of date ezvcpkg folder.
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/.tag" EZVCPKG_TAG)
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/README.md" EZVCPKG_README)
# The whole host-triplet / triplet setup is to support cross compiling, specifically for things
# like android. The idea is that some things you might need from vcpkg to act as tools to execute
# on the host system, like glslang and spirv-cross, while other things you need as binaries
# compatible with the target system. However, this isn't fully fleshed out, so don't try to use
# it yet
if (WIN32)
set(EZVCPKG_HOST_TRIPLET "x64-windows")
elseif(APPLE)
set(EZVCPKG_HOST_TRIPLET "x64-osx")
else()
set(EZVCPKG_HOST_TRIPLET "x64-linux")
endif()
if (ANDROID)
set(EZVCPKG_TRIPLET "arm64-android")
else()
set(EZVCPKG_TRIPLET ${EZVCPKG_HOST_TRIPLET})
endif()
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/installed/${EZVCPKG_TRIPLET}" EZVCPKG_INSTALLED_DIR)
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/scripts/buildsystems/vcpkg.cmake" EZVCPKG_CMAKE_TOOLCHAIN)
endmacro()
macro(EZVCPKG_BOOTSTRAP)
if (NOT EXISTS "${EZVCPKG_README}")
message(STATUS "EZVCPKG Bootstrapping")
find_package(Git)
if (NOT Git_FOUND)
message(FATAL_ERROR "EZVCPKG Git not found, can't bootstrap vcpkg")
endif()
message(STATUS "EZVCPKG Cloning repository")
execute_process(
COMMAND "${GIT_EXECUTABLE}" "clone" ${EZVCPKG_URL} "${EZVCPKG_DIR}"
OUTPUT_QUIET)
# FIXME put this into a separate check verifying the commit ID of the current directory
# If the previous run had the clone work, but the checkout fail, the readme will be
# present and the user will have the default checkout, rather than their requested commit
message(STATUS "EZVCPKG Checking out commit ${EZVCPKG_COMMIT}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" "-c" "advice.detachedHead=false" "checkout" ${EZVCPKG_COMMIT}
WORKING_DIRECTORY "${EZVCPKG_DIR}"
OUTPUT_QUIET)
endif()
if (EZVCPKG_HOST_VCPKG)
set(EZVCPKG_EXE "${EZVCPKG_HOST_VCPKG}")
elseif(NOT EXISTS "${EZVCPKG_EXE}")
message(STATUS "EZVCPKG Bootstrapping vcpkg binary")
execute_process(
COMMAND ${EZVCPKG_BOOTSTRAP}
WORKING_DIRECTORY "${EZVCPKG_DIR}"
OUTPUT_QUIET)
endif()
if (NOT EXISTS "${EZVCPKG_EXE}")
message(FATAL_ERROR "EZVCPKG vcpkg binary not failed")
endif()
endmacro()
macro(EZVCPKG_BUILD)
if (EZVCPKG_SERIALIZE)
foreach(_PACKAGE ${EZVCPKG_PACKAGES})
message(STATUS "EZVCPKG Building/Verifying package ${_PACKAGE}")
execute_process(
COMMAND "${EZVCPKG_EXE}" --vcpkg-root "${EZVCPKG_DIR}" install --triplet ${EZVCPKG_TRIPLET} ${_PACKAGE}
WORKING_DIRECTORY "${EZVCPKG_DIR}"
RESULT_VARIABLE EZVCPKG_RESULT
ERROR_VARIABLE EZVCPKG_ERROR
OUTPUT_VARIABLE EZVCPKG_OUTPUT
)
endforeach()
else()
message(STATUS "EZVCPKG Building/Verifying packages ${EZVCPKG_PACKAGES}")
execute_process(
COMMAND $"{EZVCPKG_EXE}" --vcpkg-root "${EZVCPKG_DIR}" install --triplet ${EZVCPKG_TRIPLET} ${EZVCPKG_PACKAGES}
WORKING_DIRECTORY "${EZVCPKG_DIR}"
RESULT_VARIABLE EZVCPKG_RESULT
ERROR_VARIABLE EZVCPKG_ERROR
OUTPUT_VARIABLE EZVCPKG_OUTPUT
)
endif()
if (${EZVCPKG_RESULT})
message(FATAL_ERROR "EZVCPKG vcpkg execute returned failure ${EZVCPKG_ERROR} ${EZVCPKG_OUTPUT}")
endif()
file(TO_CMAKE_PATH "${EZVCPKG_DIR}/buildtrees" EZVCPKG_BUILDTREES)
if ((EXISTS ${EZVCPKG_BUILDTREES}) AND (NOT EZVCPKG_SAVE_BUILD))
message("wiping build trees")
file(REMOVE_RECURSE "${EZVCPKG_DIR}/buildtrees")
endif()
endmacro()
macro(EZVCPKG_CLEAN)
message(STATUS "EZVCPKG Cleaning unused ezvcpkg dirs after ${EZVCPKG_CLEAN} days")
message(WARNING "Cleaning not implemented")
endmacro()
macro(EZVCPKG_CHECK_ARGS)
# Default to a recent vcpkg commit, currently 2023.02.24
if (NOT EZVCPKG_COMMIT)
set(EZVCPKG_COMMIT "c8696863d371ab7f46e213d8f5ca923c4aef2a00")
endif()
if (EZVCPKG_REPO AND EZVCPKG_URL)
message(FATAL_ERROR "Set either a Git repository URL or a REPO org/name combination, but not both")
endif()
# Default to the microsoft root vcpkg repository
if((NOT EZVCPKG_URL) AND (NOT EZVCPKG_REPO))
set(EZVCPKG_REPO "microsoft/vcpkg")
endif()
# Default to github
if(NOT EZVCPKG_URL)
set(EZVCPKG_URL "https://github.com/${EZVCPKG_REPO}.git")
endif()
if (NOT EZVCPKG_PACKAGES)
message(FATAL_ERROR "No vcpkg packages specified")
endif()
endmacro()
function(EZVCPKG_FETCH_IMPL)
if (NOT EZVCPKG_ANNOUNCED)
set(EZVCPKG_ANNOUNCED 1 PARENT_SCOPE)
message(STATUS "EZVCPKG v${EZVCPKG_VERSION} starting up\n\tWebsite: https://github.com/jherico/ezvcpkg")
endif()
set(options UPDATE_TOOLCHAIN SERIALIZE USE_HOST_VCPKG SAVE_BUILD)
set(oneValueArgs COMMIT URL REPO BASEDIR OUTPUT CLEAN)
set(multiValueArgs PACKAGES)
cmake_parse_arguments(EZVCPKG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
# Validate arguments
EZVCPKG_CHECK_ARGS()
# Figure out the paths for everything
EZVCPKG_CALCULATE_PATHS()
message(STATUS "EZVCPKG initializing\n\tcommit: ${EZVCPKG_COMMIT}\n\trepository: ${EZVCPKG_URL}\n\tlocal dir: ${EZVCPKG_DIR}")
# We can't assume build systems will be well behaved if we attempt two different concurrent builds of the same
# target, so we need to have some locking here to ensure that for a given vcpkg location, only one instance
# of vcpkg runs at a given time.
# This is critical because, for instance, when Android Studio does a native code build it will concurrently execute
# cmake for debug and release versions of the build, in different directories, and therefore concurrently try to
# bootstrap and run vcpkg, which will almost certainly corrupt your build directories
file(LOCK ${EZVCPKG_LOCK})
EZVCPKG_BOOTSTRAP()
# Touch the tag file so that this directory is marked as recent, and therefore not cleanable
file(TOUCH ${EZVCPKG_TAG})
# While still holding the global lock, clean up old build directories
if (EZVCPKG_CLEAN)
EZVCPKG_CLEAN()
endif()
# Build packages
EZVCPKG_BUILD()
file(LOCK ${EZVCPKG_LOCK} RELEASE)
file(REMOVE ${EZVCPKG_LOCK})
set(EZVCPKG_DIR "${EZVCPKG_INSTALLED_DIR}" PARENT_SCOPE)
if (EZVCPKG_UPDATE_TOOLCHAIN)
set(CMAKE_TOOLCHAIN_FILE ${EZVCPKG_CMAKE_TOOLCHAIN} PARENT_SCOPE)
endif()
message(STATUS "EZVCPKG done")
endfunction()
macro(EZVCPKG_FETCH)
EZVCPKG_FETCH_IMPL(${ARGN})
if (EZVCPKG_QUIT)
unset(EZVCPKG_QUIT CACHE)
message(STATUS "EZVCPKG quitting")
return()
endif()
endmacro()