diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2021-09-30 11:54:43 -0400 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2021-10-10 23:15:18 +0300 |
commit | 928078982c8643bffd95a8da06a1b4494fe87e2b (patch) | |
tree | 1e8e50892e5f329927d9196cea85e66801c1af03 /mesonbuild/mesonlib/vsenv.py | |
parent | 31bea202c9dc9d288d787f0073f0e221971669ba (diff) | |
download | meson-928078982c8643bffd95a8da06a1b4494fe87e2b.zip meson-928078982c8643bffd95a8da06a1b4494fe87e2b.tar.gz meson-928078982c8643bffd95a8da06a1b4494fe87e2b.tar.bz2 |
Add --vsenv command line option and active VS only when needed
Diffstat (limited to 'mesonbuild/mesonlib/vsenv.py')
-rw-r--r-- | mesonbuild/mesonlib/vsenv.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/mesonbuild/mesonlib/vsenv.py b/mesonbuild/mesonlib/vsenv.py new file mode 100644 index 0000000..1966634 --- /dev/null +++ b/mesonbuild/mesonlib/vsenv.py @@ -0,0 +1,100 @@ +import os +import subprocess +import json +import pathlib +import shutil +import tempfile + +from .. import mlog +from .universal import MesonException, is_windows + + +bat_template = '''@ECHO OFF + +call "{}" + +ECHO {} +SET +''' + +# If on Windows and VS is installed but not set up in the environment, +# set it to be runnable. In this way Meson can be directly invoked +# from any shell, VS Code etc. +def _setup_vsenv(force: bool) -> bool: + if not is_windows(): + return False + if os.environ.get('OSTYPE') == 'cygwin': + return False + if 'Visual Studio' in os.environ['PATH']: + return False + # VSINSTALL is set when running setvars from a Visual Studio installation + # Tested with Visual Studio 2012 and 2017 + if 'VSINSTALLDIR' in os.environ: + return False + # Check explicitly for cl when on Windows + if shutil.which('cl.exe'): + return False + if not force: + if shutil.which('cc'): + return False + if shutil.which('gcc'): + return False + if shutil.which('clang'): + return False + if shutil.which('clang-cl'): + return False + + root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles") + bat_locator_bin = pathlib.Path(root, 'Microsoft Visual Studio/Installer/vswhere.exe') + if not bat_locator_bin.exists(): + raise MesonException(f'Could not find {bat_locator_bin}') + bat_json = subprocess.check_output( + [ + str(bat_locator_bin), + '-latest', + '-prerelease', + '-requiresAny', + '-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + '-products', '*', + '-utf8', + '-format', + 'json' + ] + ) + bat_info = json.loads(bat_json) + if not bat_info: + # VS installer instelled but not VS itself maybe? + raise MesonException(f'Could not parse vswhere.exe output') + bat_root = pathlib.Path(bat_info[0]['installationPath']) + bat_path = bat_root / 'VC/Auxiliary/Build/vcvars64.bat' + if not bat_path.exists(): + raise MesonException(f'Could not find {bat_path}') + + mlog.log('Activating VS', bat_info[0]['catalog']['productDisplayVersion']) + bat_separator = '---SPLIT---' + bat_contents = bat_template.format(bat_path, bat_separator) + bat_file = tempfile.NamedTemporaryFile('w', suffix='.bat', encoding='utf-8') + bat_file.write(bat_contents) + bat_file.flush() + bat_output = subprocess.check_output(str(bat_file), universal_newlines=True) + bat_lines = bat_output.split('\n') + bat_separator_seen = False + for bat_line in bat_lines: + if bat_line == bat_separator: + bat_separator_seen = True + continue + if not bat_separator_seen: + continue + if not bat_line: + continue + k, v = bat_line.split('=', 1) + os.environ[k] = v + return True + +def setup_vsenv(force: bool = False): + try: + _setup_vsenv(force) + except MesonException: + if force: + raise + mlog.warning('Failed to activate VS environment:', str(e)) |