diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2022-04-20 15:17:51 -0400 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2022-05-06 23:04:11 +0300 |
commit | f9200ca8f7429d614dcb8c4144269461c6a7d9d9 (patch) | |
tree | 192030b5e3d301e3a5be272ecfd2e4ca2ab1b267 | |
parent | 1e4d4fce2250ab415964ad89c1d8b2c649b0b00d (diff) | |
download | meson-f9200ca8f7429d614dcb8c4144269461c6a7d9d9.zip meson-f9200ca8f7429d614dcb8c4144269461c6a7d9d9.tar.gz meson-f9200ca8f7429d614dcb8c4144269461c6a7d9d9.tar.bz2 |
devenv: Set WINEPATH when cross compiling for Windows
-rw-r--r-- | docs/markdown/Commands.md | 6 | ||||
-rw-r--r-- | docs/markdown/snippets/devenv_winepath.md | 4 | ||||
-rw-r--r-- | mesonbuild/backend/backends.py | 18 | ||||
-rw-r--r-- | mesonbuild/mdevenv.py | 52 |
4 files changed, 74 insertions, 6 deletions
diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index b137166..762cd2f 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -351,4 +351,10 @@ top build directory, that file is loaded by gdb automatically. In the case of python scripts that needs to load other python modules, `PYTHONPATH` may need to be modified using `meson.add_devenv()`. +Since *Since 0.63.0* when cross compiling for Windows `WINEPATH` is used instead +of `PATH` which allows running Windows executables using wine. Note that since +`WINEPATH` size is currently limited to 1024 characters, paths relative to the +root of build directory are used. That means current workdir must be the root of +build directory when running wine. + {{ devenv_arguments.inc }} diff --git a/docs/markdown/snippets/devenv_winepath.md b/docs/markdown/snippets/devenv_winepath.md new file mode 100644 index 0000000..b9e24a0 --- /dev/null +++ b/docs/markdown/snippets/devenv_winepath.md @@ -0,0 +1,4 @@ +## Running Windows executables with Wine in `meson devenv` + +When cross compiling for Windows, `meson devenv` now sets `WINEPATH` pointing to +all directories containing needed DLLs and executables. diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index b5b8171..26402b7 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1801,9 +1801,12 @@ class Backend: env = build.EnvironmentVariables() extra_paths = set() library_paths = set() + host_machine = self.environment.machines[MachineChoice.HOST] + need_exe_wrapper = self.environment.need_exe_wrapper() + need_wine = need_exe_wrapper and host_machine.is_windows() for t in self.build.get_targets().values(): cross_built = not self.environment.machines.matches_build_machine(t.for_machine) - can_run = not cross_built or not self.environment.need_exe_wrapper() + can_run = not cross_built or not need_exe_wrapper or need_wine in_default_dir = t.should_install() and not t.get_install_dir()[2] if not can_run or not in_default_dir: continue @@ -1813,22 +1816,25 @@ class Backend: # so they get used by default instead of searching on system when # in developer environment. extra_paths.add(tdir) - if mesonlib.is_windows() or mesonlib.is_cygwin(): + if host_machine.is_windows() or host_machine.is_cygwin(): # On windows we cannot rely on rpath to run executables from build # directory. We have to add in PATH the location of every DLL needed. - extra_paths.update(self.determine_windows_extra_paths(t, [])) + library_paths.update(self.determine_windows_extra_paths(t, [])) elif isinstance(t, build.SharedLibrary): # Add libraries that are going to be installed in libdir into # LD_LIBRARY_PATH. This allows running system applications using # that library. library_paths.add(tdir) if library_paths: - if mesonlib.is_windows() or mesonlib.is_cygwin(): + if host_machine.is_windows() or host_machine.is_cygwin(): extra_paths.update(library_paths) - elif mesonlib.is_osx(): + elif host_machine.is_darwin(): env.prepend('DYLD_LIBRARY_PATH', list(library_paths)) else: env.prepend('LD_LIBRARY_PATH', list(library_paths)) if extra_paths: - env.prepend('PATH', list(extra_paths)) + if need_wine: + env.prepend('WINEPATH', list(extra_paths), separator=';') + else: + env.prepend('PATH', list(extra_paths)) return env diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index 27533e3..f5dcf30 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -28,6 +28,56 @@ def get_windows_shell() -> str: result = subprocess.check_output(command) return result.decode().strip() +def get_wine_shortpath(build_dir: str, winecmd: str, wine_paths: T.List[str]) -> T.List[str]: + ''' + WINEPATH size is limited to 1024 bytes which can easily be exceeded when + adding the path to every dll inside build directory. See + https://bugs.winehq.org/show_bug.cgi?id=45810. + + To shorthen it as much as possible we use path relative to builddir + where possible and convert absolute paths to Windows shortpath (e.g. + "/usr/x86_64-w64-mingw32/lib" to "Z:\\usr\\X86_~FWL\\lib"). + ''' + rel_paths = [] + abs_paths = [] + builddir = Path(build_dir) + for p in wine_paths: + try: + rel = Path(p).relative_to(builddir) + rel_paths.append(str(rel)) + except ValueError: + abs_paths.append(p) + if not abs_paths: + return rel_paths + with tempfile.NamedTemporaryFile('w', suffix='.bat', encoding='utf-8', delete=False) as bat_file: + bat_file.write(''' + @ECHO OFF + for %%x in (%*) do ( + echo|set /p=;%~sx + ) + ''') + try: + stdout = subprocess.check_output([winecmd, 'cmd', '/C', bat_file.name] + abs_paths, + encoding='utf-8', stderr=subprocess.DEVNULL) + return rel_paths + [p for p in set(stdout.split(';')) if p] + except subprocess.CalledProcessError as e: + return rel_paths + abs_paths + finally: + os.unlink(bat_file.name) + +def reduce_winepath(build_dir: str, env: T.Dict[str, str]) -> None: + winepath = env.get('WINEPATH') + if not winepath: + return + winecmd = shutil.which('wine64') or shutil.which('wine') + if not winecmd: + return + winepath = ';'.join(get_wine_shortpath(build_dir, winecmd, winepath.split(';'))) + if len(winepath) > 1024: + mlog.warning(f'WINEPATH exceeds 1024 characters which could cause issues:\n{winepath}') + env['WINEPATH'] = winepath + mlog.log('Meson detected wine and has set WINEPATH accordingly') + def get_env(b: build.Build, build_dir: str) -> T.Tuple[T.Dict[str, str], T.Set[str]]: extra_env = build.EnvironmentVariables() extra_env.set('MESON_DEVENV', ['1']) @@ -39,6 +89,8 @@ def get_env(b: build.Build, build_dir: str) -> T.Tuple[T.Dict[str, str], T.Set[s env = i.get_env(env) varnames |= i.get_names() + reduce_winepath(build_dir, env) + return env, varnames def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List[str]: |