aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py5
-rw-r--r--mesonbuild/build.py31
-rw-r--r--test cases/rust/20 rust and cpp/lib.cpp18
-rw-r--r--test cases/rust/20 rust and cpp/lib.hpp8
-rw-r--r--test cases/rust/20 rust and cpp/main.rs19
-rw-r--r--test cases/rust/20 rust and cpp/meson.build14
6 files changed, 83 insertions, 12 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index b36e125..21d7baf 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2040,6 +2040,11 @@ class NinjaBackend(backends.Backend):
if d == '':
d = '.'
args += ['-L', d]
+
+ # Because of the way rustc links, this must come after any potential
+ # library need to link with their stdlibs (C++ and Fortran, for example)
+ args.extend(target.get_used_stdlib_args('rust'))
+
target_deps = target.get_dependencies()
has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps)
has_rust_shared_deps = any(dep.uses_rust()
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index b952598..1ecab0d 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -698,6 +698,15 @@ class BuildTarget(Target):
install_dir: T.List[T.Union[str, Literal[False]]]
+ # This set contains all the languages a linker can link natively
+ # without extra flags. For instance, nvcc (cuda) can link C++
+ # without injecting -lc++/-lstdc++, see
+ # https://github.com/mesonbuild/meson/issues/10570
+ _MASK_LANGS: T.FrozenSet[T.Tuple[str, str]] = frozenset([
+ # (language, linker)
+ ('cpp', 'cuda'),
+ ])
+
def __init__(
self,
name: str,
@@ -1579,14 +1588,6 @@ You probably should put it in link_with instead.''')
# Languages used by dependencies
dep_langs = self.get_langs_used_by_deps()
- # This set contains all the languages a linker can link natively
- # without extra flags. For instance, nvcc (cuda) can link C++
- # without injecting -lc++/-lstdc++, see
- # https://github.com/mesonbuild/meson/issues/10570
- MASK_LANGS = frozenset([
- # (language, linker)
- ('cpp', 'cuda'),
- ])
# Pick a compiler based on the language priority-order
for l in clink_langs:
if l in self.compilers or l in dep_langs:
@@ -1597,10 +1598,7 @@ You probably should put it in link_with instead.''')
f'Could not get a dynamic linker for build target {self.name!r}. '
f'Requires a linker for language "{l}", but that is not '
'a project language.')
- stdlib_args: T.List[str] = []
- for dl in itertools.chain(self.compilers, dep_langs):
- if dl != linker.language and (dl, linker.language) not in MASK_LANGS:
- stdlib_args += all_compilers[dl].language_stdlib_only_link_flags(self.environment)
+ stdlib_args: T.List[str] = self.get_used_stdlib_args(linker.language)
# Type of var 'linker' is Compiler.
# Pretty hard to fix because the return value is passed everywhere
return linker, stdlib_args
@@ -1616,6 +1614,15 @@ You probably should put it in link_with instead.''')
raise AssertionError(f'Could not get a dynamic linker for build target {self.name!r}')
+ def get_used_stdlib_args(self, link_language: str) -> T.List[str]:
+ all_compilers = self.environment.coredata.compilers[self.for_machine]
+ all_langs = set(all_compilers).union(self.get_langs_used_by_deps())
+ stdlib_args: T.List[str] = []
+ for dl in all_langs:
+ if dl != link_language and (dl, link_language) not in self._MASK_LANGS:
+ stdlib_args.extend(all_compilers[dl].language_stdlib_only_link_flags(self.environment))
+ return stdlib_args
+
def uses_rust(self) -> bool:
return 'rust' in self.compilers
diff --git a/test cases/rust/20 rust and cpp/lib.cpp b/test cases/rust/20 rust and cpp/lib.cpp
new file mode 100644
index 0000000..b08f870
--- /dev/null
+++ b/test cases/rust/20 rust and cpp/lib.cpp
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright © 2023 Intel Corporation
+
+#include "lib.hpp"
+
+#include <string>
+
+namespace {
+
+uint64_t priv_length(const std::string & str) {
+ return str.length();
+}
+
+}
+
+extern "C" uint64_t lib_length(const char * str) {
+ return priv_length(str);
+}
diff --git a/test cases/rust/20 rust and cpp/lib.hpp b/test cases/rust/20 rust and cpp/lib.hpp
new file mode 100644
index 0000000..63093c4
--- /dev/null
+++ b/test cases/rust/20 rust and cpp/lib.hpp
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright © 2023 Intel Corporation
+
+#include <cstddef>
+#include <cstdint>
+
+extern "C" uint64_t lib_length(const char * str);
+
diff --git a/test cases/rust/20 rust and cpp/main.rs b/test cases/rust/20 rust and cpp/main.rs
new file mode 100644
index 0000000..b048cac
--- /dev/null
+++ b/test cases/rust/20 rust and cpp/main.rs
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright © 2023 Intel Corporation
+
+use std::ffi::CString;
+use std::os::raw::c_char;
+
+extern "C" {
+ fn lib_length(s: *const c_char) -> u64;
+}
+
+fn main() {
+ let len: u64;
+ unsafe {
+ let c_str = CString::new("Hello, world!").unwrap();
+ len = lib_length(c_str.as_ptr());
+ }
+
+ std::process::exit(if len == 13 { 0 } else { 1 })
+}
diff --git a/test cases/rust/20 rust and cpp/meson.build b/test cases/rust/20 rust and cpp/meson.build
new file mode 100644
index 0000000..c301012
--- /dev/null
+++ b/test cases/rust/20 rust and cpp/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright © 2023 Intel Corporation
+
+project(
+ 'Rust and C++',
+ 'rust', 'cpp',
+ default_options : ['cpp_std=c++14'],
+ meson_version : '>= 1.2.0',
+)
+
+cpplib = static_library('cpp', 'lib.cpp')
+exe = executable('main', 'main.rs', link_with : cpplib)
+
+test('main', exe)