diff options
| author | Stefan Boberg <[email protected]> | 2021-09-03 16:45:48 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-09-03 16:45:48 +0200 |
| commit | caad16df658eda6dbf2c891c7b055ab08c4f226a (patch) | |
| tree | 0fa416cffa2c422a53d4ae0087e57f89f315bc92 /scripts | |
| parent | Suppressed another clang warning involving unreferenced local variable (diff) | |
| download | zen-caad16df658eda6dbf2c891c7b055ab08c4f226a.tar.xz zen-caad16df658eda6dbf2c891c7b055ab08c4f226a.zip | |
Improvements to build deploy scripts
Deploybuild script now builds code first
Jazzed up terminal output
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/deploybuild.py | 31 | ||||
| -rw-r--r-- | scripts/vswhere.py | 317 |
2 files changed, 341 insertions, 7 deletions
diff --git a/scripts/deploybuild.py b/scripts/deploybuild.py index 1062f8b2e..1d9d5d839 100644 --- a/scripts/deploybuild.py +++ b/scripts/deploybuild.py @@ -4,9 +4,14 @@ import os import fileinput import colorama import shutil +import vswhere +import subprocess from peafour import P4 from colorama import Fore, Back, Style +def jazz_print(tag, detail = ""): + print(f"{Fore.WHITE}{Style.BRIGHT}||> {tag}{Style.RESET_ALL} {detail}") + colorama.init() origcwd = os.getcwd() @@ -31,10 +36,20 @@ zenroot = __file__ while not os.path.exists(os.path.join(zenroot, "zen.sln")): zenroot = os.path.dirname(zenroot) -print(f"Zen root: {zenroot}") +jazz_print("Zen root:", zenroot) + +# Build fresh binaries + +vs_path = vswhere.get_latest_path() # can also specify prerelease=True +jazz_print("BUILDING CODE", f"using VS root: {vs_path}") +devenv_path = os.path.join(vs_path, "Common7\\IDE\\devenv.com") + +subprocess.run([devenv_path, "/build", "Release", "zen.sln"]) # Upload symbols etc to Sentry +jazz_print("Uploading symbols", "to Sentry") +subprocess.run(["scripts\sentry-cli.exe", "upload-dif", "--org", "to", "--project", "zen-server", "x64\\Release\\zenserver.exe", "x64\\Release\\zenserver.pdb"]) # scripts\sentry-cli.exe upload-dif --org to --project zen-server x64\Release\zenserver.exe x64\Release\zenserver.pdb # Change into root directory to pick up Perforce environment @@ -49,7 +64,7 @@ if not os.path.samefile(p4info.clientRoot, engineroot): # check out the binaries -print(f"Reverting any previous unsubmitted deploy") +jazz_print("Reverting", "any previous unsubmitted deploy") try: P4.revert("Engine/Binaries/Win64/zenserver.*").run() @@ -57,7 +72,7 @@ try: except: pass -print(f"Checking out zenserver executables") +jazz_print("Checking out", "zenserver executables") try: P4.edit("Engine/Binaries/Win64/zenserver.*").run() @@ -65,16 +80,18 @@ try: except: pass -print(f"Placing zenserver executables into tree") +bin_dir = os.path.join(engineroot, "Engine\\Binaries\\Win64") + +jazz_print("Placing zenserver", f"executables into tree at '{bin_dir}'") crashpadtarget = os.path.join(engineroot, "Engine/Binaries/Win64/crashpad_handler.exe") try: - shutil.copy(os.path.join(zenroot, "x64\Release\zenserver.exe"), os.path.join(engineroot, "Engine/Binaries/Win64/zenserver.exe")) - shutil.copy(os.path.join(zenroot, "x64\Release\zenserver.pdb"), os.path.join(engineroot, "Engine/Binaries/Win64/zenserver.pdb")) + shutil.copy(os.path.join(zenroot, "x64\Release\zenserver.exe"), os.path.join(bin_dir, "zenserver.exe")) + shutil.copy(os.path.join(zenroot, "x64\Release\zenserver.pdb"), os.path.join(bin_dir, "zenserver.pdb")) shutil.copy(os.path.join(zenroot, r'vcpkg_installed\x64-windows-static\tools\sentry-native\crashpad_handler.exe'), crashpadtarget) P4.add(crashpadtarget).run() - print("All done and good!") + jazz_print("All done and good!") except Exception as e: print(f"Noooooo: {e.args}") pass diff --git a/scripts/vswhere.py b/scripts/vswhere.py new file mode 100644 index 000000000..82b0723f9 --- /dev/null +++ b/scripts/vswhere.py @@ -0,0 +1,317 @@ +r""" +Interface to Microsoft's Visual Studio locator tool, vswhere. + +If Visual Studio 15.2 or later has been installed, this will use the vswhere +binary installed with Visual Studio. Otherwise, it will download the latest +release of vswhere from https://github.com/Microsoft/vswhere the first time a +function is called. +""" + +import json +import os +import shutil +import subprocess + +__version__ = '1.3.0' +__author__ = 'Joel Spadin' +__license__ = 'MIT' + +LATEST_RELEASE_ENDPOINT = 'https://api.github.com/repos/Microsoft/vswhere/releases/latest' +DOWNLOAD_PATH = os.path.join(os.path.dirname(__file__), 'vswhere.exe') + +if 'ProgramFiles(x86)' in os.environ: + DEFAULT_PATH = os.path.join(os.environ['ProgramFiles(x86)'], 'Microsoft Visual Studio', 'Installer', 'vswhere.exe') +else: + DEFAULT_PATH = None + +alternate_path = None +download_mirror_url = None + + +def execute(args): + """ + Call vswhere with the given arguments and return an array of results. + + `args` is a list of command line arguments to pass to vswhere. + + If the argument list contains '-property', this returns an array with the + property value for each result. Otherwise, this returns an array of + dictionaries containing the results. + """ + is_property = '-property' in args + + args = [get_vswhere_path(), '-utf8'] + args + + if not is_property: + args.extend(['-format', 'json']) + + output = subprocess.check_output(args).decode('utf-8') + + if is_property: + return output.splitlines() + else: + return json.loads(output) + + +def find( + find=None, + find_all=False, + latest=False, + legacy=False, + path=None, + prerelease=False, + products=None, + prop=None, + requires=None, + requires_any=False, + sort=False, + version=None, +): + """ + Call vswhere and return an array of the results. + + Selection Options: + find_all: If True, finds all instances even if they are incomplete and + may not launch. + prerelease: If True, also searches prereleases. By default, only + releases are searched. + products: a product ID or list of one or more product IDs to find. + Defaults to Community, Professional, and Enterprise if not specified. + Specify '*' by itself to search all product instances installed. + See https://aka.ms/vs/workloads for a list of product IDs. + requires: a workload component ID or list of one or more IDs required + when finding instances. All specified IDs must be installed unless + `requires_any` is True. See https://aka.ms/vs/workloads for a list + of workload and component IDs. + requires_any: If True, find instances with any one or more workload or + component IDs passed to `requires`. + version: A version range for instances to find. Example: '[15.0,16.0)' + will find versions 15.*. + latest: If True, returns only the newest version and last installed. + legacy: If True, also searches Visual Studio 2015 and older products. + Information is limited. This option cannot be used with either + `products` or `requires`. + path: Gets the instance for the given file path. Not compatible with any + other selection option. + + Output Options: + sort: If True, sorts the instances from newest version and last installed + to oldest. When used with `find`, first instances are sorted, then + files are sorted lexigraphically. + prop: The name of a property to return instead of the full installation + details. Use delimiters '.', '/', or '_' to separate object and + property names. Example: 'properties.nickname' will return the + 'nickname' property under 'properties'. + find: Returns the file paths matching this glob pattern under the + installation path. The following patterns are supported: + ? Matches any one character except "\\" + * Matches zero or more characters except "\\" + ** Searches the current directory and subdirectories for the + remaining search pattern. + """ + args = [] + + if find: + args.append('-find') + args.append(find) + + if find_all: + args.append('-all') + + if latest: + args.append('-latest') + + if legacy: + args.append('-legacy') + + if path: + args.append('-path') + args.append(path) + + if prerelease: + args.append('-prerelease') + + if products: + args.append('-products') + _extend_or_append(args, products) + + if prop: + args.append('-property') + args.append(prop) + + if requires: + args.append('-requires') + _extend_or_append(args, requires) + + if requires_any: + args.append('-requiresAny') + + if sort: + args.append('-sort') + + if version: + args.append('-version') + args.append(version) + + return execute(args) + + +def find_first(**kwargs): + """ + Call vswhere and returns only the first result, or None if there are no results. + + See find() for keyword arguments. + """ + return next(iter(find(**kwargs)), None) + + +def get_latest(legacy=None, **kwargs): + """ + Get the information for the latest installed version of Visual Studio. + + Also supports the same selection options as find(), for example to select + different products. If the `legacy` argument is not set, it defaults to + `True` unless either `products` or `requires` arguments are set. + """ + legacy = _get_legacy_arg(legacy, **kwargs) + return find_first(latest=True, legacy=legacy, **kwargs) + + +def get_latest_path(legacy=None, **kwargs): + """ + Get the file path to the latest installed version of Visual Studio. + + Returns None if no installations could be found. + + Also supports the same selection options as find(), for example to select + different products. If the `legacy` argument is not set, it defaults to + `True` unless either `products` or `requires` arguments are set. + """ + legacy = _get_legacy_arg(legacy, **kwargs) + return find_first(latest=True, legacy=legacy, prop='installationPath', **kwargs) + + +def get_latest_version(legacy=None, **kwargs): + """ + Get the version string of the latest installed version of Visual Studio. + + For Visual Studio 2017 and newer, this is the full version number, for + example: '15.8.28010.2003'. + + For Visual Studio 2015 and older, this only contains the major version, with + the minor version set to 0, for example: '14.0'. + + Returns None if no installations could be found. + + Also supports the same selection options as find(), for example to select + different products. If the `legacy` argument is not set, it defaults to + `True` unless either `products` or `requires` arguments are set. + """ + legacy = _get_legacy_arg(legacy, **kwargs) + return find_first(latest=True, legacy=legacy, prop='installationVersion', **kwargs) + +def get_latest_major_version(**kwargs): + """ + Get the major version of the latest installed version of Visual Studio as an int. + + Returns 0 if no installations could be found. + + Also supports the same selection options as find(), for example to select + different products. If the `legacy` argument is not set, it defaults to + `True` unless either `products` or `requires` arguments are set. + """ + return int(next(iter(get_latest_version(**kwargs).split('.')), '0')) + + +def get_vswhere_path(): + """ + Get the path to vshwere.exe. + + If vswhere is not already installed as part of Visual Studio, and no + alternate path is given using `set_vswhere_path()`, the latest release will + be downloaded and stored alongside this script. + """ + if alternate_path and os.path.exists(alternate_path): + return alternate_path + + if DEFAULT_PATH and os.path.exists(DEFAULT_PATH): + return DEFAULT_PATH + + if os.path.exists(DOWNLOAD_PATH): + return DOWNLOAD_PATH + + _download_vswhere() + return DOWNLOAD_PATH + + +def set_vswhere_path(path): + """ + Set the path to vswhere.exe. + + If this is set, it overrides any version installed as part of Visual Studio. + """ + global alternate_path + alternate_path = path + + +def set_download_mirror(url): + """ + Set a URL from which vswhere.exe should be downloaded if it is not already + installed as part of Visual Studio and no alternate path is given using + `set_vswhere_path()`. + """ + global download_mirror_url + download_mirror_url = url + + +def _extend_or_append(lst, value): + if isinstance(value, str): + lst.append(value) + else: + lst.extend(value) + + +def _get_legacy_arg(legacy, **kwargs): + if legacy is None: + return 'products' not in kwargs and 'requires' not in kwargs + else: + return legacy + + +def _download_vswhere(): + """ + Download vswhere to DOWNLOAD_PATH. + """ + print('downloading from', _get_latest_release_url()) + try: + from urllib.request import urlopen + with urlopen(_get_latest_release_url()) as response, open(DOWNLOAD_PATH, 'wb') as outfile: + shutil.copyfileobj(response, outfile) + except ImportError: + # Python 2 + import urllib + urllib.urlretrieve(_get_latest_release_url(), DOWNLOAD_PATH) + + +def _get_latest_release_url(): + """ + The the URL of the latest release of vswhere. + """ + if download_mirror_url: + return download_mirror_url + + try: + from urllib.request import urlopen + with urlopen(LATEST_RELEASE_ENDPOINT) as response: + release = json.loads(response.read(), encoding=response.headers.get_content_charset() or 'utf-8') + except ImportError: + # Python 2 + import urllib2 + response = urllib2.urlopen(LATEST_RELEASE_ENDPOINT) + release = json.loads(response.read(), encoding=response.headers.getparam('charset') or 'utf-8') + + for asset in release['assets']: + if asset['name'] == 'vswhere.exe': + return asset['browser_download_url'] + + raise Exception('Could not locate the latest release of vswhere.')
\ No newline at end of file |