wine: Try to get the short paths when generating WINEPATH

The size of WINEPATH is limited (1024 [until recently]), we
can very easily reach that limit, and even the new one (2048) so
try to keep path as small as possible by using the shortPath
version of paths.

Also assert that we do not reach the new hard limit.

And avoid having duplicates in the list of path.

[until recently]: https://bugs.winehq.org/show_bug.cgi?id=45810
pull/5756/head
Thibault Saunier 6 years ago
parent e3b21de563
commit 42c5e4fe2b
  1. 34
      mesonbuild/mesonlib.py
  2. 20
      mesonbuild/mtest.py
  3. 12
      mesonbuild/scripts/meson_exe.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(';')

@ -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

@ -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,

Loading…
Cancel
Save