From 456d8962f3a8097ce8c2576ad5e345c3ff510fa2 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 13 Feb 2023 22:59:17 -0500 Subject: [PATCH] python dependency: fix embed handling for system dependency Only search for and provide linkage to libpython, if the dependency expects to be linked to it. Fixes overlinking on Linux / macOS when pkg-config isn't installed and the sysconfig lookup is used instead. This was correctly handled for pkg-config rather than deferring it until use, since commit bf832743441a1171518d7a436164c989be679410 -- but that handling neglected to cover sysconfig dependencies. And sysconfig would always try to link to libpython, it just respected the dependency configuration barely enough to allow falling back to "don't link" if both link_libpython=False and the library wasn't found. --- mesonbuild/dependencies/python.py | 36 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 48ea31c7a..6b68d11f4 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -119,7 +119,15 @@ class _PythonDependencyBase(_Base): self.variables = python_holder.info['variables'] self.paths = python_holder.info['paths'] self.is_pypy = python_holder.info['is_pypy'] - self.link_libpython = python_holder.info['link_libpython'] + # The "-embed" version of python.pc / python-config was introduced in 3.8, + # and distutils extension linking was changed to be considered a non embed + # usage. Before then, this dependency always uses the embed=True handling + # because that is the only one that exists. + # + # On macOS and some Linux distros (Debian) distutils doesn't link extensions + # against libpython, even on 3.7 and below. We call into distutils and + # mirror its behavior. See https://github.com/mesonbuild/meson/issues/4117 + self.link_libpython = python_holder.info['link_libpython'] or embed self.info: T.Optional[T.Dict[str, str]] = None if mesonlib.version_compare(self.version, '>= 3.0'): self.major_version = 3 @@ -143,15 +151,8 @@ class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase): if libpc and not self.is_found: mlog.debug(f'"python-{self.version}" could not be found in LIBPC, this is likely due to a relocated python installation') - # The "-embed" version of python.pc was introduced in 3.8, and distutils - # extension linking was changed to be considered a non embed usage. Before - # then, this dependency always uses the embed=True file because that is the - # only one that exists, - # - # On macOS and some Linux distros (Debian) distutils doesn't link extensions - # against libpython, even on 3.7 and below. We call into distutils and - # mirror its behavior. See https://github.com/mesonbuild/meson/issues/4117 - if not self.embed and not self.link_libpython and mesonlib.version_compare(self.version, '< 3.8'): + # pkg-config files are usually accurate starting with python 3.8 + if not self.link_libpython and mesonlib.version_compare(self.version, '< 3.8'): self.link_args = [] @@ -170,11 +171,15 @@ class PythonSystemDependency(SystemDependency, _PythonDependencyBase): SystemDependency.__init__(self, name, environment, kwargs) _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) - # link args - if mesonlib.is_windows(): - self.find_libpy_windows(environment) + # match pkg-config behavior + if self.link_libpython: + # link args + if mesonlib.is_windows(): + self.find_libpy_windows(environment) + else: + self.find_libpy(environment) else: - self.find_libpy(environment) + self.is_found = True # compile args inc_paths = mesonlib.OrderedSet([ @@ -210,8 +215,7 @@ class PythonSystemDependency(SystemDependency, _PythonDependencyBase): largs = self.clib_compiler.find_library(libname, environment, libdirs) if largs is not None: self.link_args = largs - - self.is_found = largs is not None or not self.link_libpython + self.is_found = True def get_windows_python_arch(self) -> T.Optional[str]: if self.platform == 'mingw':