aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2021-02-23 11:05:47 -0800
committerNirbheek Chauhan <nirbheek@centricular.com>2021-06-07 20:05:11 +0530
commit1346725ec987f0dc40d94259942c49bc90a35ac6 (patch)
treea6d921ce91ed3d5eb435fe1d7f69f02d1d817e94
parentd031a684a689e29c1dbbf75ad36709171d56abdf (diff)
downloadmeson-1346725ec987f0dc40d94259942c49bc90a35ac6.zip
meson-1346725ec987f0dc40d94259942c49bc90a35ac6.tar.gz
meson-1346725ec987f0dc40d94259942c49bc90a35ac6.tar.bz2
Add a rust test for internal c linkage
We have code to support this, but no tests. That seems pretty bad. And better yet, it doesn't work on MSVC in some cases.
-rw-r--r--mesonbuild/backend/ninjabackend.py17
-rw-r--r--test cases/rust/16 internal c dependencies/lib.c6
-rw-r--r--test cases/rust/16 internal c dependencies/lib.h22
-rw-r--r--test cases/rust/16 internal c dependencies/main.rs9
-rw-r--r--test cases/rust/16 internal c dependencies/meson.build14
-rwxr-xr-xtest cases/rust/16 internal c dependencies/test.py25
6 files changed, 88 insertions, 5 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 7dc7d06..0be5873 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1608,12 +1608,19 @@ int dummy;
# 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))]
+ elif d.typename == 'static library':
+ # Rustc doesn't follow Meson's convention that static libraries
+ # are called .a, and implementation libraries are .lib, so we
+ # have to manually handle that.
+ if rustc.linker.id == 'link':
+ args += ['-C', f'link-arg={self.get_target_filename_for_linking(d)}']
+ else:
+ args += ['-l', f'static={d.name}']
+ external_deps.extend(d.external_deps)
else:
- # Rust uses -l for non rust dependencies, but we still need to add (shared|static)=foo
- _type = 'static' if d.typename == 'static library' else 'dylib'
- args += ['-l', f'{_type}={d.name}']
- if d.typename == 'static library':
- external_deps.extend(d.external_deps)
+ # Rust uses -l for non rust dependencies, but we still need to
+ # add dylib=foo
+ args += ['-l', f'dylib={d.name}']
for e in external_deps:
for a in e.get_link_args():
if a.endswith(('.dll', '.so', '.dylib')):
diff --git a/test cases/rust/16 internal c dependencies/lib.c b/test cases/rust/16 internal c dependencies/lib.c
new file mode 100644
index 0000000..e852de6
--- /dev/null
+++ b/test cases/rust/16 internal c dependencies/lib.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+#include "lib.h"
+
+void c_func(void) {
+ printf("This is a " MODE " C library\n");
+}
diff --git a/test cases/rust/16 internal c dependencies/lib.h b/test cases/rust/16 internal c dependencies/lib.h
new file mode 100644
index 0000000..847bd16
--- /dev/null
+++ b/test cases/rust/16 internal c dependencies/lib.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#if defined _WIN32 || defined __CYGWIN__
+ #if defined BUILDING_ADDER
+ #define DLL_PUBLIC __declspec(dllexport)
+ #else
+ #define DLL_PUBLIC __declspec(dllimport)
+ #endif
+#else
+ #if defined __GNUC__
+ #if defined BUILDING_ADDER
+ #define DLL_PUBLIC __attribute__ ((visibility("default")))
+ #else
+ #define DLL_PUBLIC
+ #endif
+ #else
+ #pragma message("Compiler does not support symbol visibility.")
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+DLL_PUBLIC void c_func(void);
diff --git a/test cases/rust/16 internal c dependencies/main.rs b/test cases/rust/16 internal c dependencies/main.rs
new file mode 100644
index 0000000..5383599
--- /dev/null
+++ b/test cases/rust/16 internal c dependencies/main.rs
@@ -0,0 +1,9 @@
+extern "C" {
+ fn c_func();
+}
+
+fn main() {
+ unsafe {
+ c_func();
+ }
+}
diff --git a/test cases/rust/16 internal c dependencies/meson.build b/test cases/rust/16 internal c dependencies/meson.build
new file mode 100644
index 0000000..c7476d7
--- /dev/null
+++ b/test cases/rust/16 internal c dependencies/meson.build
@@ -0,0 +1,14 @@
+project('internal dependencies', 'c', 'rust')
+
+test_prog = find_program('test.py')
+
+static = static_library('static', 'lib.c', c_args : '-DMODE="static"')
+exe = executable('static', 'main.rs', link_with : static)
+test('static linkage', test_prog, args : [exe, 'This is a static C library'])
+
+# Shared linkage with rust doesn't work on macOS with meson, yet
+if host_machine.system() != 'darwin'
+ shared = shared_library('shared', 'lib.c', c_args : '-DMODE="shared"')
+ exe = executable('shared', 'main.rs', link_with : shared)
+ test('shared linkage', test_prog, args : [exe, 'This is a shared C library'])
+endif
diff --git a/test cases/rust/16 internal c dependencies/test.py b/test cases/rust/16 internal c dependencies/test.py
new file mode 100755
index 0000000..dacec12
--- /dev/null
+++ b/test cases/rust/16 internal c dependencies/test.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import argparse
+import subprocess
+import sys
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument('command')
+ parser.add_argument('expected')
+ args = parser.parse_args()
+
+ out = subprocess.run(args.command, stdout=subprocess.PIPE)
+ actual = out.stdout.decode().strip()
+
+ if args.expected != actual:
+ print('expected:', args.expected, file=sys.stderr)
+ print('actual: ', actual, file=sys.stderr)
+ sys.exit(1)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()