Skip to content

Commit ab859a2

Browse files
committed
rust: get stdlib arguments for non-rust languages when linking
Otherwise we might not get things like libstdc++, which we need.
1 parent 1e8aaca commit ab859a2

File tree

6 files changed

+83
-12
lines changed

6 files changed

+83
-12
lines changed

mesonbuild/backend/ninjabackend.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,11 @@ def generate_rust_target(self, target: build.BuildTarget) -> None:
20402040
if d == '':
20412041
d = '.'
20422042
args += ['-L', d]
2043+
2044+
# Because of the way rustc links, this must come after any potential
2045+
# library need to link with their stdlibs (C++ and Fortran, for example)
2046+
args.extend(target.get_used_stdlib_args('rust'))
2047+
20432048
target_deps = target.get_dependencies()
20442049
has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps)
20452050
has_rust_shared_deps = any(dep.uses_rust()

mesonbuild/build.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,15 @@ class BuildTarget(Target):
698698

699699
install_dir: T.List[T.Union[str, Literal[False]]]
700700

701+
# This set contains all the languages a linker can link natively
702+
# without extra flags. For instance, nvcc (cuda) can link C++
703+
# without injecting -lc++/-lstdc++, see
704+
# https://github.com/mesonbuild/meson/issues/10570
705+
_MASK_LANGS: T.FrozenSet[T.Tuple[str, str]] = frozenset([
706+
# (language, linker)
707+
('cpp', 'cuda'),
708+
])
709+
701710
def __init__(
702711
self,
703712
name: str,
@@ -1579,14 +1588,6 @@ def get_clink_dynamic_linker_and_stdlibs(self) -> T.Tuple['Compiler', T.List[str
15791588
# Languages used by dependencies
15801589
dep_langs = self.get_langs_used_by_deps()
15811590

1582-
# This set contains all the languages a linker can link natively
1583-
# without extra flags. For instance, nvcc (cuda) can link C++
1584-
# without injecting -lc++/-lstdc++, see
1585-
# https://github.com/mesonbuild/meson/issues/10570
1586-
MASK_LANGS = frozenset([
1587-
# (language, linker)
1588-
('cpp', 'cuda'),
1589-
])
15901591
# Pick a compiler based on the language priority-order
15911592
for l in clink_langs:
15921593
if l in self.compilers or l in dep_langs:
@@ -1597,10 +1598,7 @@ def get_clink_dynamic_linker_and_stdlibs(self) -> T.Tuple['Compiler', T.List[str
15971598
f'Could not get a dynamic linker for build target {self.name!r}. '
15981599
f'Requires a linker for language "{l}", but that is not '
15991600
'a project language.')
1600-
stdlib_args: T.List[str] = []
1601-
for dl in itertools.chain(self.compilers, dep_langs):
1602-
if dl != linker.language and (dl, linker.language) not in MASK_LANGS:
1603-
stdlib_args += all_compilers[dl].language_stdlib_only_link_flags(self.environment)
1601+
stdlib_args: T.List[str] = self.get_used_stdlib_args(linker.language)
16041602
# Type of var 'linker' is Compiler.
16051603
# Pretty hard to fix because the return value is passed everywhere
16061604
return linker, stdlib_args
@@ -1616,6 +1614,15 @@ def get_clink_dynamic_linker_and_stdlibs(self) -> T.Tuple['Compiler', T.List[str
16161614

16171615
raise AssertionError(f'Could not get a dynamic linker for build target {self.name!r}')
16181616

1617+
def get_used_stdlib_args(self, link_language: str) -> T.List[str]:
1618+
all_compilers = self.environment.coredata.compilers[self.for_machine]
1619+
all_langs = set(all_compilers).union(self.get_langs_used_by_deps())
1620+
stdlib_args: T.List[str] = []
1621+
for dl in all_langs:
1622+
if dl != link_language and (dl, link_language) not in self._MASK_LANGS:
1623+
stdlib_args.extend(all_compilers[dl].language_stdlib_only_link_flags(self.environment))
1624+
return stdlib_args
1625+
16191626
def uses_rust(self) -> bool:
16201627
return 'rust' in self.compilers
16211628

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright © 2023 Intel Corporation
3+
4+
#include "lib.hpp"
5+
6+
#include <string>
7+
8+
namespace {
9+
10+
uint64_t priv_length(const std::string & str) {
11+
return str.length();
12+
}
13+
14+
}
15+
16+
extern "C" uint64_t lib_length(const char * str) {
17+
return priv_length(str);
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright © 2023 Intel Corporation
3+
4+
#include <cstddef>
5+
#include <cstdint>
6+
7+
extern "C" uint64_t lib_length(const char * str);
8+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright © 2023 Intel Corporation
3+
4+
use std::ffi::CString;
5+
use std::os::raw::c_char;
6+
7+
extern "C" {
8+
fn lib_length(s: *const c_char) -> u64;
9+
}
10+
11+
fn main() {
12+
let len: u64;
13+
unsafe {
14+
let c_str = CString::new("Hello, world!").unwrap();
15+
len = lib_length(c_str.as_ptr());
16+
}
17+
18+
std::process::exit(if len == 13 { 0 } else { 1 })
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright © 2023 Intel Corporation
3+
4+
project(
5+
'Rust and C++',
6+
'rust', 'cpp',
7+
default_options : ['cpp_std=c++14'],
8+
meson_version : '>= 1.2.0',
9+
)
10+
11+
cpplib = static_library('cpp', 'lib.cpp')
12+
exe = executable('main', 'main.rs', link_with : cpplib)
13+
14+
test('main', exe)

0 commit comments

Comments
 (0)