aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/backend/ninjabackend.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/backend/ninjabackend.py')
-rw-r--r--mesonbuild/backend/ninjabackend.py52
1 files changed, 51 insertions, 1 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 21dd87b..3d6bfb9 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1901,7 +1901,8 @@ class NinjaBackend(backends.Backend):
args += output
linkdirs = mesonlib.OrderedSet()
external_deps = target.external_deps.copy()
- for d in itertools.chain(target.link_targets, target.link_whole_targets):
+ # TODO: we likely need to use verbatim to handle name_prefix and name_suffix
+ for d in target.link_targets:
linkdirs.add(d.subdir)
if d.uses_rust():
# specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust
@@ -1922,6 +1923,55 @@ class NinjaBackend(backends.Backend):
# Rust uses -l for non rust dependencies, but we still need to
# add dylib=foo
args += ['-l', f'dylib={d.name}']
+
+ # Since 1.61.0 Rust has a special modifier for whole-archive linking,
+ # before that it would treat linking two static libraries as
+ # whole-archive linking. However, to make this work we have to disable
+ # bundling, which can't be done until 1.63.0… So for 1.61–1.62 we just
+ # have to hope that the default cases of +whole-archive are sufficent.
+ # See: https://github.com/rust-lang/rust/issues/99429
+ if mesonlib.version_compare(rustc.version, '>= 1.63.0'):
+ whole_archive = ':+whole-archive,-bundle'
+ else:
+ whole_archive = ''
+
+ if mesonlib.version_compare(rustc.version, '>= 1.67.0'):
+ verbatim = ',+verbatim'
+ else:
+ verbatim = ''
+
+ for d in target.link_whole_targets:
+ linkdirs.add(d.subdir)
+ if d.uses_rust():
+ # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust
+ # dependency, so that collisions with libraries in rustc's
+ # sysroot don't cause ambiguity
+ args += ['--extern', '{}={}'.format(d.name, os.path.join(d.subdir, d.filename))]
+ project_deps.append(RustDep(d.name, self.rust_crates[d.name].order))
+ else:
+ if rustc.linker.id in {'link', 'lld-link'}:
+ if verbatim:
+ # If we can use the verbatim modifier, then everything is great
+ args += ['-l', f'static{whole_archive}{verbatim}={d.get_outputs()[0]}']
+ elif isinstance(target, build.StaticLibrary):
+ # If we don't, for static libraries the only option is
+ # to make a copy, since we can't pass objects in, or
+ # directly affect the archiver. but we're not going to
+ # do that given how quickly rustc versions go out of
+ # support unless there's a compelling reason to do so.
+ # This only affects 1.61–1.66
+ mlog.warning('Due to limitations in Rustc versions 1.61–1.66 and meson library naming',
+ 'whole-archive linking with MSVC may or may not work. Upgrade rustc to',
+ '>= 1.67. A best effort is being made, but likely won\'t work')
+ args += ['-l', f'static={d.name}']
+ else:
+ # When doing dynamic linking (binaries and [c]dylibs),
+ # we can instead just proxy the correct arguments to the linker
+ for link_whole_arg in rustc.linker.get_link_whole_for([self.get_target_filename_for_linking(d)]):
+ args += ['-C', f'link-arg={link_whole_arg}']
+ else:
+ args += ['-l', f'static{whole_archive}={d.name}']
+ external_deps.extend(d.external_deps)
for e in external_deps:
for a in e.get_link_args():
if a.endswith(('.dll', '.so', '.dylib')):