|
|
|
@ -5,8 +5,6 @@ import subprocess |
|
|
|
|
import json |
|
|
|
|
import pathlib |
|
|
|
|
import shutil |
|
|
|
|
import tempfile |
|
|
|
|
import locale |
|
|
|
|
|
|
|
|
|
from .. import mlog |
|
|
|
|
from .core import MesonException |
|
|
|
@ -18,14 +16,6 @@ __all__ = [ |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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. |
|
|
|
@ -88,43 +78,41 @@ def _setup_vsenv(force: bool) -> bool: |
|
|
|
|
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', delete=False) |
|
|
|
|
bat_file.write(bat_contents) |
|
|
|
|
bat_file.flush() |
|
|
|
|
bat_file.close() |
|
|
|
|
bat_output = subprocess.check_output(bat_file.name, universal_newlines=True, |
|
|
|
|
encoding=locale.getpreferredencoding(False)) |
|
|
|
|
os.unlink(bat_file.name) |
|
|
|
|
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 |
|
|
|
|
parts = bat_line.split('=', 1) |
|
|
|
|
if len(parts) != 2: |
|
|
|
|
continue |
|
|
|
|
k, v = parts |
|
|
|
|
# Some CI's include variables containing the issue description, like |
|
|
|
|
# GitLab's CI_MERGE_REQUEST_DESCRIPTION. The description itself can |
|
|
|
|
# have multiple lines and any kind of content. |
|
|
|
|
# If one of these lines is '=========', it will leave k empty |
|
|
|
|
# when it's split by '=' |
|
|
|
|
if k is None or v is None: |
|
|
|
|
continue |
|
|
|
|
try: |
|
|
|
|
os.environ[k] = v |
|
|
|
|
except ValueError: |
|
|
|
|
# Ignore errors from junk data returning invalid environment variable names |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
before_separator = '---BEFORE---' |
|
|
|
|
after_separator = '---AFTER---' |
|
|
|
|
# This will print to stdout the env variables set before the VS |
|
|
|
|
# activation and after VS activation so that we can process only |
|
|
|
|
# newly created environment variables. This is required to correctly parse |
|
|
|
|
# environment variables taking into account that some variables |
|
|
|
|
# can have multiple lines. (https://github.com/mesonbuild/meson/pull/13682) |
|
|
|
|
cmd = f'set&& echo {before_separator}&&"{bat_path.absolute()}" && echo {after_separator}&& set' |
|
|
|
|
process = subprocess.Popen( |
|
|
|
|
f'cmd.exe /c "{cmd}"', |
|
|
|
|
stdout=subprocess.PIPE, |
|
|
|
|
stderr=subprocess.PIPE, |
|
|
|
|
shell=True, |
|
|
|
|
) |
|
|
|
|
stdout, stderr = process.communicate() |
|
|
|
|
if process.returncode != 0: |
|
|
|
|
raise RuntimeError(f"Script failed with error: {stderr.decode()}") |
|
|
|
|
lines = stdout.decode().splitlines() |
|
|
|
|
|
|
|
|
|
# Remove the output from the vcvars script |
|
|
|
|
try: |
|
|
|
|
lines_before = lines[:lines.index(before_separator)] |
|
|
|
|
lines_after = lines[lines.index(after_separator) + 1:] |
|
|
|
|
except ValueError: |
|
|
|
|
raise MesonException('Could not find separators in environment variables output') |
|
|
|
|
|
|
|
|
|
# Filter out duplicated lines to remove env variables that haven't changed |
|
|
|
|
new_lines = set(lines_before) - set(lines_after) |
|
|
|
|
for line in new_lines: |
|
|
|
|
k, v = line.split('=', 1) |
|
|
|
|
os.environ[k] = v |
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def setup_vsenv(force: bool = False) -> bool: |
|
|
|
|
try: |
|
|
|
|
return _setup_vsenv(force) |
|
|
|
|