backends: include objects of linked targets into the depscan phase

The get_all_linked_targets() method is incomplete, in that it does
not check other targets that provide objects for the target. While
ninjabackend.py does use `flatten_object_list` on the target itself,
it does not check any link_with or link_whole targets. And because the
static library in a `BothLibraries` object might actually have no sources
and have just an `ExtractedObjects` entry instead, using `link_with:
foo.get_static_lib()` in a Fortran program is broken.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini authored and Paolo Bonzini committed 2026-08-27 07:51:15 +02:00
1 parent 88c5b5def0
commit bb575c20e3
4 files changed
+25 -4

No files matched your search

+10 -4
View File
@@ -508,14 +508,21 @@ class Backend:
def get_all_linked_targets(self, target: build.BuildTarget) -> T.Iterator[build.BuildTargetTypes]:
"""Get all targets that have been linked with this one, including internal and
indirect static libraries unlike :method:`build.BuildTarget.get_all_link_deps`
and :method:`build.all_dependencies_recurse`.
and :method:`build.all_dependencies_recurse`, and targets whose objects
are borrowed by this one or any returned target.
This is useful for cases where we need to analyze these links, such as
for module information.
"""
seen: T.Set[build.BuildTarget] = set()
stack: T.Deque[build.BuildTargetTypes] = deque()
def add_linked_targets(t: build.BuildTarget) -> None:
stack.extendleft(t.link_targets)
stack.extendleft(t.link_whole_targets)
_, od = self.flatten_object_list(t)
stack.extendleft(od)
stack.extendleft(target.link_targets)
stack.extendleft(target.link_whole_targets)
while stack:
@@ -523,8 +530,7 @@ class Backend:
if t in seen or not isinstance(t, build.BuildTarget):
continue
seen.add(t)
stack.extendleft(t.link_targets)
stack.extendleft(t.link_whole_targets)
add_linked_targets(t)
yield t
assert target not in seen, 'should not have self'
@@ -0,0 +1,5 @@
program main
use mymod, only: myval
implicit none
print *, myval
end program main
@@ -0,0 +1,6 @@
project('fmodbug', 'fortran', default_options: ['default_library=both'])
lib = library('mylib', 'modsrc.f90')
# CI also runs with other default_library settings
lib_linked = get_option('default_library') == 'both' ? lib.get_static_lib() : lib
exe = executable('myexe', 'main.f90', link_with: lib_linked)
@@ -0,0 +1,4 @@
module mymod
implicit none
integer, parameter :: myval = 42
end module mymod