build: Sync update_deps.py
authorJeremy Kniager <jeremyk@lunarg.com>
Thu, 30 Aug 2018 14:18:43 +0000 (08:18 -0600)
committerjeremyk-lunarg <jeremyk@lunarg.com>
Wed, 26 Sep 2018 17:41:33 +0000 (11:41 -0600)
Syncing changes made to update_deps.py
in Vulkan-ValidationLayers.

Change-Id: If617596654b982023ee883fe131390c760c53532

scripts/update_deps.py

index ca9a202e38767a8d10d003e3e0b8dcd74f456fc4..119cf70292d711afc610d11ba759dc788e0f4089 100755 (executable)
@@ -176,6 +176,27 @@ googletest.
 The commands listed in "prebuild" are executed first, and then the
 commands for the specific platform are executed.
 
+- custom_build (optional)
+
+A list of commands to execute as a custom build instead of using
+the built in CMake way of building. Requires "build_step" to be
+set to "custom"
+
+You can insert the following keywords into the commands listed in
+"custom_build" if they require runtime information (like whether the
+build config is "Debug" or "Release").
+
+Keywords:
+{0} reference to a dictionary of repos and their attributes
+{1} reference to the command line arguments set before start
+{2} reference to the CONFIG_MAP value of config.
+
+Example:
+{2} returns the CONFIG_MAP value of config e.g. debug -> Debug
+{1}.config returns the config variable set when you ran update_dep.py
+{0}[Vulkan-Headers][repo_root] returns the repo_root variable from
+                                   the Vulkan-Headers GoodRepo object.
+
 - cmake_options (optional)
 
 A list of options to pass to CMake during the generation phase.
@@ -194,9 +215,19 @@ is an empty list, which means that the repo is always processed.
 - build_step (optional)
 
 Specifies if the dependent repository should be built or not. This can
-have a value of 'build' or 'skip'. The dependent repositories are
+have a value of 'build', 'custom',  or 'skip'. The dependent repositories are
 built by default.
 
+- build_platforms (optional)
+
+A list of platforms the repository will be built on.
+Legal options include:
+"windows"
+"linux"
+"darwin"
+
+Builds on all platforms by default.
+
 Note
 ----
 
@@ -217,6 +248,7 @@ import subprocess
 import sys
 import platform
 import multiprocessing
+import shlex
 import shutil
 
 KNOWN_GOOD_FILE_NAME = 'known_good.json'
@@ -253,7 +285,6 @@ def command_output(cmd, directory, fail_ok=False):
         print(stdout)
     return stdout
 
-
 class GoodRepo(object):
     """Represents a repository at a known-good commit."""
 
@@ -284,10 +315,12 @@ class GoodRepo(object):
             'prebuild_linux' in json) else []
         self.prebuild_windows = json['prebuild_windows'] if (
             'prebuild_windows' in json) else []
+        self.custom_build = json['custom_build'] if ('custom_build' in json) else []
         self.cmake_options = json['cmake_options'] if (
             'cmake_options' in json) else []
         self.ci_only = json['ci_only'] if ('ci_only' in json) else []
         self.build_step = json['build_step'] if ('build_step' in json) else 'build'
+        self.build_platforms = json['build_platforms'] if ('build_platforms' in json) else []
         # Absolute paths for a repo's directories
         dir_top = os.path.abspath(args.dir)
         self.repo_dir = os.path.join(dir_top, self.sub_dir)
@@ -295,6 +328,10 @@ class GoodRepo(object):
             self.build_dir = os.path.join(dir_top, self.build_dir)
         if self.install_dir:
             self.install_dir = os.path.join(dir_top, self.install_dir)
+           # Check if platform is one to build on
+        self.on_build_platform = False
+        if self.build_platforms == [] or platform.system().lower() in self.build_platforms:
+            self.on_build_platform = True
 
     def Clone(self):
         distutils.dir_util.mkpath(self.repo_dir)
@@ -316,16 +353,25 @@ class GoodRepo(object):
             command_output(['git', 'checkout', self.commit], self.repo_dir)
         print(command_output(['git', 'status'], self.repo_dir))
 
+    def CustomPreProcess(self, cmd_str, repo_dict):
+        return cmd_str.format(repo_dict, self._args, CONFIG_MAP[self._args.config])
+
     def PreBuild(self):
         """Execute any prebuild steps from the repo root"""
         for p in self.prebuild:
-            command_output(p.split(), self.repo_dir)
+            command_output(shlex.split(p), self.repo_dir)
         if platform.system() == 'Linux' or platform.system() == 'Darwin':
             for p in self.prebuild_linux:
-                command_output(p.split(), self.repo_dir)
+                command_output(shlex.split(p), self.repo_dir)
         if platform.system() == 'Windows':
             for p in self.prebuild_windows:
-                command_output(p.split(), self.repo_dir)
+                command_output(shlex.split(p), self.repo_dir)
+
+    def CustomBuild(self, repo_dict):
+        """Execute any custom_build steps from the repo root"""
+        for p in self.custom_build:
+            cmd = self.CustomPreProcess(p, repo_dict)
+            command_output(shlex.split(cmd), self.repo_dir)
 
     def CMakeConfig(self, repos):
         """Build CMake command for the configuration phase and execute it"""
@@ -402,7 +448,7 @@ class GoodRepo(object):
         if ret_code != 0:
             sys.exit(ret_code)
 
-    def Build(self, repos):
+    def Build(self, repos, repo_dict):
         """Build the dependent repo"""
         print('Building {n} in {d}'.format(n=self.name, d=self.repo_dir))
         print('Build dir = {b}'.format(b=self.build_dir))
@@ -411,6 +457,10 @@ class GoodRepo(object):
         # Run any prebuild commands
         self.PreBuild()
 
+        if self.build_step == 'custom':
+            self.CustomBuild(repo_dict)
+            return
+
         # Build and execute CMake command for creating build files
         self.CMakeConfig(repos)
 
@@ -473,7 +523,7 @@ def CreateHelper(args, repos, filename):
     install_names = GetInstallNames(args)
     with open(filename, 'w') as helper_file:
         for repo in repos:
-            if install_names and repo.name in install_names:
+            if install_names and repo.name in install_names and repo.on_build_platform:
                 helper_file.write('set({var} "{dir}" CACHE STRING "" FORCE)\n'
                                   .format(
                                       var=install_names[repo.name],
@@ -551,9 +601,33 @@ def main():
     abs_top_dir = os.path.abspath(args.dir)
 
     repos = GetGoodRepos(args)
+    repo_dict = {}
 
     print('Starting builds in {d}'.format(d=abs_top_dir))
     for repo in repos:
+        # If the repo has a platform whitelist, skip the repo
+        # unless we are building on a whitelisted platform.
+        if not repo.on_build_platform:
+            continue
+
+        field_list = ('url',
+                      'sub_dir',
+                      'commit',
+                      'build_dir',
+                      'install_dir',
+                      'deps',
+                      'prebuild',
+                      'prebuild_linux',
+                      'prebuild_windows',
+                      'custom_build',
+                      'cmake_options',
+                      'ci_only',
+                      'build_step',
+                      'build_platforms',
+                      'repo_dir',
+                      'on_build_platform')
+        repo_dict[repo.name] = {field: getattr(repo, field) for field in field_list};
+
         # If the repo has a CI whitelist, skip the repo unless
         # one of the CI's environment variable is set to true.
         if len(repo.ci_only):
@@ -571,8 +645,8 @@ def main():
         repo.Checkout()
 
         # Build the repository
-        if args.do_build and repo.build_step == 'build':
-            repo.Build(repos)
+        if args.do_build and repo.build_step != 'skip':
+            repo.Build(repos, repo_dict)
 
     # Need to restore original cwd in order for CreateHelper to find json file
     os.chdir(save_cwd)