From 03498424d0bacab75f19c335ffdaa4efd8d512ed Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 24 Mar 2023 15:43:29 -0400 Subject: find dll path on Windows When running tests on Windows (or for devenv), paths of shared libraries need to be added to the PATH envvar for Windows to be able to find them. Meson is currently using the path of the import lib, which is wrong in many cases. This fix does two things: if there is a variable bindir in the pkg-config file, those variable values are added to the list of path. This is for conan dependencies, if conan decides to export those paths. See https://github.com/conan-io/conan/issues/13532 . The fallback is to replace `lib` by `bin` in the import library path. This heuristic will work most of the time (but the bin directory could have a different name, or the dll itself could have a different name). In all cases, it cannot be worse than current implementation, and it solves many cases. --- mesonbuild/backend/backends.py | 44 ++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'mesonbuild/backend/backends.py') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index fa1629b..6370800 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -737,6 +737,20 @@ class Backend: def rpaths_for_non_system_absolute_shared_libraries(self, target: build.BuildTarget, exclude_system: bool = True) -> 'ImmutableListProtocol[str]': paths: OrderedSet[str] = OrderedSet() srcdir = self.environment.get_source_dir() + + def add_path(libdir: str) -> None: + try: + commonpath = os.path.commonpath((libdir, srcdir)) + except ValueError: # when paths are on different drives on Windows + commonpath = '' + + if commonpath == srcdir: + rel_to_src = libdir[len(srcdir) + 1:] + assert not os.path.isabs(rel_to_src), f'rel_to_src: {rel_to_src} is absolute' + paths.add(os.path.join(self.build_to_src, rel_to_src)) + else: + paths.add(libdir) + for dep in target.external_deps: if not isinstance(dep, (dependencies.ExternalLibrary, dependencies.PkgConfigDependency)): continue @@ -756,17 +770,27 @@ class Backend: if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so', '.dylib']: continue - try: - commonpath = os.path.commonpath((libdir, srcdir)) - except ValueError: # when paths are on different drives on Windows - commonpath = '' + if mesonlib.is_windows() and libpath.endswith('.lib'): + + if isinstance(dep, dependencies.PkgConfigDependency): + # If by chance pkg-config knows the bin dir... + bindir = dep.get_pkgconfig_variable('bindir', [], default='') + if bindir: + add_path(bindir) + continue + + # If the dll is not in the same dir, try to replace 'lib' with 'bin' in the path. + # This is not 100% proof, since the bin dir could be elsewhere or with a different + # name, and the DLL could have a different name as well, but this is better than nothing. + p = Path(libpath).with_suffix('.dll') + if not p.exists(): + # replace last occurence: + binpath = '/bin/'.join(p.as_posix().rsplit('/lib/', maxsplit=1)) + if Path(binpath).exists(): + libdir = os.path.dirname(binpath) + + add_path(libdir) - if commonpath == srcdir: - rel_to_src = libdir[len(srcdir) + 1:] - assert not os.path.isabs(rel_to_src), f'rel_to_src: {rel_to_src} is absolute' - paths.add(os.path.join(self.build_to_src, rel_to_src)) - else: - paths.add(libdir) # Don't remove rpaths specified by the dependency paths.difference_update(self.get_rpath_dirs_from_link_args(dep.link_args)) for i in chain(target.link_targets, target.link_whole_targets): -- cgit v1.1