build: Simplify recursive function that extracts objects in link_whole

pull/12485/head
Xavier Claessens 1 year ago
parent 686963f1c2
commit 21bf18afa1
  1. 37
      mesonbuild/build.py

@ -1276,13 +1276,13 @@ class BuildTarget(Target):
return self.extra_args[language]
@lru_cache(maxsize=None)
def get_dependencies(self) -> OrderedSet[Target]:
def get_dependencies(self) -> OrderedSet[BuildTargetTypes]:
# Get all targets needed for linking. This includes all link_with and
# link_whole targets, and also all dependencies of static libraries
# recursively. The algorithm here is closely related to what we do in
# get_internal_static_libraries(): Installed static libraries include
# objects from all their dependencies already.
result: OrderedSet[Target] = OrderedSet()
result: OrderedSet[BuildTargetTypes] = OrderedSet()
for t in itertools.chain(self.link_targets, self.link_whole_targets):
if t not in result:
result.add(t)
@ -1290,7 +1290,7 @@ class BuildTarget(Target):
t.get_dependencies_recurse(result)
return result
def get_dependencies_recurse(self, result: OrderedSet[Target], include_internals: bool = True) -> None:
def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include_internals: bool = True) -> None:
# self is always a static library because we don't need to pull dependencies
# of shared libraries. If self is installed (not internal) it already
# include objects extracted from all its internal dependencies so we can
@ -1394,7 +1394,7 @@ class BuildTarget(Target):
def is_internal(self) -> bool:
return False
def link(self, targets):
def link(self, targets: T.List[BuildTargetTypes]) -> None:
for t in targets:
if not isinstance(t, (Target, CustomTargetIndex)):
if isinstance(t, dependencies.ExternalLibrary):
@ -1420,7 +1420,7 @@ class BuildTarget(Target):
self.check_can_link_together(t)
self.link_targets.append(t)
def link_whole(self, targets, promoted: bool = False):
def link_whole(self, targets: T.List[BuildTargetTypes], promoted: bool = False) -> None:
for t in targets:
if isinstance(t, (CustomTarget, CustomTargetIndex)):
if not t.is_linkable_target():
@ -1437,32 +1437,30 @@ class BuildTarget(Target):
if isinstance(self, StaticLibrary) and not self.uses_rust():
# 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.check_can_extract_objects(t, origin=self, promoted=promoted)
self.objects += [t.extract_all_objects()]
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(origin=self):
self.objects += [lib.extract_all_objects()]
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, origin: StaticLibrary) -> OrderedSet[Target]:
result: OrderedSet[Target] = OrderedSet()
self.get_internal_static_libraries_recurse(result, origin)
def get_internal_static_libraries(self) -> OrderedSet[BuildTargetTypes]:
result: OrderedSet[BuildTargetTypes] = OrderedSet()
self.get_internal_static_libraries_recurse(result)
return result
def get_internal_static_libraries_recurse(self, result: OrderedSet[Target], origin: StaticLibrary) -> None:
def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTypes]) -> None:
for t in self.link_targets:
if t.is_internal() and t not in result:
self.check_can_extract_objects(t, origin, promoted=True)
result.add(t)
t.get_internal_static_libraries_recurse(result, origin)
t.get_internal_static_libraries_recurse(result)
for t in self.link_whole_targets:
if t.is_internal():
t.get_internal_static_libraries_recurse(result, origin)
t.get_internal_static_libraries_recurse(result)
def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origin: StaticLibrary, promoted: bool = False) -> None:
def _bundle_static_library(self, t: T.Union[BuildTargetTypes], promoted: bool = False) -> None:
if 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
@ -1472,12 +1470,13 @@ class BuildTarget(Target):
# 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 {origin.name!r}. '
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 {origin.name!r} is installed but not {t.name!r},'
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)
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()

Loading…
Cancel
Save