blob: 119cf70292d711afc610d11ba759dc788e0f4089 [file] [log] [blame]
Karl Schultz5ff6f742018-06-21 17:38:56 -06001#!/usr/bin/env python
2
3# Copyright 2017 The Glslang Authors. All rights reserved.
4# Copyright (c) 2018 Valve Corporation
5# Copyright (c) 2018 LunarG, Inc.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18
19# This script was heavily leveraged from KhronosGroup/glslang
20# update_glslang_sources.py.
21"""update_deps.py
22
23Get and build dependent repositories using known-good commits.
24
25Purpose
26-------
27
28This program is intended to assist a developer of this repository
29(the "home" repository) by gathering and building the repositories that
30this home repository depend on. It also checks out each dependent
31repository at a "known-good" commit in order to provide stability in
32the dependent repositories.
33
34Python Compatibility
35--------------------
36
37This program can be used with Python 2.7 and Python 3.
38
39Known-Good JSON Database
40------------------------
41
42This program expects to find a file named "known-good.json" in the
43same directory as the program file. This JSON file is tailored for
44the needs of the home repository by including its dependent repositories.
45
46Program Options
47---------------
48
49See the help text (update_deps.py --help) for a complete list of options.
50
51Program Operation
52-----------------
53
54The program uses the user's current directory at the time of program
55invocation as the location for fetching and building the dependent
56repositories. The user can override this by using the "--dir" option.
57
58For example, a directory named "build" in the repository's root directory
59is a good place to put the dependent repositories because that directory
60is not tracked by Git. (See the .gitignore file.) The "external" directory
61may also be a suitable location.
62A user can issue:
63
64$ cd My-Repo
65$ mkdir build
66$ cd build
67$ ../scripts/update_deps.py
68
69or, to do the same thing, but using the --dir option:
70
71$ cd My-Repo
72$ mkdir build
73$ scripts/update_deps.py --dir=build
74
75With these commands, the "build" directory is considered the "top"
76directory where the program clones the dependent repositories. The
77JSON file configures the build and install working directories to be
78within this "top" directory.
79
80Note that the "dir" option can also specify an absolute path:
81
82$ cd My-Repo
83$ scripts/update_deps.py --dir=/tmp/deps
84
85The "top" dir is then /tmp/deps (Linux filesystem example) and is
86where this program will clone and build the dependent repositories.
87
88Helper CMake Config File
89------------------------
90
91When the program finishes building the dependencies, it writes a file
92named "helper.cmake" to the "top" directory that contains CMake commands
93for setting CMake variables for locating the dependent repositories.
94This helper file can be used to set up the CMake build files for this
95"home" repository.
96
97A complete sequence might look like:
98
99$ git clone git@github.com:My-Group/My-Repo.git
100$ cd My-Repo
101$ mkdir build
102$ cd build
103$ ../scripts/update_deps.py
104$ cmake -C helper.cmake ..
105$ cmake --build .
106
107JSON File Schema
108----------------
109
Shannon McPhersonfabe2c22018-07-31 09:41:15 -0600110There's no formal schema for the "known-good" JSON file, but here is
Karl Schultz5ff6f742018-06-21 17:38:56 -0600111a description of its elements. All elements are required except those
112marked as optional. Please see the "known_good.json" file for
113examples of all of these elements.
114
115- name
116
117The name of the dependent repository. This field can be referenced
118by the "deps.repo_name" structure to record a dependency.
119
120- url
121
122Specifies the URL of the repository.
123Example: https://github.com/KhronosGroup/Vulkan-Loader.git
124
125- sub_dir
126
127The directory where the program clones the repository, relative to
128the "top" directory.
129
130- build_dir
131
132The directory used to build the repository, relative to the "top"
133directory.
134
135- install_dir
136
137The directory used to store the installed build artifacts, relative
138to the "top" directory.
139
140- commit
141
142The commit used to checkout the repository. This can be a SHA-1
143object name or a refname used with the remote name "origin".
144For example, this field can be set to "origin/sdk-1.1.77" to
145select the end of the sdk-1.1.77 branch.
146
147- deps (optional)
148
149An array of pairs consisting of a CMake variable name and a
150repository name to specify a dependent repo and a "link" to
151that repo's install artifacts. For example:
152
153"deps" : [
154 {
155 "var_name" : "VULKAN_HEADERS_INSTALL_DIR",
156 "repo_name" : "Vulkan-Headers"
157 }
158]
159
160which represents that this repository depends on the Vulkan-Headers
161repository and uses the VULKAN_HEADERS_INSTALL_DIR CMake variable to
162specify the location where it expects to find the Vulkan-Headers install
163directory.
164Note that the "repo_name" element must match the "name" element of some
165other repository in the JSON file.
166
167- prebuild (optional)
168- prebuild_linux (optional) (For Linux and MacOS)
169- prebuild_windows (optional)
170
171A list of commands to execute before building a dependent repository.
172This is useful for repositories that require the execution of some
173sort of "update" script or need to clone an auxillary repository like
174googletest.
175
176The commands listed in "prebuild" are executed first, and then the
177commands for the specific platform are executed.
178
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600179- custom_build (optional)
180
181A list of commands to execute as a custom build instead of using
182the built in CMake way of building. Requires "build_step" to be
183set to "custom"
184
185You can insert the following keywords into the commands listed in
186"custom_build" if they require runtime information (like whether the
187build config is "Debug" or "Release").
188
189Keywords:
190{0} reference to a dictionary of repos and their attributes
191{1} reference to the command line arguments set before start
192{2} reference to the CONFIG_MAP value of config.
193
194Example:
195{2} returns the CONFIG_MAP value of config e.g. debug -> Debug
196{1}.config returns the config variable set when you ran update_dep.py
197{0}[Vulkan-Headers][repo_root] returns the repo_root variable from
198 the Vulkan-Headers GoodRepo object.
199
Karl Schultz5ff6f742018-06-21 17:38:56 -0600200- cmake_options (optional)
201
202A list of options to pass to CMake during the generation phase.
203
204- ci_only (optional)
205
206A list of environment variables where one must be set to "true"
207(case-insensitive) in order for this repo to be fetched and built.
208This list can be used to specify repos that should be built only in CI.
209Typically, this list might contain "TRAVIS" and/or "APPVEYOR" because
210each of these CI systems sets an environment variable with its own
211name to "true". Note that this could also be (ab)used to control
212the processing of the repo with any environment variable. The default
213is an empty list, which means that the repo is always processed.
214
Shannon McPhersonfabe2c22018-07-31 09:41:15 -0600215- build_step (optional)
216
217Specifies if the dependent repository should be built or not. This can
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600218have a value of 'build', 'custom', or 'skip'. The dependent repositories are
Shannon McPhersonfabe2c22018-07-31 09:41:15 -0600219built by default.
220
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600221- build_platforms (optional)
222
223A list of platforms the repository will be built on.
224Legal options include:
225"windows"
226"linux"
227"darwin"
228
229Builds on all platforms by default.
230
Karl Schultz5ff6f742018-06-21 17:38:56 -0600231Note
232----
233
234The "sub_dir", "build_dir", and "install_dir" elements are all relative
235to the effective "top" directory. Specifying absolute paths is not
236supported. However, the "top" directory specified with the "--dir"
237option can be a relative or absolute path.
238
239"""
240
241from __future__ import print_function
242
243import argparse
244import json
245import distutils.dir_util
246import os.path
247import subprocess
248import sys
249import platform
250import multiprocessing
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600251import shlex
Karl Schultz5ff6f742018-06-21 17:38:56 -0600252import shutil
253
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600254KNOWN_GOOD_FILE_NAME = 'known_good.json'
Karl Schultz5ff6f742018-06-21 17:38:56 -0600255
256CONFIG_MAP = {
257 'debug': 'Debug',
258 'release': 'Release',
259 'relwithdebinfo': 'RelWithDebInfo',
260 'minsizerel': 'MinSizeRel'
261}
262
263VERBOSE = False
264
265DEVNULL = open(os.devnull, 'wb')
266
267
268def command_output(cmd, directory, fail_ok=False):
269 """Runs a command in a directory and returns its standard output stream.
270
271 Captures the standard error stream and prints it if error.
272
273 Raises a RuntimeError if the command fails to launch or otherwise fails.
274 """
275 if VERBOSE:
276 print('In {d}: {cmd}'.format(d=directory, cmd=cmd))
277 p = subprocess.Popen(
278 cmd, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
279 (stdout, stderr) = p.communicate()
280 if p.returncode != 0:
281 print('*** Error ***\nstderr contents:\n{}'.format(stderr))
282 if not fail_ok:
283 raise RuntimeError('Failed to run {} in {}'.format(cmd, directory))
284 if VERBOSE:
285 print(stdout)
286 return stdout
287
Karl Schultz5ff6f742018-06-21 17:38:56 -0600288class GoodRepo(object):
289 """Represents a repository at a known-good commit."""
290
291 def __init__(self, json, args):
292 """Initializes this good repo object.
293
294 Args:
295 'json': A fully populated JSON object describing the repo.
296 'args': Results from ArgumentParser
297 """
298 self._json = json
299 self._args = args
300 # Required JSON elements
301 self.name = json['name']
302 self.url = json['url']
303 self.sub_dir = json['sub_dir']
Karl Schultz5ff6f742018-06-21 17:38:56 -0600304 self.commit = json['commit']
305 # Optional JSON elements
Mark Lobodzinski3fe96b62018-07-19 14:45:10 -0600306 self.build_dir = None
307 self.install_dir = None
308 if json.get('build_dir'):
309 self.build_dir = json['build_dir']
310 if json.get('install_dir'):
311 self.install_dir = json['install_dir']
Karl Schultz5ff6f742018-06-21 17:38:56 -0600312 self.deps = json['deps'] if ('deps' in json) else []
313 self.prebuild = json['prebuild'] if ('prebuild' in json) else []
314 self.prebuild_linux = json['prebuild_linux'] if (
315 'prebuild_linux' in json) else []
316 self.prebuild_windows = json['prebuild_windows'] if (
317 'prebuild_windows' in json) else []
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600318 self.custom_build = json['custom_build'] if ('custom_build' in json) else []
Karl Schultz5ff6f742018-06-21 17:38:56 -0600319 self.cmake_options = json['cmake_options'] if (
320 'cmake_options' in json) else []
321 self.ci_only = json['ci_only'] if ('ci_only' in json) else []
Shannon McPhersonfabe2c22018-07-31 09:41:15 -0600322 self.build_step = json['build_step'] if ('build_step' in json) else 'build'
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600323 self.build_platforms = json['build_platforms'] if ('build_platforms' in json) else []
Karl Schultz5ff6f742018-06-21 17:38:56 -0600324 # Absolute paths for a repo's directories
325 dir_top = os.path.abspath(args.dir)
326 self.repo_dir = os.path.join(dir_top, self.sub_dir)
Mark Lobodzinski3fe96b62018-07-19 14:45:10 -0600327 if self.build_dir:
328 self.build_dir = os.path.join(dir_top, self.build_dir)
329 if self.install_dir:
330 self.install_dir = os.path.join(dir_top, self.install_dir)
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600331 # Check if platform is one to build on
332 self.on_build_platform = False
333 if self.build_platforms == [] or platform.system().lower() in self.build_platforms:
334 self.on_build_platform = True
Karl Schultz5ff6f742018-06-21 17:38:56 -0600335
336 def Clone(self):
337 distutils.dir_util.mkpath(self.repo_dir)
338 command_output(['git', 'clone', self.url, '.'], self.repo_dir)
339
340 def Fetch(self):
341 command_output(['git', 'fetch', 'origin'], self.repo_dir)
342
343 def Checkout(self):
344 print('Checking out {n} in {d}'.format(n=self.name, d=self.repo_dir))
345 if self._args.do_clean_repo:
346 shutil.rmtree(self.repo_dir)
347 if not os.path.exists(os.path.join(self.repo_dir, '.git')):
348 self.Clone()
349 self.Fetch()
350 if len(self._args.ref):
351 command_output(['git', 'checkout', self._args.ref], self.repo_dir)
352 else:
353 command_output(['git', 'checkout', self.commit], self.repo_dir)
354 print(command_output(['git', 'status'], self.repo_dir))
355
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600356 def CustomPreProcess(self, cmd_str, repo_dict):
357 return cmd_str.format(repo_dict, self._args, CONFIG_MAP[self._args.config])
358
Karl Schultz5ff6f742018-06-21 17:38:56 -0600359 def PreBuild(self):
360 """Execute any prebuild steps from the repo root"""
361 for p in self.prebuild:
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600362 command_output(shlex.split(p), self.repo_dir)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600363 if platform.system() == 'Linux' or platform.system() == 'Darwin':
364 for p in self.prebuild_linux:
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600365 command_output(shlex.split(p), self.repo_dir)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600366 if platform.system() == 'Windows':
367 for p in self.prebuild_windows:
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600368 command_output(shlex.split(p), self.repo_dir)
369
370 def CustomBuild(self, repo_dict):
371 """Execute any custom_build steps from the repo root"""
372 for p in self.custom_build:
373 cmd = self.CustomPreProcess(p, repo_dict)
374 command_output(shlex.split(cmd), self.repo_dir)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600375
376 def CMakeConfig(self, repos):
377 """Build CMake command for the configuration phase and execute it"""
378 if self._args.do_clean_build:
379 shutil.rmtree(self.build_dir)
380 if self._args.do_clean_install:
381 shutil.rmtree(self.install_dir)
382
383 # Create and change to build directory
384 distutils.dir_util.mkpath(self.build_dir)
385 os.chdir(self.build_dir)
386
387 cmake_cmd = [
388 'cmake', self.repo_dir,
389 '-DCMAKE_INSTALL_PREFIX=' + self.install_dir
390 ]
391
392 # For each repo this repo depends on, generate a CMake variable
393 # definitions for "...INSTALL_DIR" that points to that dependent
394 # repo's install dir.
395 for d in self.deps:
396 dep_commit = [r for r in repos if r.name == d['repo_name']]
397 if len(dep_commit):
398 cmake_cmd.append('-D{var_name}={install_dir}'.format(
399 var_name=d['var_name'],
400 install_dir=dep_commit[0].install_dir))
401
402 # Add any CMake options
403 for option in self.cmake_options:
404 cmake_cmd.append(option)
405
406 # Set build config for single-configuration generators
407 if platform.system() == 'Linux' or platform.system() == 'Darwin':
408 cmake_cmd.append('-DCMAKE_BUILD_TYPE={config}'.format(
409 config=CONFIG_MAP[self._args.config]))
410
411 # Use the CMake -A option to select the platform architecture
412 # without needing a Visual Studio generator.
413 if platform.system() == 'Windows':
414 if self._args.arch == '64' or self._args.arch == 'x64' or self._args.arch == 'win64':
415 cmake_cmd.append('-A')
416 cmake_cmd.append('x64')
417
418 if VERBOSE:
419 print("CMake command: " + " ".join(cmake_cmd))
420
421 ret_code = subprocess.call(cmake_cmd)
422 if ret_code != 0:
423 sys.exit(ret_code)
424
425 def CMakeBuild(self):
426 """Build CMake command for the build phase and execute it"""
427 cmake_cmd = ['cmake', '--build', self.build_dir, '--target', 'install']
428 if self._args.do_clean:
429 cmake_cmd.append('--clean-first')
430
431 if platform.system() == 'Windows':
432 cmake_cmd.append('--config')
433 cmake_cmd.append(CONFIG_MAP[self._args.config])
434
435 # Speed up the build.
436 if platform.system() == 'Linux' or platform.system() == 'Darwin':
437 cmake_cmd.append('--')
438 cmake_cmd.append('-j{ncpu}'
439 .format(ncpu=multiprocessing.cpu_count()))
440 if platform.system() == 'Windows':
441 cmake_cmd.append('--')
442 cmake_cmd.append('/maxcpucount')
443
444 if VERBOSE:
445 print("CMake command: " + " ".join(cmake_cmd))
446
447 ret_code = subprocess.call(cmake_cmd)
448 if ret_code != 0:
449 sys.exit(ret_code)
450
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600451 def Build(self, repos, repo_dict):
Karl Schultz5ff6f742018-06-21 17:38:56 -0600452 """Build the dependent repo"""
453 print('Building {n} in {d}'.format(n=self.name, d=self.repo_dir))
454 print('Build dir = {b}'.format(b=self.build_dir))
455 print('Install dir = {i}\n'.format(i=self.install_dir))
456
457 # Run any prebuild commands
458 self.PreBuild()
459
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600460 if self.build_step == 'custom':
461 self.CustomBuild(repo_dict)
462 return
463
Karl Schultz5ff6f742018-06-21 17:38:56 -0600464 # Build and execute CMake command for creating build files
465 self.CMakeConfig(repos)
466
467 # Build and execute CMake command for the build
468 self.CMakeBuild()
469
470
471def GetGoodRepos(args):
472 """Returns the latest list of GoodRepo objects.
473
474 The known-good file is expected to be in the same
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600475 directory as this script unless overridden by the 'known_good_dir'
476 parameter.
Karl Schultz5ff6f742018-06-21 17:38:56 -0600477 """
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600478 if args.known_good_dir:
479 known_good_file = os.path.join( os.path.abspath(args.known_good_dir),
480 KNOWN_GOOD_FILE_NAME)
481 else:
482 known_good_file = os.path.join(
483 os.path.dirname(os.path.abspath(__file__)), KNOWN_GOOD_FILE_NAME)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600484 with open(known_good_file) as known_good:
485 return [
486 GoodRepo(repo, args)
487 for repo in json.loads(known_good.read())['repos']
488 ]
489
490
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600491def GetInstallNames(args):
Karl Schultz5ff6f742018-06-21 17:38:56 -0600492 """Returns the install names list.
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600493
Karl Schultz5ff6f742018-06-21 17:38:56 -0600494 The known-good file is expected to be in the same
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600495 directory as this script unless overridden by the 'known_good_dir'
496 parameter.
Karl Schultz5ff6f742018-06-21 17:38:56 -0600497 """
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600498 if args.known_good_dir:
499 known_good_file = os.path.join(os.path.abspath(args.known_good_dir),
500 KNOWN_GOOD_FILE_NAME)
501 else:
502 known_good_file = os.path.join(
503 os.path.dirname(os.path.abspath(__file__)), KNOWN_GOOD_FILE_NAME)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600504 with open(known_good_file) as known_good:
Mark Lobodzinski3fe96b62018-07-19 14:45:10 -0600505 install_info = json.loads(known_good.read())
506 if install_info.get('install_names'):
507 return install_info['install_names']
508 else:
509 return None
Karl Schultz5ff6f742018-06-21 17:38:56 -0600510
511
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600512def CreateHelper(args, repos, filename):
Karl Schultz5ff6f742018-06-21 17:38:56 -0600513 """Create a CMake config helper file.
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600514
Karl Schultz5ff6f742018-06-21 17:38:56 -0600515 The helper file is intended to be used with 'cmake -C <file>'
516 to build this home repo using the dependencies built by this script.
517
518 The install_names dictionary represents the CMake variables used by the
519 home repo to locate the install dirs of the dependent repos.
520 This information is baked into the CMake files of the home repo and so
521 this dictionary is kept with the repo via the json file.
522 """
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600523 install_names = GetInstallNames(args)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600524 with open(filename, 'w') as helper_file:
525 for repo in repos:
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600526 if install_names and repo.name in install_names and repo.on_build_platform:
Karl Schultz5ff6f742018-06-21 17:38:56 -0600527 helper_file.write('set({var} "{dir}" CACHE STRING "" FORCE)\n'
528 .format(
529 var=install_names[repo.name],
530 dir=repo.install_dir))
531
532
533def main():
534 parser = argparse.ArgumentParser(
535 description='Get and build dependent repos at known-good commits')
536 parser.add_argument(
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600537 '--known_good_dir',
538 dest='known_good_dir',
539 help="Specify directory for known_good.json file.")
540 parser.add_argument(
Karl Schultz5ff6f742018-06-21 17:38:56 -0600541 '--dir',
542 dest='dir',
543 default='.',
544 help="Set target directory for repository roots. Default is \'.\'.")
545 parser.add_argument(
546 '--ref',
547 dest='ref',
548 default='',
549 help="Override 'commit' with git reference. E.g., 'origin/master'")
550 parser.add_argument(
551 '--no-build',
552 dest='do_build',
553 action='store_false',
554 help=
555 "Clone/update repositories and generate build files without performing compilation",
556 default=True)
557 parser.add_argument(
558 '--clean',
559 dest='do_clean',
560 action='store_true',
561 help="Clean files generated by compiler and linker before building",
562 default=False)
563 parser.add_argument(
564 '--clean-repo',
565 dest='do_clean_repo',
566 action='store_true',
567 help="Delete repository directory before building",
568 default=False)
569 parser.add_argument(
570 '--clean-build',
571 dest='do_clean_build',
572 action='store_true',
573 help="Delete build directory before building",
574 default=False)
575 parser.add_argument(
576 '--clean-install',
577 dest='do_clean_install',
578 action='store_true',
579 help="Delete install directory before building",
580 default=False)
581 parser.add_argument(
582 '--arch',
583 dest='arch',
Tony-LunarGf445ff12018-07-24 16:31:20 -0600584 choices=['32', '64', 'x86', 'x64', 'win32', 'win64'],
Karl Schultz5ff6f742018-06-21 17:38:56 -0600585 type=str.lower,
586 help="Set build files architecture (Windows)",
587 default='64')
588 parser.add_argument(
589 '--config',
590 dest='config',
591 choices=['debug', 'release', 'relwithdebinfo', 'minsizerel'],
592 type=str.lower,
593 help="Set build files configuration",
594 default='debug')
595
596 args = parser.parse_args()
597 save_cwd = os.getcwd()
598
599 # Create working "top" directory if needed
600 distutils.dir_util.mkpath(args.dir)
601 abs_top_dir = os.path.abspath(args.dir)
602
603 repos = GetGoodRepos(args)
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600604 repo_dict = {}
Karl Schultz5ff6f742018-06-21 17:38:56 -0600605
606 print('Starting builds in {d}'.format(d=abs_top_dir))
607 for repo in repos:
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600608 # If the repo has a platform whitelist, skip the repo
609 # unless we are building on a whitelisted platform.
610 if not repo.on_build_platform:
611 continue
612
613 field_list = ('url',
614 'sub_dir',
615 'commit',
616 'build_dir',
617 'install_dir',
618 'deps',
619 'prebuild',
620 'prebuild_linux',
621 'prebuild_windows',
622 'custom_build',
623 'cmake_options',
624 'ci_only',
625 'build_step',
626 'build_platforms',
627 'repo_dir',
628 'on_build_platform')
629 repo_dict[repo.name] = {field: getattr(repo, field) for field in field_list};
630
Karl Schultz5ff6f742018-06-21 17:38:56 -0600631 # If the repo has a CI whitelist, skip the repo unless
632 # one of the CI's environment variable is set to true.
633 if len(repo.ci_only):
634 do_build = False
635 for env in repo.ci_only:
636 if not env in os.environ:
637 continue
638 if os.environ[env].lower() == 'true':
639 do_build = True
640 break
641 if not do_build:
642 continue
643
644 # Clone/update the repository
645 repo.Checkout()
646
647 # Build the repository
Jeremy Kniager5e9b7f72018-08-09 09:36:30 -0600648 if args.do_build and repo.build_step != 'skip':
649 repo.Build(repos, repo_dict)
Karl Schultz5ff6f742018-06-21 17:38:56 -0600650
651 # Need to restore original cwd in order for CreateHelper to find json file
652 os.chdir(save_cwd)
Mark Lobodzinskiac1043c2018-07-19 13:20:46 -0600653 CreateHelper(args, repos, os.path.join(abs_top_dir, 'helper.cmake'))
Karl Schultz5ff6f742018-06-21 17:38:56 -0600654
655 sys.exit(0)
656
657
658if __name__ == '__main__':
659 main()