diff options
| author | Dylan Baker <dylan@pnwbakers.com> | 2025-12-05 09:06:21 -0800 |
|---|---|---|
| committer | Dylan Baker <dylan@pnwbakers.com> | 2025-12-17 14:04:17 -0800 |
| commit | 7a1655acd29e5ba50a2951ad6c8db934fa7a6eb9 (patch) | |
| tree | 12db71bed861b2b51f60cab12b1ae8f425caab30 /mesonbuild | |
| parent | 6e4caca1dacd62b86967c0aa9f5a64e95f356e39 (diff) | |
| download | meson-7a1655acd29e5ba50a2951ad6c8db934fa7a6eb9.tar.gz | |
build: clean up some some of the link_whole path
This puts subclass specific logic in the subclasses, and cleans up some
typing.
Diffstat (limited to 'mesonbuild')
| -rw-r--r-- | mesonbuild/build.py | 104 | ||||
| -rw-r--r-- | mesonbuild/interpreter/kwargs.py | 4 |
2 files changed, 63 insertions, 45 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 32a643601..50d83fa9f 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -52,6 +52,7 @@ if T.TYPE_CHECKING: GeneratedTypes: TypeAlias = T.Union['CustomTarget', 'CustomTargetIndex', 'GeneratedList'] LibTypes: TypeAlias = T.Union['SharedLibrary', 'StaticLibrary', 'CustomTarget', 'CustomTargetIndex'] BuildTargetTypes: TypeAlias = T.Union['BuildTarget', 'CustomTarget', 'CustomTargetIndex'] + StaticTargetTypes: TypeAlias = T.Union['StaticLibrary', 'CustomTarget', 'CustomTargetIndex'] ObjectTypes: TypeAlias = T.Union[str, 'File', 'ExtractedObjects', 'GeneratedTypes'] AnyTargetType: TypeAlias = T.Union['Target', 'CustomTargetIndex'] RustCrateType: TypeAlias = Literal['bin', 'lib', 'rlib', 'dylib', 'cdylib', 'staticlib', 'proc-macro'] @@ -90,7 +91,7 @@ if T.TYPE_CHECKING: link_args: T.List[str] link_depends: T.List[T.Union[str, File, CustomTarget, CustomTargetIndex]] link_language: str - link_whole: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]] + link_whole: T.List[StaticTargetTypes] link_with: T.List[BuildTargetTypes] name_prefix: T.Optional[str] name_suffix: T.Optional[str] @@ -796,7 +797,7 @@ class BuildTarget(Target): self.include_dirs: T.List['IncludeDirs'] = [] self.link_language = kwargs.get('link_language') self.link_targets: T.List[LibTypes] = [] - self.link_whole_targets: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]] = [] + self.link_whole_targets: T.List[StaticTargetTypes] = [] self.depend_files: T.List[File] = [] self.link_depends: T.List[T.Union[File, BuildTargetTypes]] = [] self.added_deps = set() @@ -1493,32 +1494,19 @@ class BuildTarget(Target): def link_whole( self, - targets: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]], + targets: T.List[StaticTargetTypes], promoted: bool = False) -> None: for t in targets: - if isinstance(self, SharedLibrary) and not getattr(t, 'pic', True): - msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " - msg += "Use the 'pic' option to static_library to build with PIC." - raise InvalidArguments(msg) self.check_can_link_together(t) - if isinstance(self, StaticLibrary): - # When we're a static library and we link_whole: to another static - # library, we need to add that target's objects to ourselves. - self._bundle_static_library(t, promoted) - # If we install this static library we also need to include objects - # from all uninstalled static libraries it depends on. - if self.install: - for lib in t.get_internal_static_libraries(): - self._bundle_static_library(lib, True) self.link_whole_targets.append(t) @lru_cache(maxsize=None) - def get_internal_static_libraries(self) -> OrderedSet[BuildTargetTypes]: - result: OrderedSet[BuildTargetTypes] = OrderedSet() + def get_internal_static_libraries(self) -> OrderedSet[StaticTargetTypes]: + result: OrderedSet[StaticTargetTypes] = OrderedSet() self.get_internal_static_libraries_recurse(result) return result - def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTypes]) -> None: + def get_internal_static_libraries_recurse(self, result: OrderedSet[StaticTargetTypes]) -> None: for t in self.link_targets: if t.is_internal() and t not in result: result.add(t) @@ -1527,28 +1515,6 @@ class BuildTarget(Target): if t.is_internal(): t.get_internal_static_libraries_recurse(result) - def _bundle_static_library(self, t: T.Union[BuildTargetTypes], promoted: bool = False) -> None: - if self.uses_rust(): - # Rustc can bundle static libraries, no need to extract objects. - self.link_whole_targets.append(t) - elif isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): - # To extract objects from a custom target we would have to extract - # the archive, WIP implementation can be found in - # https://github.com/mesonbuild/meson/pull/9218. - # For Rust C ABI we could in theory have access to objects, but there - # are several meson issues that need to be fixed: - # https://github.com/mesonbuild/meson/issues/10722 - # https://github.com/mesonbuild/meson/issues/10723 - # https://github.com/mesonbuild/meson/issues/10724 - m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {self.name!r}. ' - 'Instead, pass individual object files with the "objects:" keyword argument if possible.') - if promoted: - m += (f' Meson had to promote link to link_whole because {self.name!r} is installed but not {t.name!r},' - f' and thus has to include objects from {t.name!r} to be usable.') - raise InvalidArguments(m) - else: - self.objects.append(t.extract_all_objects()) - def check_can_link_together(self, t: BuildTargetTypes) -> None: links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi() if not self.uses_rust() and links_with_rust_abi: @@ -2374,6 +2340,46 @@ class StaticLibrary(BuildTarget): result.link_targets = [t.get(lib_type, True) for t in self.link_targets] return result + def link_whole( + self, + targets: T.List[StaticTargetTypes], + promoted: bool = False) -> None: + for t in targets: + self.check_can_link_together(t) + + # When we're a static library and we link_whole: to another static + # library, we need to add that target's objects to ourselves. + self._bundle_static_library(t, promoted) + + # If we install this static library we also need to include objects + # from all uninstalled static libraries it depends on. + if self.install: + for lib in t.get_internal_static_libraries(): + self._bundle_static_library(lib, True) + self.link_whole_targets.append(t) + + def _bundle_static_library(self, t: StaticTargetTypes, promoted: bool = False) -> None: + if self.uses_rust(): + # Rustc can bundle static libraries, no need to extract objects. + self.link_whole_targets.append(t) + elif isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): + # To extract objects from a custom target we would have to extract + # the archive, WIP implementation can be found in + # https://github.com/mesonbuild/meson/pull/9218. + # For Rust C ABI we could in theory have access to objects, but there + # are several meson issues that need to be fixed: + # https://github.com/mesonbuild/meson/issues/10722 + # https://github.com/mesonbuild/meson/issues/10723 + # https://github.com/mesonbuild/meson/issues/10724 + m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {self.name!r}. ' + 'Instead, pass individual object files with the "objects:" keyword argument if possible.') + if promoted: + m += (f' Meson had to promote link to link_whole because {self.name!r} is installed but not {t.name!r},' + f' and thus has to include objects from {t.name!r} to be usable.') + raise InvalidArguments(m) + else: + self.objects.append(t.extract_all_objects()) + class SharedLibrary(BuildTarget): known_kwargs = known_shlib_kwargs @@ -2678,6 +2684,18 @@ class SharedLibrary(BuildTarget): result.link_targets = [t.get(lib_type, True) for t in self.link_targets] return result + def link_whole( + self, + targets: T.List[StaticTargetTypes], + promoted: bool = False) -> None: + for t in targets: + self.check_can_link_together(t) + if not getattr(t, 'pic', True): + msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " + msg += "Use the 'pic' option to static_library to build with PIC." + raise InvalidArguments(msg) + self.link_whole_targets.append(t) + # A shared library that is meant to be used with dlopen rather than linking # into something else. class SharedModule(SharedLibrary): @@ -2792,10 +2810,10 @@ class CustomTargetBase: def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include_internals: bool = True) -> None: pass - def get_internal_static_libraries(self) -> OrderedSet[BuildTargetTypes]: + def get_internal_static_libraries(self) -> OrderedSet[StaticTargetTypes]: return OrderedSet() - def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTypes]) -> None: + def get_internal_static_libraries_recurse(self, result: OrderedSet[StaticTargetTypes]) -> None: pass def get_all_linked_targets(self) -> ImmutableListProtocol[BuildTargetTypes]: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index e3e919019..e7d2ac9a8 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -348,7 +348,7 @@ class _BaseBuildTarget(TypedDict): implicit_include_directories: bool link_depends: T.List[T.Union[str, File, build.GeneratedTypes]] link_language: T.Optional[str] - link_whole: T.List[T.Union[build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]] + link_whole: T.List[build.StaticTargetTypes] name_prefix: T.Optional[str] name_suffix: T.Optional[str] native: MachineChoice @@ -493,7 +493,7 @@ class FuncDeclareDependency(TypedDict): extra_files: T.List[FileOrString] include_directories: T.List[T.Union[build.IncludeDirs, str]] link_args: T.List[str] - link_whole: T.List[T.Union[build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]] + link_whole: T.List[build.StaticTargetTypes] link_with: T.List[build.LibTypes] objects: T.List[build.ExtractedObjects] sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] |
