parent
31bea202c9
commit
928078982c
14 changed files with 150 additions and 115 deletions
@ -0,0 +1,14 @@ |
||||
## Force Visual Studio environment activation |
||||
|
||||
Since `0.59.0`, meson automatically activates Visual Studio environment on Windows |
||||
for all its subcommands, but only if no other compilers (e.g. `gcc` or `clang`) |
||||
are found, and silently continue if Visual Studio activation fails. |
||||
|
||||
`meson setup --vsenv` command line argument can now be used to force Visual Studio |
||||
activation even when other compilers are found. It also make Meson abort with an |
||||
error message when activation fails. This is especially useful for Github Action |
||||
because their Windows images have gcc in their PATH by default. |
||||
|
||||
`--vsenv` is set by default when using `vs` backend. |
||||
|
||||
Only `setup`, `compile`, `dist` and `devenv` subcommands now activate Visual Studio. |
@ -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)) |
Loading…
Reference in new issue