summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Brunet <charles.brunet@optelgroup.com>2025-06-27 15:50:14 -0400
committerJussi Pakkanen <jussi.pakkanen@mailbox.org>2025-08-01 15:54:21 +0300
commit8bfe9ef4624180a6344a44fef41418543e2f3c34 (patch)
treea9f5fe010ae69d98afca485eb04e3b65bb7398e3
parent27bdac0f4b422e67ca03c0bcf43ed1e8275c7e5e (diff)
downloadmeson-8bfe9ef4624180a6344a44fef41418543e2f3c34.tar.gz
move rpath functions from Backend to BuildTarget
It is more logical, since those functions depend on a build target, and do not require anything specific to the backend. Furthermore, it will allow us to call determine_rpath_dirs from the linker in a following commit, without the need to depend on the backend.
-rw-r--r--mesonbuild/backend/backends.py109
-rw-r--r--mesonbuild/build.py113
-rw-r--r--mesonbuild/modules/gnome.py4
3 files changed, 115 insertions, 111 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 6c9b31543..e3d6c602d 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -24,12 +24,12 @@ from .. import dependencies
from .. import programs
from .. import mesonlib
from .. import mlog
-from ..compilers import LANGUAGES_USING_LDFLAGS, detect, lang_suffixes
+from ..compilers import detect, lang_suffixes
from ..mesonlib import (
File, MachineChoice, MesonException, MesonBugException, OrderedSet,
ExecutableSerialisation, EnvironmentException,
classify_unity_sources, get_compiler_for_source,
- is_parent_path, get_rsp_threshold,
+ get_rsp_threshold,
)
from ..options import OptionKey
@@ -733,111 +733,6 @@ class Backend:
return l, stdlib_args
@staticmethod
- def _libdir_is_system(libdir: str, compilers: T.Mapping[str, 'Compiler'], env: 'Environment') -> bool:
- libdir = os.path.normpath(libdir)
- for cc in compilers.values():
- if libdir in cc.get_library_dirs(env):
- return True
- return False
-
- def get_external_rpath_dirs(self, target: build.BuildTarget) -> T.Set[str]:
- args: T.List[str] = []
- for lang in LANGUAGES_USING_LDFLAGS:
- try:
- args += self.environment.coredata.get_external_link_args(target.for_machine, lang)
- except KeyError:
- pass
- return self.get_rpath_dirs_from_link_args(args)
-
- @staticmethod
- def get_rpath_dirs_from_link_args(args: T.List[str]) -> T.Set[str]:
- dirs: T.Set[str] = set()
- # Match rpath formats:
- # -Wl,-rpath=
- # -Wl,-rpath,
- rpath_regex = re.compile(r'-Wl,-rpath[=,]([^,]+)')
- # Match solaris style compat runpath formats:
- # -Wl,-R
- # -Wl,-R,
- runpath_regex = re.compile(r'-Wl,-R[,]?([^,]+)')
- # Match symbols formats:
- # -Wl,--just-symbols=
- # -Wl,--just-symbols,
- symbols_regex = re.compile(r'-Wl,--just-symbols[=,]([^,]+)')
- for arg in args:
- rpath_match = rpath_regex.match(arg)
- if rpath_match:
- for dir in rpath_match.group(1).split(':'):
- dirs.add(dir)
- runpath_match = runpath_regex.match(arg)
- if runpath_match:
- for dir in runpath_match.group(1).split(':'):
- # The symbols arg is an rpath if the path is a directory
- if Path(dir).is_dir():
- dirs.add(dir)
- symbols_match = symbols_regex.match(arg)
- if symbols_match:
- for dir in symbols_match.group(1).split(':'):
- # Prevent usage of --just-symbols to specify rpath
- if Path(dir).is_dir():
- raise MesonException(f'Invalid arg for --just-symbols, {dir} is a directory.')
- return dirs
-
- @lru_cache(maxsize=None)
- 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()
-
- for dep in target.external_deps:
- if dep.type_name not in {'library', 'pkgconfig', 'cmake'}:
- continue
- for libpath in dep.link_args:
- # For all link args that are absolute paths to a library file, add RPATH args
- if not os.path.isabs(libpath):
- continue
- libdir = os.path.dirname(libpath)
- if exclude_system and self._libdir_is_system(libdir, target.compilers, self.environment):
- # No point in adding system paths.
- continue
- # Don't remove rpaths specified in LDFLAGS.
- if libdir in self.get_external_rpath_dirs(target):
- continue
- # Windows doesn't support rpaths, but we use this function to
- # emulate rpaths by setting PATH
- # .dll is there for mingw gcc
- # .so's may be extended with version information, e.g. libxyz.so.1.2.3
- if not (
- os.path.splitext(libpath)[1] in {'.dll', '.lib', '.so', '.dylib'}
- or re.match(r'.+\.so(\.|$)', os.path.basename(libpath))
- ):
- continue
-
- if is_parent_path(srcdir, libdir):
- 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):
- if isinstance(i, build.BuildTarget):
- paths.update(self.rpaths_for_non_system_absolute_shared_libraries(i, exclude_system))
- return list(paths)
-
- def determine_rpath_dirs(self, target: build.BuildTarget) -> T.Tuple[str, ...]:
- result: OrderedSet[str]
- if self.environment.coredata.optstore.get_value_for(OptionKey('layout')) == 'mirror':
- # Need a copy here
- result = OrderedSet(target.get_link_dep_subdirs())
- else:
- result = OrderedSet()
- result.add('meson-out')
- result.update(self.rpaths_for_non_system_absolute_shared_libraries(target))
- target.rpath_dirs_to_remove.update([d.encode('utf-8') for d in result])
- return tuple(result)
-
- @staticmethod
@lru_cache(maxsize=None)
def canonicalize_filename(fname: str) -> str:
if os.path.altsep is not None:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 410b4d243..8f812c959 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -24,14 +24,14 @@ from .mesonlib import (
File, MesonException, MachineChoice, PerMachine, OrderedSet, listify,
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
get_filenames_templates_dict, substitute_values, has_path_sep,
- is_parent_path, PerMachineDefaultable,
+ is_parent_path, relpath, PerMachineDefaultable,
MesonBugException, EnvironmentVariables, pickle_load, lazy_property,
)
from .options import OptionKey
from .compilers import (
is_header, is_object, is_source, clink_langs, sort_clink, all_languages,
- is_known_suffix, detect_static_linker
+ is_known_suffix, detect_static_linker, LANGUAGES_USING_LDFLAGS
)
from .interpreterbase import FeatureNew, FeatureDeprecated, UnknownValue
@@ -1796,6 +1796,115 @@ class BuildTarget(Target):
"""Base case used by BothLibraries"""
return self
+ def determine_rpath_dirs(self) -> T.Tuple[str, ...]:
+ result: OrderedSet[str]
+ if self.environment.coredata.optstore.get_value_for(OptionKey('layout')) == 'mirror':
+ # Need a copy here
+ result = OrderedSet(self.get_link_dep_subdirs())
+ else:
+ result = OrderedSet()
+ result.add('meson-out')
+ result.update(self.rpaths_for_non_system_absolute_shared_libraries())
+ self.rpath_dirs_to_remove.update([d.encode('utf-8') for d in result])
+ return tuple(result)
+
+ @staticmethod
+ def _libdir_is_system(libdir: str, compilers: T.Mapping[str, Compiler], env: environment.Environment) -> bool:
+ libdir = os.path.normpath(libdir)
+ for cc in compilers.values():
+ if libdir in cc.get_library_dirs(env):
+ return True
+ return False
+
+ @lru_cache(maxsize=None)
+ def rpaths_for_non_system_absolute_shared_libraries(self, exclude_system: bool = True) -> ImmutableListProtocol[str]:
+ paths: OrderedSet[str] = OrderedSet()
+ srcdir = self.environment.get_source_dir()
+
+ build_to_src = relpath(self.environment.get_source_dir(),
+ self.environment.get_build_dir())
+
+ for dep in self.external_deps:
+ if dep.type_name not in {'library', 'pkgconfig', 'cmake'}:
+ continue
+ for libpath in dep.link_args:
+ # For all link args that are absolute paths to a library file, add RPATH args
+ if not os.path.isabs(libpath):
+ continue
+ libdir = os.path.dirname(libpath)
+ if exclude_system and self._libdir_is_system(libdir, self.compilers, self.environment):
+ # No point in adding system paths.
+ continue
+ # Don't remove rpaths specified in LDFLAGS.
+ if libdir in self.get_external_rpath_dirs():
+ continue
+ # Windows doesn't support rpaths, but we use this function to
+ # emulate rpaths by setting PATH
+ # .dll is there for mingw gcc
+ # .so's may be extended with version information, e.g. libxyz.so.1.2.3
+ if not (
+ os.path.splitext(libpath)[1] in {'.dll', '.lib', '.so', '.dylib'}
+ or re.match(r'.+\.so(\.|$)', os.path.basename(libpath))
+ ):
+ continue
+
+ if is_parent_path(srcdir, libdir):
+ 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(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 itertools.chain(self.link_targets, self.link_whole_targets):
+ if isinstance(i, BuildTarget):
+ paths.update(i.rpaths_for_non_system_absolute_shared_libraries(exclude_system))
+ return list(paths)
+
+ def get_external_rpath_dirs(self) -> T.Set[str]:
+ args: T.List[str] = []
+ for lang in LANGUAGES_USING_LDFLAGS:
+ try:
+ args += self.environment.coredata.get_external_link_args(self.for_machine, lang)
+ except KeyError:
+ pass
+ return self.get_rpath_dirs_from_link_args(args)
+
+ @staticmethod
+ def get_rpath_dirs_from_link_args(args: T.List[str]) -> T.Set[str]:
+ dirs: T.Set[str] = set()
+ # Match rpath formats:
+ # -Wl,-rpath=
+ # -Wl,-rpath,
+ rpath_regex = re.compile(r'-Wl,-rpath[=,]([^,]+)')
+ # Match solaris style compat runpath formats:
+ # -Wl,-R
+ # -Wl,-R,
+ runpath_regex = re.compile(r'-Wl,-R[,]?([^,]+)')
+ # Match symbols formats:
+ # -Wl,--just-symbols=
+ # -Wl,--just-symbols,
+ symbols_regex = re.compile(r'-Wl,--just-symbols[=,]([^,]+)')
+ for arg in args:
+ rpath_match = rpath_regex.match(arg)
+ if rpath_match:
+ for dir in rpath_match.group(1).split(':'):
+ dirs.add(dir)
+ runpath_match = runpath_regex.match(arg)
+ if runpath_match:
+ for dir in runpath_match.group(1).split(':'):
+ # The symbols arg is an rpath if the path is a directory
+ if os.path.isdir(dir):
+ dirs.add(dir)
+ symbols_match = symbols_regex.match(arg)
+ if symbols_match:
+ for dir in symbols_match.group(1).split(':'):
+ # Prevent usage of --just-symbols to specify rpath
+ if os.path.isdir(dir):
+ raise MesonException(f'Invalid arg for --just-symbols, {dir} is a directory.')
+ return dirs
+
+
class FileInTargetPrivateDir:
"""Represents a file with the path '/path/to/build/target_private_dir/fname'.
target_private_dir is the return value of get_target_private_dir which is e.g. 'subdir/target.p'.
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 7ae66930a..53919bc2e 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -634,7 +634,7 @@ class GnomeModule(ExtensionModule):
# https://github.com/mesonbuild/meson/issues/1911
# However, g-ir-scanner does not understand -Wl,-rpath
# so we need to use -L instead
- for d in state.backend.determine_rpath_dirs(lib):
+ for d in lib.determine_rpath_dirs():
d = os.path.join(state.environment.get_build_dir(), d)
link_command.append('-L' + d)
if include_rpath:
@@ -871,7 +871,7 @@ class GnomeModule(ExtensionModule):
# https://github.com/mesonbuild/meson/issues/1911
# However, g-ir-scanner does not understand -Wl,-rpath
# so we need to use -L instead
- for d in state.backend.determine_rpath_dirs(girtarget):
+ for d in girtarget.determine_rpath_dirs():
d = os.path.join(state.environment.get_build_dir(), d)
ret.append('-L' + d)