diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2023-11-06 13:52:51 -0500 |
---|---|---|
committer | Xavier Claessens <xavier.claessens@collabora.com> | 2023-11-09 16:20:01 -0500 |
commit | d25d8e2772b92838299b4f4056fe3888c10c0ee7 (patch) | |
tree | 54860c02283c20c6b4d81f104bb427267af241d4 /test cases/rust | |
parent | d0a7a203a6edb570c36a9fb5f04a3541df2be687 (diff) | |
download | meson-d25d8e2772b92838299b4f4056fe3888c10c0ee7.zip meson-d25d8e2772b92838299b4f4056fe3888c10c0ee7.tar.gz meson-d25d8e2772b92838299b4f4056fe3888c10c0ee7.tar.bz2 |
rust: Fix linking with C libraries (again)
Pass link arguments directly down to linker by using `-C link-args=`
instead of letting rustc/linker resolve `-l` arguments. This solves
problems with e.g. +verbatim not being portable. Note that we also pass
`-l` args as `-Clink-args=-l` because rustc would otherwise reorder
arguments and put `-lstdc++` before `-Clink-args=libfoo++.a`.
However, when building a rlib/staticlib we should still use `-l`
arguments because that allows rustc to bundle static libraries we
link-whole. In that case, since there is no platform specific dynamic
linker, +verbatim works.
This also fix installed staticlib that now bundle uninstalled static
libraries it links to (recursively). This is done by putting them all
into self.link_whole_targets instead of putting their objects into
self.objects, and let rustc do the bundling. This has the extra
advantage that rustc can bundle static libries built with CustomTarget.
Disable bundling in all other cases, otherwise we could end up with
duplicated objects in static libraries, in diamond dependency graph
case.
Fixes: #12484
Diffstat (limited to 'test cases/rust')
14 files changed, 111 insertions, 17 deletions
diff --git a/test cases/rust/15 polyglot sharedlib/adder.c b/test cases/rust/15 polyglot sharedlib/adder.c index 66613ed..1b5faa6 100644 --- a/test cases/rust/15 polyglot sharedlib/adder.c +++ b/test cases/rust/15 polyglot sharedlib/adder.c @@ -11,7 +11,13 @@ adder* adder_create(int number) { return a; } -// adder_add is implemented in the Rust file. +// adder_add_r is implemented in the Rust file. +int adder_add_r(adder *a, int number); + +int adder_add(adder *a, int number) +{ + return adder_add_r(a, number); +} void adder_destroy(adder *a) { free(a); diff --git a/test cases/rust/15 polyglot sharedlib/adder.rs b/test cases/rust/15 polyglot sharedlib/adder.rs index 9095350..ec4d1cc 100644 --- a/test cases/rust/15 polyglot sharedlib/adder.rs +++ b/test cases/rust/15 polyglot sharedlib/adder.rs @@ -3,7 +3,14 @@ pub struct Adder { pub number: i32 } +extern "C" { + pub fn zero() -> i32; + pub fn zero_static() -> i32; +} + #[no_mangle] -pub extern fn adder_add(a: &Adder, number: i32) -> i32 { - return a.number + number; +pub extern fn adder_add_r(a: &Adder, number: i32) -> i32 { + unsafe { + return a.number + number + zero() + zero_static(); + } } diff --git a/test cases/rust/15 polyglot sharedlib/meson.build b/test cases/rust/15 polyglot sharedlib/meson.build index 13fc8fd..fc3d53b 100644 --- a/test cases/rust/15 polyglot sharedlib/meson.build +++ b/test cases/rust/15 polyglot sharedlib/meson.build @@ -1,20 +1,15 @@ project('adder', 'c', 'rust', version: '1.0.0') -if build_machine.system() != 'linux' - error('MESON_SKIP_TEST, this test only works on Linux. Patches welcome.') -endif +subdir('zero') -thread_dep = dependency('threads') -dl_dep = meson.get_compiler('c').find_library('dl', required: false) -m_dep = meson.get_compiler('c').find_library('m', required: false) - -rl = static_library('radder', 'adder.rs', rust_crate_type: 'staticlib') +rl = shared_library('radder', 'adder.rs', + rust_abi: 'c', + link_with: [zero_shared, zero_static]) l = shared_library('adder', 'adder.c', - c_args: '-DBUILDING_ADDER', - link_with: rl, - version: '1.0.0', - soversion: '1', - link_args: '-Wl,-u,adder_add', # Ensure that Rust code is not removed as unused. - dependencies: [thread_dep, dl_dep, m_dep]) + c_args: '-DBUILDING_ADDER', + link_with: rl, + version: '1.0.0', + soversion: '1', +) test('adder', executable('addertest', 'addertest.c', link_with: l)) diff --git a/test cases/rust/15 polyglot sharedlib/zero/meson.build b/test cases/rust/15 polyglot sharedlib/zero/meson.build new file mode 100644 index 0000000..ec7ecf7 --- /dev/null +++ b/test cases/rust/15 polyglot sharedlib/zero/meson.build @@ -0,0 +1,6 @@ +# They both have the same name, this tests we use +verbatim to distinguish them +# using their filename. It also ensures we pass the importlib on Windows. +# Those libs are in a subdir as regression test: +# https://github.com/mesonbuild/meson/issues/12484 +zero_shared = shared_library('zero', 'zero.c') +zero_static = static_library('zero', 'zero_static.c') diff --git a/test cases/rust/15 polyglot sharedlib/zero/zero.c b/test cases/rust/15 polyglot sharedlib/zero/zero.c new file mode 100644 index 0000000..02672f3 --- /dev/null +++ b/test cases/rust/15 polyglot sharedlib/zero/zero.c @@ -0,0 +1,11 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT int zero(void); + +int zero(void) { + return 0; +} diff --git a/test cases/rust/15 polyglot sharedlib/zero/zero_static.c b/test cases/rust/15 polyglot sharedlib/zero/zero_static.c new file mode 100644 index 0000000..7f14fb4 --- /dev/null +++ b/test cases/rust/15 polyglot sharedlib/zero/zero_static.c @@ -0,0 +1,6 @@ +int zero_static(void); + +int zero_static(void) +{ + return 0; +} diff --git a/test cases/rust/20 transitive dependencies/diamond/func.c b/test cases/rust/20 transitive dependencies/diamond/func.c new file mode 100644 index 0000000..c07ab72 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/func.c @@ -0,0 +1,4 @@ +int c_func(void); +int c_func(void) { + return 123; +} diff --git a/test cases/rust/20 transitive dependencies/diamond/main.c b/test cases/rust/20 transitive dependencies/diamond/main.c new file mode 100644 index 0000000..c633e9a --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/main.c @@ -0,0 +1,5 @@ +int r3(void); + +int main_func(void) { + return r3() == 246 ? 0 : 1; +} diff --git a/test cases/rust/20 transitive dependencies/diamond/meson.build b/test cases/rust/20 transitive dependencies/diamond/meson.build new file mode 100644 index 0000000..dc48d45 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/meson.build @@ -0,0 +1,25 @@ +# Regression test for a diamond dependency graph: +# ┌►R1┐ +# main-►R3─┤ ├─►C1 +# └►R2┘ +# Both libr1.rlib and libr2.rlib used to contain func.c.o. That was causing +# libr3.rlib to have duplicated func.c.o and then libmain.so failed to link: +# multiple definition of `c_func'. + +libc1 = static_library('c1', 'func.c') +libr1 = static_library('r1', 'r1.rs', link_with: libc1) +libr2 = static_library('r2', 'r2.rs', link_with: libc1) +libr3 = static_library('r3', 'r3.rs', + link_with: [libr1, libr2], + rust_abi: 'c', +) +shared_library('main', 'main.c', link_whole: [libr3]) + +# Same dependency graph, but r3 is now installed. Since c1, r1 and r2 are +# not installed, r3 must contain them. +libr3 = static_library('r3-installed', 'r3.rs', + link_with: [libr1, libr2], + rust_abi: 'c', + install: true, +) +shared_library('main-installed', 'main.c', link_with: [libr3]) diff --git a/test cases/rust/20 transitive dependencies/diamond/r1.rs b/test cases/rust/20 transitive dependencies/diamond/r1.rs new file mode 100644 index 0000000..7afb711 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/r1.rs @@ -0,0 +1,9 @@ +extern "C" { + fn c_func() -> i32; +} + +pub fn r1() -> i32 { + unsafe { + c_func() + } +} diff --git a/test cases/rust/20 transitive dependencies/diamond/r2.rs b/test cases/rust/20 transitive dependencies/diamond/r2.rs new file mode 100644 index 0000000..ee73ee2 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/r2.rs @@ -0,0 +1,9 @@ +extern "C" { + fn c_func() -> i32; +} + +pub fn r2() -> i32 { + unsafe { + c_func() + } +} diff --git a/test cases/rust/20 transitive dependencies/diamond/r3.rs b/test cases/rust/20 transitive dependencies/diamond/r3.rs new file mode 100644 index 0000000..9794b7e --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/r3.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub fn r3() -> i32 { + r1::r1() + r2::r2() +} diff --git a/test cases/rust/20 transitive dependencies/meson.build b/test cases/rust/20 transitive dependencies/meson.build index e5354b8..b786e64 100644 --- a/test cases/rust/20 transitive dependencies/meson.build +++ b/test cases/rust/20 transitive dependencies/meson.build @@ -25,3 +25,5 @@ exe = executable('footest', 'foo.c', link_with: foo, ) test('footest', exe) + +subdir('diamond') diff --git a/test cases/rust/20 transitive dependencies/test.json b/test cases/rust/20 transitive dependencies/test.json new file mode 100644 index 0000000..0d98c23 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/test.json @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libr3-installed.a"} + ] +} |