aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py52
-rw-r--r--test cases/rust/2 sharedlib/meson.build5
-rw-r--r--test cases/rust/2 sharedlib/stuff.rs10
-rw-r--r--test cases/rust/2 sharedlib/value.c3
-rw-r--r--test cases/rust/3 staticlib/meson.build6
-rw-r--r--test cases/rust/3 staticlib/other.rs5
-rw-r--r--test cases/rust/3 staticlib/prog.rs4
-rw-r--r--test cases/rust/3 staticlib/stuff.rs13
-rw-r--r--test cases/rust/3 staticlib/value.c5
-rw-r--r--test cases/rust/5 polyglot static/clib.c12
-rw-r--r--test cases/rust/5 polyglot static/meson.build3
-rw-r--r--test cases/rust/5 polyglot static/prog.c5
-rw-r--r--test cases/rust/5 polyglot static/stuff.rs2
-rw-r--r--test cases/rust/5 polyglot static/test.json2
14 files changed, 113 insertions, 14 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')):
diff --git a/test cases/rust/2 sharedlib/meson.build b/test cases/rust/2 sharedlib/meson.build
index 02b8cf7..295fa04 100644
--- a/test cases/rust/2 sharedlib/meson.build
+++ b/test cases/rust/2 sharedlib/meson.build
@@ -1,10 +1,11 @@
-project('rust shared library', 'rust')
+project('rust shared library', 'rust', 'c')
if host_machine.system() == 'darwin'
error('MESON_SKIP_TEST: does not work right on macos, please fix!')
endif
-l = shared_library('stuff', 'stuff.rs', install : true)
+s = static_library('static', 'value.c')
+l = shared_library('stuff', 'stuff.rs', link_whole : s, install : true)
e = executable('prog', 'prog.rs', link_with : l, install : true)
if build_machine.system() == 'windows'
diff --git a/test cases/rust/2 sharedlib/stuff.rs b/test cases/rust/2 sharedlib/stuff.rs
index 8cabc62..e7c0521 100644
--- a/test cases/rust/2 sharedlib/stuff.rs
+++ b/test cases/rust/2 sharedlib/stuff.rs
@@ -1,3 +1,11 @@
#![crate_name = "stuff"]
-pub fn explore() -> &'static str { "librarystring" }
+extern "C" {
+ fn c_value() -> i32;
+}
+
+pub fn explore() -> String {
+ unsafe {
+ format!("library{}string", c_value())
+ }
+}
diff --git a/test cases/rust/2 sharedlib/value.c b/test cases/rust/2 sharedlib/value.c
new file mode 100644
index 0000000..d17b6de
--- /dev/null
+++ b/test cases/rust/2 sharedlib/value.c
@@ -0,0 +1,3 @@
+int c_value(void) {
+ return 7;
+}
diff --git a/test cases/rust/3 staticlib/meson.build b/test cases/rust/3 staticlib/meson.build
index 6769564..cf8e103 100644
--- a/test cases/rust/3 staticlib/meson.build
+++ b/test cases/rust/3 staticlib/meson.build
@@ -1,5 +1,7 @@
-project('rust static library', 'rust')
+project('rust static library', 'rust', 'c')
-l = static_library('stuff', 'stuff.rs', install : true)
+o = static_library('other', 'other.rs')
+v = static_library('value', 'value.c')
+l = static_library('stuff', 'stuff.rs', link_whole : [o, v], install : true)
e = executable('prog', 'prog.rs', link_with : l, install : true)
test('linktest', e)
diff --git a/test cases/rust/3 staticlib/other.rs b/test cases/rust/3 staticlib/other.rs
new file mode 100644
index 0000000..037be33
--- /dev/null
+++ b/test cases/rust/3 staticlib/other.rs
@@ -0,0 +1,5 @@
+pub fn explore(
+ value: i32,
+) -> String {
+ format!("library{}string", value)
+}
diff --git a/test cases/rust/3 staticlib/prog.rs b/test cases/rust/3 staticlib/prog.rs
index fbf3181..eee2653 100644
--- a/test cases/rust/3 staticlib/prog.rs
+++ b/test cases/rust/3 staticlib/prog.rs
@@ -1,3 +1,5 @@
extern crate stuff;
-fn main() { println!("printing: {}", stuff::explore()); }
+fn main() {
+ println!("printing: {}", stuff::explore());
+}
diff --git a/test cases/rust/3 staticlib/stuff.rs b/test cases/rust/3 staticlib/stuff.rs
index 8cabc62..7cfcdff 100644
--- a/test cases/rust/3 staticlib/stuff.rs
+++ b/test cases/rust/3 staticlib/stuff.rs
@@ -1,3 +1,14 @@
#![crate_name = "stuff"]
-pub fn explore() -> &'static str { "librarystring" }
+extern crate other;
+
+extern "C" {
+ fn c_explore_value() -> i32;
+}
+
+pub fn explore(
+) -> String {
+ unsafe {
+ other::explore(c_explore_value())
+ }
+}
diff --git a/test cases/rust/3 staticlib/value.c b/test cases/rust/3 staticlib/value.c
new file mode 100644
index 0000000..b71c8060
--- /dev/null
+++ b/test cases/rust/3 staticlib/value.c
@@ -0,0 +1,5 @@
+int
+c_explore_value (void)
+{
+ return 42;
+}
diff --git a/test cases/rust/5 polyglot static/clib.c b/test cases/rust/5 polyglot static/clib.c
new file mode 100644
index 0000000..366dbe5
--- /dev/null
+++ b/test cases/rust/5 polyglot static/clib.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void hello_from_rust(void);
+
+static void hello_from_c(void) {
+ printf("Hello from C!\n");
+}
+
+void hello_from_both(void) {
+ hello_from_c();
+ hello_from_rust();
+}
diff --git a/test cases/rust/5 polyglot static/meson.build b/test cases/rust/5 polyglot static/meson.build
index b2a44da..bed7977 100644
--- a/test cases/rust/5 polyglot static/meson.build
+++ b/test cases/rust/5 polyglot static/meson.build
@@ -8,7 +8,8 @@ deps = [
extra_winlibs = meson.get_compiler('c').get_id() in ['msvc', 'clang-cl'] ? ['userenv.lib', 'ws2_32.lib', 'bcrypt.lib'] : []
-l = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib', install : true)
+r = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib')
+l = static_library('clib', 'clib.c', link_with : r, install : true)
e = executable('prog', 'prog.c',
dependencies: deps,
link_with : l,
diff --git a/test cases/rust/5 polyglot static/prog.c b/test cases/rust/5 polyglot static/prog.c
index dbbd880..0a8e0d1 100644
--- a/test cases/rust/5 polyglot static/prog.c
+++ b/test cases/rust/5 polyglot static/prog.c
@@ -1,8 +1,7 @@
#include <stdio.h>
-void f();
+void hello_from_both();
int main(void) {
- printf("Hello from C!\n");
- f();
+ hello_from_both();
}
diff --git a/test cases/rust/5 polyglot static/stuff.rs b/test cases/rust/5 polyglot static/stuff.rs
index ecf623c..3777ae8 100644
--- a/test cases/rust/5 polyglot static/stuff.rs
+++ b/test cases/rust/5 polyglot static/stuff.rs
@@ -1,6 +1,6 @@
#![crate_name = "stuff"]
#[no_mangle]
-pub extern fn f() {
+pub extern "C" fn hello_from_rust() {
println!("Hello from Rust!");
}
diff --git a/test cases/rust/5 polyglot static/test.json b/test cases/rust/5 polyglot static/test.json
index 1d4eff4..cc0d2da 100644
--- a/test cases/rust/5 polyglot static/test.json
+++ b/test cases/rust/5 polyglot static/test.json
@@ -2,6 +2,6 @@
"installed": [
{"type": "exe", "file": "usr/bin/prog"},
{"type": "pdb", "file": "usr/bin/prog"},
- {"type": "file", "file": "usr/lib/libstuff.a"}
+ {"type": "file", "file": "usr/lib/libclib.a"}
]
}