diff options
-rw-r--r-- | mesonbuild/mesonlib.py | 34 | ||||
-rw-r--r-- | mesonbuild/mtest.py | 20 | ||||
-rw-r--r-- | mesonbuild/scripts/meson_exe.py | 12 |
3 files changed, 48 insertions, 18 deletions
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index bf87f0f..1333027 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -22,6 +22,7 @@ import collections from enum import Enum from functools import lru_cache import typing +import uuid from mesonbuild import mlog @@ -1375,3 +1376,36 @@ try: super().__init__(*args, **kwargs) except ImportError: ProgressBar = ProgressBarFallback + + +def get_wine_shortpath(winecmd, wine_paths): + + """ Get A short version of @wine_paths to avoid + reaching WINEPATH number of char limit. + """ + + seen = set() + wine_paths = [p for p in wine_paths if not (p in seen or seen.add(p))] + + getShortPathScript = '%s.bat' % str(uuid.uuid4()).lower()[:5] + with open(getShortPathScript, mode='w') as f: + f.write("@ECHO OFF\nfor %%x in (%*) do (\n echo|set /p=;%~sx\n)\n") + f.flush() + try: + with open(os.devnull, 'w') as stderr: + wine_path = subprocess.check_output( + winecmd + + ['cmd', '/C', getShortPathScript] + wine_paths, + stderr=stderr).decode('utf-8') + except subprocess.CalledProcessError as e: + print("Could not get short paths: %s" % e) + wine_path = ';'.join(wine_paths) + finally: + os.remove(getShortPathScript) + if len(wine_path) > 2048: + raise MesonException( + 'WINEPATH size {} > 2048' + ' this will cause random failure.'.format( + len(wine_path))) + + return wine_path.strip(';') diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index dc5c9d1..e11c8e4 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -41,7 +41,7 @@ from . import build from . import environment from . import mlog from .dependencies import ExternalProgram -from .mesonlib import substring_is_in_list, MesonException +from .mesonlib import MesonException, get_wine_shortpath if typing.TYPE_CHECKING: from .backend.backends import TestSerialisation @@ -488,15 +488,15 @@ class SingleTestRunner: if len(self.test.extra_paths) > 0: self.env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + self.env['PATH'] - if substring_is_in_list('wine', cmd): - wine_paths = ['Z:' + p for p in self.test.extra_paths] - wine_path = ';'.join(wine_paths) - # Don't accidentally end with an `;` because that will add the - # current directory and might cause unexpected behaviour - if 'WINEPATH' in self.env: - self.env['WINEPATH'] = wine_path + ';' + self.env['WINEPATH'] - else: - self.env['WINEPATH'] = wine_path + winecmd = [] + for c in cmd: + winecmd.append(c) + if os.path.basename(c).startswith('wine'): + self.env['WINEPATH'] = get_wine_shortpath( + winecmd, + ['Z:' + p for p in self.test.extra_paths] + self.env.get('WINEPATH', '').split(';') + ) + break # If MALLOC_PERTURB_ is not set, or if it is set to an empty value, # (i.e., the test or the environment don't explicitly set it), set diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index 8b34448..a5acb22 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -52,14 +52,10 @@ def run_exe(exe): child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) + child_env['PATH']) if exe.exe_runner and mesonlib.substring_is_in_list('wine', exe.exe_runner.get_command()): - wine_paths = ['Z:' + p for p in exe.extra_paths] - wine_path = ';'.join(wine_paths) - # Don't accidentally end with an `;` because that will add the - # current directory and might cause unexpected behaviour - if 'WINEPATH' in child_env: - child_env['WINEPATH'] = wine_path + ';' + child_env['WINEPATH'] - else: - child_env['WINEPATH'] = wine_path + child_env['WINEPATH'] = mesonlib.get_wine_shortpath( + exe.exe_runner.get_command(), + ['Z:' + p for p in exe.extra_paths] + child_env.get('WINEPATH', '').split(';') + ) p = subprocess.Popen(cmd_args, env=child_env, cwd=exe.workdir, close_fds=False, |