15db71995Sopenharmony_ci#!/usr/bin/env python3 25db71995Sopenharmony_ci 35db71995Sopenharmony_ci# Copyright 2017 The Glslang Authors. All rights reserved. 45db71995Sopenharmony_ci# Copyright (c) 2018-2023 Valve Corporation 55db71995Sopenharmony_ci# Copyright (c) 2018-2023 LunarG, Inc. 65db71995Sopenharmony_ci# Copyright (c) 2023-2023 RasterGrid Kft. 75db71995Sopenharmony_ci# 85db71995Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 95db71995Sopenharmony_ci# you may not use this file except in compliance with the License. 105db71995Sopenharmony_ci# You may obtain a copy of the License at 115db71995Sopenharmony_ci# 125db71995Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 135db71995Sopenharmony_ci# 145db71995Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 155db71995Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 165db71995Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 175db71995Sopenharmony_ci# See the License for the specific language governing permissions and 185db71995Sopenharmony_ci# limitations under the License. 195db71995Sopenharmony_ci 205db71995Sopenharmony_ci# This script was heavily leveraged from KhronosGroup/glslang 215db71995Sopenharmony_ci# update_glslang_sources.py. 225db71995Sopenharmony_ci"""update_deps.py 235db71995Sopenharmony_ci 245db71995Sopenharmony_ciGet and build dependent repositories using known-good commits. 255db71995Sopenharmony_ci 265db71995Sopenharmony_ciPurpose 275db71995Sopenharmony_ci------- 285db71995Sopenharmony_ci 295db71995Sopenharmony_ciThis program is intended to assist a developer of this repository 305db71995Sopenharmony_ci(the "home" repository) by gathering and building the repositories that 315db71995Sopenharmony_cithis home repository depend on. It also checks out each dependent 325db71995Sopenharmony_cirepository at a "known-good" commit in order to provide stability in 335db71995Sopenharmony_cithe dependent repositories. 345db71995Sopenharmony_ci 355db71995Sopenharmony_ciKnown-Good JSON Database 365db71995Sopenharmony_ci------------------------ 375db71995Sopenharmony_ci 385db71995Sopenharmony_ciThis program expects to find a file named "known-good.json" in the 395db71995Sopenharmony_cisame directory as the program file. This JSON file is tailored for 405db71995Sopenharmony_cithe needs of the home repository by including its dependent repositories. 415db71995Sopenharmony_ci 425db71995Sopenharmony_ciProgram Options 435db71995Sopenharmony_ci--------------- 445db71995Sopenharmony_ci 455db71995Sopenharmony_ciSee the help text (update_deps.py --help) for a complete list of options. 465db71995Sopenharmony_ci 475db71995Sopenharmony_ciProgram Operation 485db71995Sopenharmony_ci----------------- 495db71995Sopenharmony_ci 505db71995Sopenharmony_ciThe program uses the user's current directory at the time of program 515db71995Sopenharmony_ciinvocation as the location for fetching and building the dependent 525db71995Sopenharmony_cirepositories. The user can override this by using the "--dir" option. 535db71995Sopenharmony_ci 545db71995Sopenharmony_ciFor example, a directory named "build" in the repository's root directory 555db71995Sopenharmony_ciis a good place to put the dependent repositories because that directory 565db71995Sopenharmony_ciis not tracked by Git. (See the .gitignore file.) The "external" directory 575db71995Sopenharmony_cimay also be a suitable location. 585db71995Sopenharmony_ciA user can issue: 595db71995Sopenharmony_ci 605db71995Sopenharmony_ci$ cd My-Repo 615db71995Sopenharmony_ci$ mkdir build 625db71995Sopenharmony_ci$ cd build 635db71995Sopenharmony_ci$ ../scripts/update_deps.py 645db71995Sopenharmony_ci 655db71995Sopenharmony_cior, to do the same thing, but using the --dir option: 665db71995Sopenharmony_ci 675db71995Sopenharmony_ci$ cd My-Repo 685db71995Sopenharmony_ci$ mkdir build 695db71995Sopenharmony_ci$ scripts/update_deps.py --dir=build 705db71995Sopenharmony_ci 715db71995Sopenharmony_ciWith these commands, the "build" directory is considered the "top" 725db71995Sopenharmony_cidirectory where the program clones the dependent repositories. The 735db71995Sopenharmony_ciJSON file configures the build and install working directories to be 745db71995Sopenharmony_ciwithin this "top" directory. 755db71995Sopenharmony_ci 765db71995Sopenharmony_ciNote that the "dir" option can also specify an absolute path: 775db71995Sopenharmony_ci 785db71995Sopenharmony_ci$ cd My-Repo 795db71995Sopenharmony_ci$ scripts/update_deps.py --dir=/tmp/deps 805db71995Sopenharmony_ci 815db71995Sopenharmony_ciThe "top" dir is then /tmp/deps (Linux filesystem example) and is 825db71995Sopenharmony_ciwhere this program will clone and build the dependent repositories. 835db71995Sopenharmony_ci 845db71995Sopenharmony_ciHelper CMake Config File 855db71995Sopenharmony_ci------------------------ 865db71995Sopenharmony_ci 875db71995Sopenharmony_ciWhen the program finishes building the dependencies, it writes a file 885db71995Sopenharmony_cinamed "helper.cmake" to the "top" directory that contains CMake commands 895db71995Sopenharmony_cifor setting CMake variables for locating the dependent repositories. 905db71995Sopenharmony_ciThis helper file can be used to set up the CMake build files for this 915db71995Sopenharmony_ci"home" repository. 925db71995Sopenharmony_ci 935db71995Sopenharmony_ciA complete sequence might look like: 945db71995Sopenharmony_ci 955db71995Sopenharmony_ci$ git clone git@github.com:My-Group/My-Repo.git 965db71995Sopenharmony_ci$ cd My-Repo 975db71995Sopenharmony_ci$ mkdir build 985db71995Sopenharmony_ci$ cd build 995db71995Sopenharmony_ci$ ../scripts/update_deps.py 1005db71995Sopenharmony_ci$ cmake -C helper.cmake .. 1015db71995Sopenharmony_ci$ cmake --build . 1025db71995Sopenharmony_ci 1035db71995Sopenharmony_ciJSON File Schema 1045db71995Sopenharmony_ci---------------- 1055db71995Sopenharmony_ci 1065db71995Sopenharmony_ciThere's no formal schema for the "known-good" JSON file, but here is 1075db71995Sopenharmony_cia description of its elements. All elements are required except those 1085db71995Sopenharmony_cimarked as optional. Please see the "known_good.json" file for 1095db71995Sopenharmony_ciexamples of all of these elements. 1105db71995Sopenharmony_ci 1115db71995Sopenharmony_ci- name 1125db71995Sopenharmony_ci 1135db71995Sopenharmony_ciThe name of the dependent repository. This field can be referenced 1145db71995Sopenharmony_ciby the "deps.repo_name" structure to record a dependency. 1155db71995Sopenharmony_ci 1165db71995Sopenharmony_ci- api 1175db71995Sopenharmony_ci 1185db71995Sopenharmony_ciThe name of the API the dependency is specific to (e.g. "vulkan"). 1195db71995Sopenharmony_ci 1205db71995Sopenharmony_ci- url 1215db71995Sopenharmony_ci 1225db71995Sopenharmony_ciSpecifies the URL of the repository. 1235db71995Sopenharmony_ciExample: https://github.com/KhronosGroup/Vulkan-Loader.git 1245db71995Sopenharmony_ci 1255db71995Sopenharmony_ci- sub_dir 1265db71995Sopenharmony_ci 1275db71995Sopenharmony_ciThe directory where the program clones the repository, relative to 1285db71995Sopenharmony_cithe "top" directory. 1295db71995Sopenharmony_ci 1305db71995Sopenharmony_ci- build_dir 1315db71995Sopenharmony_ci 1325db71995Sopenharmony_ciThe directory used to build the repository, relative to the "top" 1335db71995Sopenharmony_cidirectory. 1345db71995Sopenharmony_ci 1355db71995Sopenharmony_ci- install_dir 1365db71995Sopenharmony_ci 1375db71995Sopenharmony_ciThe directory used to store the installed build artifacts, relative 1385db71995Sopenharmony_cito the "top" directory. 1395db71995Sopenharmony_ci 1405db71995Sopenharmony_ci- commit 1415db71995Sopenharmony_ci 1425db71995Sopenharmony_ciThe commit used to checkout the repository. This can be a SHA-1 1435db71995Sopenharmony_ciobject name or a refname used with the remote name "origin". 1445db71995Sopenharmony_ci 1455db71995Sopenharmony_ci- deps (optional) 1465db71995Sopenharmony_ci 1475db71995Sopenharmony_ciAn array of pairs consisting of a CMake variable name and a 1485db71995Sopenharmony_cirepository name to specify a dependent repo and a "link" to 1495db71995Sopenharmony_cithat repo's install artifacts. For example: 1505db71995Sopenharmony_ci 1515db71995Sopenharmony_ci"deps" : [ 1525db71995Sopenharmony_ci { 1535db71995Sopenharmony_ci "var_name" : "VULKAN_HEADERS_INSTALL_DIR", 1545db71995Sopenharmony_ci "repo_name" : "Vulkan-Headers" 1555db71995Sopenharmony_ci } 1565db71995Sopenharmony_ci] 1575db71995Sopenharmony_ci 1585db71995Sopenharmony_ciwhich represents that this repository depends on the Vulkan-Headers 1595db71995Sopenharmony_cirepository and uses the VULKAN_HEADERS_INSTALL_DIR CMake variable to 1605db71995Sopenharmony_cispecify the location where it expects to find the Vulkan-Headers install 1615db71995Sopenharmony_cidirectory. 1625db71995Sopenharmony_ciNote that the "repo_name" element must match the "name" element of some 1635db71995Sopenharmony_ciother repository in the JSON file. 1645db71995Sopenharmony_ci 1655db71995Sopenharmony_ci- prebuild (optional) 1665db71995Sopenharmony_ci- prebuild_linux (optional) (For Linux and MacOS) 1675db71995Sopenharmony_ci- prebuild_windows (optional) 1685db71995Sopenharmony_ci 1695db71995Sopenharmony_ciA list of commands to execute before building a dependent repository. 1705db71995Sopenharmony_ciThis is useful for repositories that require the execution of some 1715db71995Sopenharmony_cisort of "update" script or need to clone an auxillary repository like 1725db71995Sopenharmony_cigoogletest. 1735db71995Sopenharmony_ci 1745db71995Sopenharmony_ciThe commands listed in "prebuild" are executed first, and then the 1755db71995Sopenharmony_cicommands for the specific platform are executed. 1765db71995Sopenharmony_ci 1775db71995Sopenharmony_ci- custom_build (optional) 1785db71995Sopenharmony_ci 1795db71995Sopenharmony_ciA list of commands to execute as a custom build instead of using 1805db71995Sopenharmony_cithe built in CMake way of building. Requires "build_step" to be 1815db71995Sopenharmony_ciset to "custom" 1825db71995Sopenharmony_ci 1835db71995Sopenharmony_ciYou can insert the following keywords into the commands listed in 1845db71995Sopenharmony_ci"custom_build" if they require runtime information (like whether the 1855db71995Sopenharmony_cibuild config is "Debug" or "Release"). 1865db71995Sopenharmony_ci 1875db71995Sopenharmony_ciKeywords: 1885db71995Sopenharmony_ci{0} reference to a dictionary of repos and their attributes 1895db71995Sopenharmony_ci{1} reference to the command line arguments set before start 1905db71995Sopenharmony_ci{2} reference to the CONFIG_MAP value of config. 1915db71995Sopenharmony_ci 1925db71995Sopenharmony_ciExample: 1935db71995Sopenharmony_ci{2} returns the CONFIG_MAP value of config e.g. debug -> Debug 1945db71995Sopenharmony_ci{1}.config returns the config variable set when you ran update_dep.py 1955db71995Sopenharmony_ci{0}[Vulkan-Headers][repo_root] returns the repo_root variable from 1965db71995Sopenharmony_ci the Vulkan-Headers GoodRepo object. 1975db71995Sopenharmony_ci 1985db71995Sopenharmony_ci- cmake_options (optional) 1995db71995Sopenharmony_ci 2005db71995Sopenharmony_ciA list of options to pass to CMake during the generation phase. 2015db71995Sopenharmony_ci 2025db71995Sopenharmony_ci- ci_only (optional) 2035db71995Sopenharmony_ci 2045db71995Sopenharmony_ciA list of environment variables where one must be set to "true" 2055db71995Sopenharmony_ci(case-insensitive) in order for this repo to be fetched and built. 2065db71995Sopenharmony_ciThis list can be used to specify repos that should be built only in CI. 2075db71995Sopenharmony_ci 2085db71995Sopenharmony_ci- build_step (optional) 2095db71995Sopenharmony_ci 2105db71995Sopenharmony_ciSpecifies if the dependent repository should be built or not. This can 2115db71995Sopenharmony_cihave a value of 'build', 'custom', or 'skip'. The dependent repositories are 2125db71995Sopenharmony_cibuilt by default. 2135db71995Sopenharmony_ci 2145db71995Sopenharmony_ci- build_platforms (optional) 2155db71995Sopenharmony_ci 2165db71995Sopenharmony_ciA list of platforms the repository will be built on. 2175db71995Sopenharmony_ciLegal options include: 2185db71995Sopenharmony_ci"windows" 2195db71995Sopenharmony_ci"linux" 2205db71995Sopenharmony_ci"darwin" 2215db71995Sopenharmony_ci"android" 2225db71995Sopenharmony_ci 2235db71995Sopenharmony_ciBuilds on all platforms by default. 2245db71995Sopenharmony_ci 2255db71995Sopenharmony_ciNote 2265db71995Sopenharmony_ci---- 2275db71995Sopenharmony_ci 2285db71995Sopenharmony_ciThe "sub_dir", "build_dir", and "install_dir" elements are all relative 2295db71995Sopenharmony_cito the effective "top" directory. Specifying absolute paths is not 2305db71995Sopenharmony_cisupported. However, the "top" directory specified with the "--dir" 2315db71995Sopenharmony_cioption can be a relative or absolute path. 2325db71995Sopenharmony_ci 2335db71995Sopenharmony_ci""" 2345db71995Sopenharmony_ci 2355db71995Sopenharmony_ciimport argparse 2365db71995Sopenharmony_ciimport json 2375db71995Sopenharmony_ciimport os 2385db71995Sopenharmony_ciimport os.path 2395db71995Sopenharmony_ciimport subprocess 2405db71995Sopenharmony_ciimport sys 2415db71995Sopenharmony_ciimport platform 2425db71995Sopenharmony_ciimport multiprocessing 2435db71995Sopenharmony_ciimport shlex 2445db71995Sopenharmony_ciimport shutil 2455db71995Sopenharmony_ciimport stat 2465db71995Sopenharmony_ciimport time 2475db71995Sopenharmony_ci 2485db71995Sopenharmony_ciKNOWN_GOOD_FILE_NAME = 'known_good.json' 2495db71995Sopenharmony_ci 2505db71995Sopenharmony_ciCONFIG_MAP = { 2515db71995Sopenharmony_ci 'debug': 'Debug', 2525db71995Sopenharmony_ci 'release': 'Release', 2535db71995Sopenharmony_ci 'relwithdebinfo': 'RelWithDebInfo', 2545db71995Sopenharmony_ci 'minsizerel': 'MinSizeRel' 2555db71995Sopenharmony_ci} 2565db71995Sopenharmony_ci 2575db71995Sopenharmony_ci# NOTE: CMake also uses the VERBOSE environment variable. This is intentional. 2585db71995Sopenharmony_ciVERBOSE = os.getenv("VERBOSE") 2595db71995Sopenharmony_ci 2605db71995Sopenharmony_ciDEVNULL = open(os.devnull, 'wb') 2615db71995Sopenharmony_ci 2625db71995Sopenharmony_ci 2635db71995Sopenharmony_cidef on_rm_error( func, path, exc_info): 2645db71995Sopenharmony_ci """Error handler for recursively removing a directory. The 2655db71995Sopenharmony_ci shutil.rmtree function can fail on Windows due to read-only files. 2665db71995Sopenharmony_ci This handler will change the permissions for the file and continue. 2675db71995Sopenharmony_ci """ 2685db71995Sopenharmony_ci os.chmod( path, stat.S_IWRITE ) 2695db71995Sopenharmony_ci os.unlink( path ) 2705db71995Sopenharmony_ci 2715db71995Sopenharmony_cidef make_or_exist_dirs(path): 2725db71995Sopenharmony_ci "Wrapper for os.makedirs that tolerates the directory already existing" 2735db71995Sopenharmony_ci # Could use os.makedirs(path, exist_ok=True) if we drop python2 2745db71995Sopenharmony_ci if not os.path.isdir(path): 2755db71995Sopenharmony_ci os.makedirs(path) 2765db71995Sopenharmony_ci 2775db71995Sopenharmony_cidef command_output(cmd, directory): 2785db71995Sopenharmony_ci # Runs a command in a directory and returns its standard output stream. 2795db71995Sopenharmony_ci # Captures the standard error stream and prints it an error occurs. 2805db71995Sopenharmony_ci # Raises a RuntimeError if the command fails to launch or otherwise fails. 2815db71995Sopenharmony_ci if VERBOSE: 2825db71995Sopenharmony_ci print('In {d}: {cmd}'.format(d=directory, cmd=cmd)) 2835db71995Sopenharmony_ci 2845db71995Sopenharmony_ci result = subprocess.run(cmd, cwd=directory, capture_output=True, text=True) 2855db71995Sopenharmony_ci 2865db71995Sopenharmony_ci if result.returncode != 0: 2875db71995Sopenharmony_ci print(f'{result.stderr}', file=sys.stderr) 2885db71995Sopenharmony_ci raise RuntimeError(f'Failed to run {cmd} in {directory}') 2895db71995Sopenharmony_ci 2905db71995Sopenharmony_ci if VERBOSE: 2915db71995Sopenharmony_ci print(result.stdout) 2925db71995Sopenharmony_ci return result.stdout 2935db71995Sopenharmony_ci 2945db71995Sopenharmony_cidef run_cmake_command(cmake_cmd): 2955db71995Sopenharmony_ci # NOTE: Because CMake is an exectuable that runs executables 2965db71995Sopenharmony_ci # stdout/stderr are mixed together. So this combines the outputs 2975db71995Sopenharmony_ci # and prints them properly in case there is a non-zero exit code. 2985db71995Sopenharmony_ci result = subprocess.run(cmake_cmd, 2995db71995Sopenharmony_ci stdout = subprocess.PIPE, 3005db71995Sopenharmony_ci stderr = subprocess.STDOUT, 3015db71995Sopenharmony_ci text = True 3025db71995Sopenharmony_ci ) 3035db71995Sopenharmony_ci 3045db71995Sopenharmony_ci if VERBOSE: 3055db71995Sopenharmony_ci print(result.stdout) 3065db71995Sopenharmony_ci print(f"CMake command: {cmake_cmd} ", flush=True) 3075db71995Sopenharmony_ci 3085db71995Sopenharmony_ci if result.returncode != 0: 3095db71995Sopenharmony_ci print(result.stdout, file=sys.stderr) 3105db71995Sopenharmony_ci sys.exit(result.returncode) 3115db71995Sopenharmony_ci 3125db71995Sopenharmony_cidef escape(path): 3135db71995Sopenharmony_ci return path.replace('\\', '/') 3145db71995Sopenharmony_ci 3155db71995Sopenharmony_ciclass GoodRepo(object): 3165db71995Sopenharmony_ci """Represents a repository at a known-good commit.""" 3175db71995Sopenharmony_ci 3185db71995Sopenharmony_ci def __init__(self, json, args): 3195db71995Sopenharmony_ci """Initializes this good repo object. 3205db71995Sopenharmony_ci 3215db71995Sopenharmony_ci Args: 3225db71995Sopenharmony_ci 'json': A fully populated JSON object describing the repo. 3235db71995Sopenharmony_ci 'args': Results from ArgumentParser 3245db71995Sopenharmony_ci """ 3255db71995Sopenharmony_ci self._json = json 3265db71995Sopenharmony_ci self._args = args 3275db71995Sopenharmony_ci # Required JSON elements 3285db71995Sopenharmony_ci self.name = json['name'] 3295db71995Sopenharmony_ci self.url = json['url'] 3305db71995Sopenharmony_ci self.sub_dir = json['sub_dir'] 3315db71995Sopenharmony_ci self.commit = json['commit'] 3325db71995Sopenharmony_ci # Optional JSON elements 3335db71995Sopenharmony_ci self.build_dir = None 3345db71995Sopenharmony_ci self.install_dir = None 3355db71995Sopenharmony_ci if json.get('build_dir'): 3365db71995Sopenharmony_ci self.build_dir = os.path.normpath(json['build_dir']) 3375db71995Sopenharmony_ci if json.get('install_dir'): 3385db71995Sopenharmony_ci self.install_dir = os.path.normpath(json['install_dir']) 3395db71995Sopenharmony_ci self.deps = json['deps'] if ('deps' in json) else [] 3405db71995Sopenharmony_ci self.prebuild = json['prebuild'] if ('prebuild' in json) else [] 3415db71995Sopenharmony_ci self.prebuild_linux = json['prebuild_linux'] if ( 3425db71995Sopenharmony_ci 'prebuild_linux' in json) else [] 3435db71995Sopenharmony_ci self.prebuild_windows = json['prebuild_windows'] if ( 3445db71995Sopenharmony_ci 'prebuild_windows' in json) else [] 3455db71995Sopenharmony_ci self.custom_build = json['custom_build'] if ('custom_build' in json) else [] 3465db71995Sopenharmony_ci self.cmake_options = json['cmake_options'] if ( 3475db71995Sopenharmony_ci 'cmake_options' in json) else [] 3485db71995Sopenharmony_ci self.ci_only = json['ci_only'] if ('ci_only' in json) else [] 3495db71995Sopenharmony_ci self.build_step = json['build_step'] if ('build_step' in json) else 'build' 3505db71995Sopenharmony_ci self.build_platforms = json['build_platforms'] if ('build_platforms' in json) else [] 3515db71995Sopenharmony_ci self.optional = set(json.get('optional', [])) 3525db71995Sopenharmony_ci self.api = json['api'] if ('api' in json) else None 3535db71995Sopenharmony_ci # Absolute paths for a repo's directories 3545db71995Sopenharmony_ci dir_top = os.path.abspath(args.dir) 3555db71995Sopenharmony_ci self.repo_dir = os.path.join(dir_top, self.sub_dir) 3565db71995Sopenharmony_ci if self.build_dir: 3575db71995Sopenharmony_ci self.build_dir = os.path.join(dir_top, self.build_dir) 3585db71995Sopenharmony_ci if self.install_dir: 3595db71995Sopenharmony_ci self.install_dir = os.path.join(dir_top, self.install_dir) 3605db71995Sopenharmony_ci 3615db71995Sopenharmony_ci # By default the target platform is the host platform. 3625db71995Sopenharmony_ci target_platform = platform.system().lower() 3635db71995Sopenharmony_ci # However, we need to account for cross-compiling. 3645db71995Sopenharmony_ci for cmake_var in self._args.cmake_var: 3655db71995Sopenharmony_ci if "android.toolchain.cmake" in cmake_var: 3665db71995Sopenharmony_ci target_platform = 'android' 3675db71995Sopenharmony_ci 3685db71995Sopenharmony_ci self.on_build_platform = False 3695db71995Sopenharmony_ci if self.build_platforms == [] or target_platform in self.build_platforms: 3705db71995Sopenharmony_ci self.on_build_platform = True 3715db71995Sopenharmony_ci 3725db71995Sopenharmony_ci def Clone(self, retries=10, retry_seconds=60): 3735db71995Sopenharmony_ci if VERBOSE: 3745db71995Sopenharmony_ci print('Cloning {n} into {d}'.format(n=self.name, d=self.repo_dir)) 3755db71995Sopenharmony_ci for retry in range(retries): 3765db71995Sopenharmony_ci make_or_exist_dirs(self.repo_dir) 3775db71995Sopenharmony_ci try: 3785db71995Sopenharmony_ci command_output(['git', 'clone', self.url, '.'], self.repo_dir) 3795db71995Sopenharmony_ci # If we get here, we didn't raise an error 3805db71995Sopenharmony_ci return 3815db71995Sopenharmony_ci except RuntimeError as e: 3825db71995Sopenharmony_ci print("Error cloning on iteration {}/{}: {}".format(retry + 1, retries, e)) 3835db71995Sopenharmony_ci if retry + 1 < retries: 3845db71995Sopenharmony_ci if retry_seconds > 0: 3855db71995Sopenharmony_ci print("Waiting {} seconds before trying again".format(retry_seconds)) 3865db71995Sopenharmony_ci time.sleep(retry_seconds) 3875db71995Sopenharmony_ci if os.path.isdir(self.repo_dir): 3885db71995Sopenharmony_ci print("Removing old tree {}".format(self.repo_dir)) 3895db71995Sopenharmony_ci shutil.rmtree(self.repo_dir, onerror=on_rm_error) 3905db71995Sopenharmony_ci continue 3915db71995Sopenharmony_ci 3925db71995Sopenharmony_ci # If we get here, we've exhausted our retries. 3935db71995Sopenharmony_ci print("Failed to clone {} on all retries.".format(self.url)) 3945db71995Sopenharmony_ci raise e 3955db71995Sopenharmony_ci 3965db71995Sopenharmony_ci def Fetch(self, retries=10, retry_seconds=60): 3975db71995Sopenharmony_ci for retry in range(retries): 3985db71995Sopenharmony_ci try: 3995db71995Sopenharmony_ci command_output(['git', 'fetch', 'origin'], self.repo_dir) 4005db71995Sopenharmony_ci # if we get here, we didn't raise an error, and we're done 4015db71995Sopenharmony_ci return 4025db71995Sopenharmony_ci except RuntimeError as e: 4035db71995Sopenharmony_ci print("Error fetching on iteration {}/{}: {}".format(retry + 1, retries, e)) 4045db71995Sopenharmony_ci if retry + 1 < retries: 4055db71995Sopenharmony_ci if retry_seconds > 0: 4065db71995Sopenharmony_ci print("Waiting {} seconds before trying again".format(retry_seconds)) 4075db71995Sopenharmony_ci time.sleep(retry_seconds) 4085db71995Sopenharmony_ci continue 4095db71995Sopenharmony_ci 4105db71995Sopenharmony_ci # If we get here, we've exhausted our retries. 4115db71995Sopenharmony_ci print("Failed to fetch {} on all retries.".format(self.url)) 4125db71995Sopenharmony_ci raise e 4135db71995Sopenharmony_ci 4145db71995Sopenharmony_ci def Checkout(self): 4155db71995Sopenharmony_ci if VERBOSE: 4165db71995Sopenharmony_ci print('Checking out {n} in {d}'.format(n=self.name, d=self.repo_dir)) 4175db71995Sopenharmony_ci 4185db71995Sopenharmony_ci if self._args.do_clean_repo: 4195db71995Sopenharmony_ci if os.path.isdir(self.repo_dir): 4205db71995Sopenharmony_ci shutil.rmtree(self.repo_dir, onerror = on_rm_error) 4215db71995Sopenharmony_ci if not os.path.exists(os.path.join(self.repo_dir, '.git')): 4225db71995Sopenharmony_ci self.Clone() 4235db71995Sopenharmony_ci self.Fetch() 4245db71995Sopenharmony_ci if len(self._args.ref): 4255db71995Sopenharmony_ci command_output(['git', 'checkout', self._args.ref], self.repo_dir) 4265db71995Sopenharmony_ci else: 4275db71995Sopenharmony_ci command_output(['git', 'checkout', self.commit], self.repo_dir) 4285db71995Sopenharmony_ci 4295db71995Sopenharmony_ci if VERBOSE: 4305db71995Sopenharmony_ci print(command_output(['git', 'status'], self.repo_dir)) 4315db71995Sopenharmony_ci 4325db71995Sopenharmony_ci def CustomPreProcess(self, cmd_str, repo_dict): 4335db71995Sopenharmony_ci return cmd_str.format(repo_dict, self._args, CONFIG_MAP[self._args.config]) 4345db71995Sopenharmony_ci 4355db71995Sopenharmony_ci def PreBuild(self): 4365db71995Sopenharmony_ci """Execute any prebuild steps from the repo root""" 4375db71995Sopenharmony_ci for p in self.prebuild: 4385db71995Sopenharmony_ci command_output(shlex.split(p), self.repo_dir) 4395db71995Sopenharmony_ci if platform.system() == 'Linux' or platform.system() == 'Darwin': 4405db71995Sopenharmony_ci for p in self.prebuild_linux: 4415db71995Sopenharmony_ci command_output(shlex.split(p), self.repo_dir) 4425db71995Sopenharmony_ci if platform.system() == 'Windows': 4435db71995Sopenharmony_ci for p in self.prebuild_windows: 4445db71995Sopenharmony_ci command_output(shlex.split(p), self.repo_dir) 4455db71995Sopenharmony_ci 4465db71995Sopenharmony_ci def CustomBuild(self, repo_dict): 4475db71995Sopenharmony_ci """Execute any custom_build steps from the repo root""" 4485db71995Sopenharmony_ci 4495db71995Sopenharmony_ci # It's not uncommon for builds to not support universal binaries 4505db71995Sopenharmony_ci if self._args.OSX_ARCHITECTURES: 4515db71995Sopenharmony_ci print("Universal Binaries not supported for custom builds", file=sys.stderr) 4525db71995Sopenharmony_ci exit(-1) 4535db71995Sopenharmony_ci 4545db71995Sopenharmony_ci for p in self.custom_build: 4555db71995Sopenharmony_ci cmd = self.CustomPreProcess(p, repo_dict) 4565db71995Sopenharmony_ci command_output(shlex.split(cmd), self.repo_dir) 4575db71995Sopenharmony_ci 4585db71995Sopenharmony_ci def CMakeConfig(self, repos): 4595db71995Sopenharmony_ci """Build CMake command for the configuration phase and execute it""" 4605db71995Sopenharmony_ci if self._args.do_clean_build: 4615db71995Sopenharmony_ci if os.path.isdir(self.build_dir): 4625db71995Sopenharmony_ci shutil.rmtree(self.build_dir, onerror=on_rm_error) 4635db71995Sopenharmony_ci if self._args.do_clean_install: 4645db71995Sopenharmony_ci if os.path.isdir(self.install_dir): 4655db71995Sopenharmony_ci shutil.rmtree(self.install_dir, onerror=on_rm_error) 4665db71995Sopenharmony_ci 4675db71995Sopenharmony_ci # Create and change to build directory 4685db71995Sopenharmony_ci make_or_exist_dirs(self.build_dir) 4695db71995Sopenharmony_ci os.chdir(self.build_dir) 4705db71995Sopenharmony_ci 4715db71995Sopenharmony_ci cmake_cmd = [ 4725db71995Sopenharmony_ci 'cmake', self.repo_dir, 4735db71995Sopenharmony_ci '-DCMAKE_INSTALL_PREFIX=' + self.install_dir 4745db71995Sopenharmony_ci ] 4755db71995Sopenharmony_ci 4765db71995Sopenharmony_ci # Allow users to pass in arbitrary cache variables 4775db71995Sopenharmony_ci for cmake_var in self._args.cmake_var: 4785db71995Sopenharmony_ci pieces = cmake_var.split('=', 1) 4795db71995Sopenharmony_ci cmake_cmd.append('-D{}={}'.format(pieces[0], pieces[1])) 4805db71995Sopenharmony_ci 4815db71995Sopenharmony_ci # For each repo this repo depends on, generate a CMake variable 4825db71995Sopenharmony_ci # definitions for "...INSTALL_DIR" that points to that dependent 4835db71995Sopenharmony_ci # repo's install dir. 4845db71995Sopenharmony_ci for d in self.deps: 4855db71995Sopenharmony_ci dep_commit = [r for r in repos if r.name == d['repo_name']] 4865db71995Sopenharmony_ci if len(dep_commit) and dep_commit[0].on_build_platform: 4875db71995Sopenharmony_ci cmake_cmd.append('-D{var_name}={install_dir}'.format( 4885db71995Sopenharmony_ci var_name=d['var_name'], 4895db71995Sopenharmony_ci install_dir=dep_commit[0].install_dir)) 4905db71995Sopenharmony_ci 4915db71995Sopenharmony_ci # Add any CMake options 4925db71995Sopenharmony_ci for option in self.cmake_options: 4935db71995Sopenharmony_ci cmake_cmd.append(escape(option.format(**self.__dict__))) 4945db71995Sopenharmony_ci 4955db71995Sopenharmony_ci # Set build config for single-configuration generators (this is a no-op on multi-config generators) 4965db71995Sopenharmony_ci cmake_cmd.append(f'-D CMAKE_BUILD_TYPE={CONFIG_MAP[self._args.config]}') 4975db71995Sopenharmony_ci 4985db71995Sopenharmony_ci if self._args.OSX_ARCHITECTURES: 4995db71995Sopenharmony_ci # CMAKE_OSX_ARCHITECTURES must be a semi-colon seperated list 5005db71995Sopenharmony_ci cmake_osx_archs = self._args.OSX_ARCHITECTURES.replace(':', ';') 5015db71995Sopenharmony_ci cmake_cmd.append(f'-D CMAKE_OSX_ARCHITECTURES={cmake_osx_archs}') 5025db71995Sopenharmony_ci 5035db71995Sopenharmony_ci # Use the CMake -A option to select the platform architecture 5045db71995Sopenharmony_ci # without needing a Visual Studio generator. 5055db71995Sopenharmony_ci if platform.system() == 'Windows' and self._args.generator != "Ninja": 5065db71995Sopenharmony_ci if self._args.arch.lower() == '64' or self._args.arch == 'x64' or self._args.arch == 'win64': 5075db71995Sopenharmony_ci cmake_cmd.append('-A') 5085db71995Sopenharmony_ci cmake_cmd.append('x64') 5095db71995Sopenharmony_ci else: 5105db71995Sopenharmony_ci cmake_cmd.append('-A') 5115db71995Sopenharmony_ci cmake_cmd.append('Win32') 5125db71995Sopenharmony_ci 5135db71995Sopenharmony_ci # Apply a generator, if one is specified. This can be used to supply 5145db71995Sopenharmony_ci # a specific generator for the dependent repositories to match 5155db71995Sopenharmony_ci # that of the main repository. 5165db71995Sopenharmony_ci if self._args.generator is not None: 5175db71995Sopenharmony_ci cmake_cmd.extend(['-G', self._args.generator]) 5185db71995Sopenharmony_ci 5195db71995Sopenharmony_ci # Removes warnings related to unused CLI 5205db71995Sopenharmony_ci # EX: Setting CMAKE_CXX_COMPILER for a C project 5215db71995Sopenharmony_ci if not VERBOSE: 5225db71995Sopenharmony_ci cmake_cmd.append("--no-warn-unused-cli") 5235db71995Sopenharmony_ci 5245db71995Sopenharmony_ci run_cmake_command(cmake_cmd) 5255db71995Sopenharmony_ci 5265db71995Sopenharmony_ci def CMakeBuild(self): 5275db71995Sopenharmony_ci """Build CMake command for the build phase and execute it""" 5285db71995Sopenharmony_ci cmake_cmd = ['cmake', '--build', self.build_dir, '--target', 'install', '--config', CONFIG_MAP[self._args.config]] 5295db71995Sopenharmony_ci if self._args.do_clean: 5305db71995Sopenharmony_ci cmake_cmd.append('--clean-first') 5315db71995Sopenharmony_ci 5325db71995Sopenharmony_ci # Xcode / Ninja are parallel by default. 5335db71995Sopenharmony_ci if self._args.generator != "Ninja" or self._args.generator != "Xcode": 5345db71995Sopenharmony_ci cmake_cmd.append('--parallel') 5355db71995Sopenharmony_ci cmake_cmd.append(format(multiprocessing.cpu_count())) 5365db71995Sopenharmony_ci 5375db71995Sopenharmony_ci run_cmake_command(cmake_cmd) 5385db71995Sopenharmony_ci 5395db71995Sopenharmony_ci def Build(self, repos, repo_dict): 5405db71995Sopenharmony_ci """Build the dependent repo and time how long it took""" 5415db71995Sopenharmony_ci if VERBOSE: 5425db71995Sopenharmony_ci print('Building {n} in {d}'.format(n=self.name, d=self.repo_dir)) 5435db71995Sopenharmony_ci print('Build dir = {b}'.format(b=self.build_dir)) 5445db71995Sopenharmony_ci print('Install dir = {i}\n'.format(i=self.install_dir)) 5455db71995Sopenharmony_ci 5465db71995Sopenharmony_ci start = time.time() 5475db71995Sopenharmony_ci 5485db71995Sopenharmony_ci self.PreBuild() 5495db71995Sopenharmony_ci 5505db71995Sopenharmony_ci if self.build_step == 'custom': 5515db71995Sopenharmony_ci self.CustomBuild(repo_dict) 5525db71995Sopenharmony_ci else: 5535db71995Sopenharmony_ci self.CMakeConfig(repos) 5545db71995Sopenharmony_ci self.CMakeBuild() 5555db71995Sopenharmony_ci 5565db71995Sopenharmony_ci total_time = time.time() - start 5575db71995Sopenharmony_ci 5585db71995Sopenharmony_ci print(f"Installed {self.name} ({self.commit}) in {total_time} seconds", flush=True) 5595db71995Sopenharmony_ci 5605db71995Sopenharmony_ci def IsOptional(self, opts): 5615db71995Sopenharmony_ci return len(self.optional.intersection(opts)) > 0 5625db71995Sopenharmony_ci 5635db71995Sopenharmony_cidef GetGoodRepos(args): 5645db71995Sopenharmony_ci """Returns the latest list of GoodRepo objects. 5655db71995Sopenharmony_ci 5665db71995Sopenharmony_ci The known-good file is expected to be in the same 5675db71995Sopenharmony_ci directory as this script unless overridden by the 'known_good_dir' 5685db71995Sopenharmony_ci parameter. 5695db71995Sopenharmony_ci """ 5705db71995Sopenharmony_ci if args.known_good_dir: 5715db71995Sopenharmony_ci known_good_file = os.path.join( os.path.abspath(args.known_good_dir), 5725db71995Sopenharmony_ci KNOWN_GOOD_FILE_NAME) 5735db71995Sopenharmony_ci else: 5745db71995Sopenharmony_ci known_good_file = os.path.join( 5755db71995Sopenharmony_ci os.path.dirname(os.path.abspath(__file__)), KNOWN_GOOD_FILE_NAME) 5765db71995Sopenharmony_ci with open(known_good_file) as known_good: 5775db71995Sopenharmony_ci return [ 5785db71995Sopenharmony_ci GoodRepo(repo, args) 5795db71995Sopenharmony_ci for repo in json.loads(known_good.read())['repos'] 5805db71995Sopenharmony_ci ] 5815db71995Sopenharmony_ci 5825db71995Sopenharmony_ci 5835db71995Sopenharmony_cidef GetInstallNames(args): 5845db71995Sopenharmony_ci """Returns the install names list. 5855db71995Sopenharmony_ci 5865db71995Sopenharmony_ci The known-good file is expected to be in the same 5875db71995Sopenharmony_ci directory as this script unless overridden by the 'known_good_dir' 5885db71995Sopenharmony_ci parameter. 5895db71995Sopenharmony_ci """ 5905db71995Sopenharmony_ci if args.known_good_dir: 5915db71995Sopenharmony_ci known_good_file = os.path.join(os.path.abspath(args.known_good_dir), 5925db71995Sopenharmony_ci KNOWN_GOOD_FILE_NAME) 5935db71995Sopenharmony_ci else: 5945db71995Sopenharmony_ci known_good_file = os.path.join( 5955db71995Sopenharmony_ci os.path.dirname(os.path.abspath(__file__)), KNOWN_GOOD_FILE_NAME) 5965db71995Sopenharmony_ci with open(known_good_file) as known_good: 5975db71995Sopenharmony_ci install_info = json.loads(known_good.read()) 5985db71995Sopenharmony_ci if install_info.get('install_names'): 5995db71995Sopenharmony_ci return install_info['install_names'] 6005db71995Sopenharmony_ci else: 6015db71995Sopenharmony_ci return None 6025db71995Sopenharmony_ci 6035db71995Sopenharmony_ci 6045db71995Sopenharmony_cidef CreateHelper(args, repos, filename): 6055db71995Sopenharmony_ci """Create a CMake config helper file. 6065db71995Sopenharmony_ci 6075db71995Sopenharmony_ci The helper file is intended to be used with 'cmake -C <file>' 6085db71995Sopenharmony_ci to build this home repo using the dependencies built by this script. 6095db71995Sopenharmony_ci 6105db71995Sopenharmony_ci The install_names dictionary represents the CMake variables used by the 6115db71995Sopenharmony_ci home repo to locate the install dirs of the dependent repos. 6125db71995Sopenharmony_ci This information is baked into the CMake files of the home repo and so 6135db71995Sopenharmony_ci this dictionary is kept with the repo via the json file. 6145db71995Sopenharmony_ci """ 6155db71995Sopenharmony_ci install_names = GetInstallNames(args) 6165db71995Sopenharmony_ci with open(filename, 'w') as helper_file: 6175db71995Sopenharmony_ci for repo in repos: 6185db71995Sopenharmony_ci # If the repo has an API tag and that does not match 6195db71995Sopenharmony_ci # the target API then skip it 6205db71995Sopenharmony_ci if repo.api is not None and repo.api != args.api: 6215db71995Sopenharmony_ci continue 6225db71995Sopenharmony_ci if install_names and repo.name in install_names and repo.on_build_platform: 6235db71995Sopenharmony_ci helper_file.write('set({var} "{dir}" CACHE STRING "" FORCE)\n' 6245db71995Sopenharmony_ci .format( 6255db71995Sopenharmony_ci var=install_names[repo.name], 6265db71995Sopenharmony_ci dir=escape(repo.install_dir))) 6275db71995Sopenharmony_ci 6285db71995Sopenharmony_ci 6295db71995Sopenharmony_cidef main(): 6305db71995Sopenharmony_ci parser = argparse.ArgumentParser( 6315db71995Sopenharmony_ci description='Get and build dependent repos at known-good commits') 6325db71995Sopenharmony_ci parser.add_argument( 6335db71995Sopenharmony_ci '--known_good_dir', 6345db71995Sopenharmony_ci dest='known_good_dir', 6355db71995Sopenharmony_ci help="Specify directory for known_good.json file.") 6365db71995Sopenharmony_ci parser.add_argument( 6375db71995Sopenharmony_ci '--dir', 6385db71995Sopenharmony_ci dest='dir', 6395db71995Sopenharmony_ci default='.', 6405db71995Sopenharmony_ci help="Set target directory for repository roots. Default is \'.\'.") 6415db71995Sopenharmony_ci parser.add_argument( 6425db71995Sopenharmony_ci '--ref', 6435db71995Sopenharmony_ci dest='ref', 6445db71995Sopenharmony_ci default='', 6455db71995Sopenharmony_ci help="Override 'commit' with git reference. E.g., 'origin/main'") 6465db71995Sopenharmony_ci parser.add_argument( 6475db71995Sopenharmony_ci '--no-build', 6485db71995Sopenharmony_ci dest='do_build', 6495db71995Sopenharmony_ci action='store_false', 6505db71995Sopenharmony_ci help= 6515db71995Sopenharmony_ci "Clone/update repositories and generate build files without performing compilation", 6525db71995Sopenharmony_ci default=True) 6535db71995Sopenharmony_ci parser.add_argument( 6545db71995Sopenharmony_ci '--clean', 6555db71995Sopenharmony_ci dest='do_clean', 6565db71995Sopenharmony_ci action='store_true', 6575db71995Sopenharmony_ci help="Clean files generated by compiler and linker before building", 6585db71995Sopenharmony_ci default=False) 6595db71995Sopenharmony_ci parser.add_argument( 6605db71995Sopenharmony_ci '--clean-repo', 6615db71995Sopenharmony_ci dest='do_clean_repo', 6625db71995Sopenharmony_ci action='store_true', 6635db71995Sopenharmony_ci help="Delete repository directory before building", 6645db71995Sopenharmony_ci default=False) 6655db71995Sopenharmony_ci parser.add_argument( 6665db71995Sopenharmony_ci '--clean-build', 6675db71995Sopenharmony_ci dest='do_clean_build', 6685db71995Sopenharmony_ci action='store_true', 6695db71995Sopenharmony_ci help="Delete build directory before building", 6705db71995Sopenharmony_ci default=False) 6715db71995Sopenharmony_ci parser.add_argument( 6725db71995Sopenharmony_ci '--clean-install', 6735db71995Sopenharmony_ci dest='do_clean_install', 6745db71995Sopenharmony_ci action='store_true', 6755db71995Sopenharmony_ci help="Delete install directory before building", 6765db71995Sopenharmony_ci default=False) 6775db71995Sopenharmony_ci parser.add_argument( 6785db71995Sopenharmony_ci '--skip-existing-install', 6795db71995Sopenharmony_ci dest='skip_existing_install', 6805db71995Sopenharmony_ci action='store_true', 6815db71995Sopenharmony_ci help="Skip build if install directory exists", 6825db71995Sopenharmony_ci default=False) 6835db71995Sopenharmony_ci parser.add_argument( 6845db71995Sopenharmony_ci '--arch', 6855db71995Sopenharmony_ci dest='arch', 6865db71995Sopenharmony_ci choices=['32', '64', 'x86', 'x64', 'win32', 'win64'], 6875db71995Sopenharmony_ci type=str.lower, 6885db71995Sopenharmony_ci help="Set build files architecture (Visual Studio Generator Only)", 6895db71995Sopenharmony_ci default='64') 6905db71995Sopenharmony_ci parser.add_argument( 6915db71995Sopenharmony_ci '--config', 6925db71995Sopenharmony_ci dest='config', 6935db71995Sopenharmony_ci choices=['debug', 'release', 'relwithdebinfo', 'minsizerel'], 6945db71995Sopenharmony_ci type=str.lower, 6955db71995Sopenharmony_ci help="Set build files configuration", 6965db71995Sopenharmony_ci default='debug') 6975db71995Sopenharmony_ci parser.add_argument( 6985db71995Sopenharmony_ci '--api', 6995db71995Sopenharmony_ci dest='api', 7005db71995Sopenharmony_ci default='vulkan', 7015db71995Sopenharmony_ci choices=['vulkan'], 7025db71995Sopenharmony_ci help="Target API") 7035db71995Sopenharmony_ci parser.add_argument( 7045db71995Sopenharmony_ci '--generator', 7055db71995Sopenharmony_ci dest='generator', 7065db71995Sopenharmony_ci help="Set the CMake generator", 7075db71995Sopenharmony_ci default=None) 7085db71995Sopenharmony_ci parser.add_argument( 7095db71995Sopenharmony_ci '--optional', 7105db71995Sopenharmony_ci dest='optional', 7115db71995Sopenharmony_ci type=lambda a: set(a.lower().split(',')), 7125db71995Sopenharmony_ci help="Comma-separated list of 'optional' resources that may be skipped. Only 'tests' is currently supported as 'optional'", 7135db71995Sopenharmony_ci default=set()) 7145db71995Sopenharmony_ci parser.add_argument( 7155db71995Sopenharmony_ci '--cmake_var', 7165db71995Sopenharmony_ci dest='cmake_var', 7175db71995Sopenharmony_ci action='append', 7185db71995Sopenharmony_ci metavar='VAR[=VALUE]', 7195db71995Sopenharmony_ci help="Add CMake command line option -D'VAR'='VALUE' to the CMake generation command line; may be used multiple times", 7205db71995Sopenharmony_ci default=[]) 7215db71995Sopenharmony_ci parser.add_argument( 7225db71995Sopenharmony_ci '--osx-archs', 7235db71995Sopenharmony_ci dest='OSX_ARCHITECTURES', 7245db71995Sopenharmony_ci help="Architectures when building a universal binary. Takes a colon seperated list. Ex: arm64:x86_64", 7255db71995Sopenharmony_ci type=str, 7265db71995Sopenharmony_ci default=None) 7275db71995Sopenharmony_ci 7285db71995Sopenharmony_ci args = parser.parse_args() 7295db71995Sopenharmony_ci save_cwd = os.getcwd() 7305db71995Sopenharmony_ci 7315db71995Sopenharmony_ci if args.OSX_ARCHITECTURES: 7325db71995Sopenharmony_ci print(f"Building dependencies as universal binaries targeting {args.OSX_ARCHITECTURES}") 7335db71995Sopenharmony_ci 7345db71995Sopenharmony_ci # Create working "top" directory if needed 7355db71995Sopenharmony_ci make_or_exist_dirs(args.dir) 7365db71995Sopenharmony_ci abs_top_dir = os.path.abspath(args.dir) 7375db71995Sopenharmony_ci 7385db71995Sopenharmony_ci repos = GetGoodRepos(args) 7395db71995Sopenharmony_ci repo_dict = {} 7405db71995Sopenharmony_ci 7415db71995Sopenharmony_ci print('Starting builds in {d}'.format(d=abs_top_dir)) 7425db71995Sopenharmony_ci for repo in repos: 7435db71995Sopenharmony_ci # If the repo has an API tag and that does not match 7445db71995Sopenharmony_ci # the target API then skip it 7455db71995Sopenharmony_ci if repo.api is not None and repo.api != args.api: 7465db71995Sopenharmony_ci continue 7475db71995Sopenharmony_ci 7485db71995Sopenharmony_ci # If the repo has a platform whitelist, skip the repo 7495db71995Sopenharmony_ci # unless we are building on a whitelisted platform. 7505db71995Sopenharmony_ci if not repo.on_build_platform: 7515db71995Sopenharmony_ci continue 7525db71995Sopenharmony_ci 7535db71995Sopenharmony_ci # Skip building the repo if its install directory already exists 7545db71995Sopenharmony_ci # and requested via an option. This is useful for cases where the 7555db71995Sopenharmony_ci # install directory is restored from a cache that is known to be up 7565db71995Sopenharmony_ci # to date. 7575db71995Sopenharmony_ci if args.skip_existing_install and os.path.isdir(repo.install_dir): 7585db71995Sopenharmony_ci print('Skipping build for repo {n} due to existing install directory'.format(n=repo.name)) 7595db71995Sopenharmony_ci continue 7605db71995Sopenharmony_ci 7615db71995Sopenharmony_ci # Skip test-only repos if the --tests option was not passed in 7625db71995Sopenharmony_ci if repo.IsOptional(args.optional): 7635db71995Sopenharmony_ci continue 7645db71995Sopenharmony_ci 7655db71995Sopenharmony_ci field_list = ('url', 7665db71995Sopenharmony_ci 'sub_dir', 7675db71995Sopenharmony_ci 'commit', 7685db71995Sopenharmony_ci 'build_dir', 7695db71995Sopenharmony_ci 'install_dir', 7705db71995Sopenharmony_ci 'deps', 7715db71995Sopenharmony_ci 'prebuild', 7725db71995Sopenharmony_ci 'prebuild_linux', 7735db71995Sopenharmony_ci 'prebuild_windows', 7745db71995Sopenharmony_ci 'custom_build', 7755db71995Sopenharmony_ci 'cmake_options', 7765db71995Sopenharmony_ci 'ci_only', 7775db71995Sopenharmony_ci 'build_step', 7785db71995Sopenharmony_ci 'build_platforms', 7795db71995Sopenharmony_ci 'repo_dir', 7805db71995Sopenharmony_ci 'on_build_platform') 7815db71995Sopenharmony_ci repo_dict[repo.name] = {field: getattr(repo, field) for field in field_list} 7825db71995Sopenharmony_ci 7835db71995Sopenharmony_ci # If the repo has a CI whitelist, skip the repo unless 7845db71995Sopenharmony_ci # one of the CI's environment variable is set to true. 7855db71995Sopenharmony_ci if len(repo.ci_only): 7865db71995Sopenharmony_ci do_build = False 7875db71995Sopenharmony_ci for env in repo.ci_only: 7885db71995Sopenharmony_ci if env not in os.environ: 7895db71995Sopenharmony_ci continue 7905db71995Sopenharmony_ci if os.environ[env].lower() == 'true': 7915db71995Sopenharmony_ci do_build = True 7925db71995Sopenharmony_ci break 7935db71995Sopenharmony_ci if not do_build: 7945db71995Sopenharmony_ci continue 7955db71995Sopenharmony_ci 7965db71995Sopenharmony_ci # Clone/update the repository 7975db71995Sopenharmony_ci repo.Checkout() 7985db71995Sopenharmony_ci 7995db71995Sopenharmony_ci # Build the repository 8005db71995Sopenharmony_ci if args.do_build and repo.build_step != 'skip': 8015db71995Sopenharmony_ci repo.Build(repos, repo_dict) 8025db71995Sopenharmony_ci 8035db71995Sopenharmony_ci # Need to restore original cwd in order for CreateHelper to find json file 8045db71995Sopenharmony_ci os.chdir(save_cwd) 8055db71995Sopenharmony_ci CreateHelper(args, repos, os.path.join(abs_top_dir, 'helper.cmake')) 8065db71995Sopenharmony_ci 8075db71995Sopenharmony_ci sys.exit(0) 8085db71995Sopenharmony_ci 8095db71995Sopenharmony_ci 8105db71995Sopenharmony_ciif __name__ == '__main__': 8115db71995Sopenharmony_ci main() 8125db71995Sopenharmony_ci 813