Skip to content

Commit 16465e7

Browse files
authored
Merge 3385acc into 2fd5bd9
2 parents 2fd5bd9 + 3385acc commit 16465e7

File tree

8 files changed

+86
-5
lines changed

8 files changed

+86
-5
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Rust object crates
2+
3+
In order to link Rust objects into C/C++ libraries/programs without static
4+
linking all crates/libraries used by the objects, the new 'object' type crate
5+
can be used. It will produce object files instead of libraries from the Rust
6+
sources. The caller is responsible for providing the linking parameters for
7+
any crate/library needed by the Rust objects.
8+
9+
```meson
10+
libstd_rust = meson.get_compiler('c').find_library('std-abcdefgh')
11+
12+
librust = static_library(
13+
'rust',
14+
'librust.rs',
15+
rust_crate_type : 'object',
16+
dependencies: libstd-rust
17+
)
18+
19+
user = executable(
20+
'user,
21+
'user.c',
22+
link_with : librust)
23+
```

docs/yaml/functions/_build_target_base.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,17 @@ kwargs:
291291
292292
If it is a [[static_library]] it defaults to "lib", and may be "lib",
293293
"staticlib", or "rlib". If "lib" then Rustc will pick a default, "staticlib"
294-
means a C ABI library, "rlib" means a Rust ABI.
294+
means a C ABI library, "rlib" means a Rust ABI, "object" means only object
295+
files will be emitted.
295296
296297
If it is a [[shared_library]] it defaults to "lib", and may be "lib",
297298
"dylib", "cdylib", or "proc-macro". If "lib" then Rustc will pick a
298299
default, "cdylib" means a C ABI library, "dylib" means a Rust ABI, and
299300
"proc-macro" is a special rust proceedural macro crate.
300301
301302
"proc-macro" is new in 0.62.0.
303+
304+
"object" is new in 1.1.0 and allows to link Rust object files in C/C++
305+
programs without static linking Rust crates/libraries. The caller must
306+
provide dynamic linking parameters for all crates/libraries used, including
307+
the Rust standard library.

mesonbuild/backend/ninjabackend.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,14 @@ def generate_rust_target(self, target: build.BuildTarget) -> None:
18711871
cratetype = 'rlib'
18721872
else:
18731873
raise InvalidArguments('Unknown target type for rustc.')
1874+
1875+
# Support for building and linking only object files, without static linking crates
1876+
# Note that we don't emit the shared library here (avoid --emit link) as we only want objects
1877+
if cratetype == 'object':
1878+
cratetype = 'cdylib'
1879+
args.extend(['--emit', 'obj', '-C', 'prefer-dynamic'])
1880+
else:
1881+
args.extend(['--emit', 'link'])
18741882
args.extend(['--crate-type', cratetype])
18751883

18761884
# If we're dynamically linking, add those arguments
@@ -1884,7 +1892,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None:
18841892
# Rustc replaces - with _. spaces are not allowed, so we replace them with underscores
18851893
args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_')]
18861894
depfile = os.path.join(target.subdir, target.name + '.d')
1887-
args += ['--emit', f'dep-info={depfile}', '--emit', 'link']
1895+
args += ['--emit', f'dep-info={depfile}']
18881896
args += target.get_extra_args('rust')
18891897
output = rustc.get_output_args(os.path.join(target.subdir, target.get_filename()))
18901898
args += output

mesonbuild/build.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,8 +1931,8 @@ def post_init(self) -> None:
19311931
mlog.debug('Defaulting Rust static library target crate type to rlib')
19321932
self.rust_crate_type = 'rlib'
19331933
# Don't let configuration proceed with a non-static crate type
1934-
elif self.rust_crate_type not in ['rlib', 'staticlib']:
1935-
raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib" or "staticlib"')
1934+
elif self.rust_crate_type not in ['rlib', 'staticlib', 'object']:
1935+
raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib", "staticlib" or "object"')
19361936
# By default a static library is named libfoo.a even on Windows because
19371937
# MSVC does not have a consistent convention for what static libraries
19381938
# are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses
@@ -1949,6 +1949,8 @@ def post_init(self) -> None:
19491949
self.suffix = 'rlib'
19501950
elif self.rust_crate_type == 'staticlib':
19511951
self.suffix = 'a'
1952+
elif self.rust_crate_type == 'object':
1953+
self.suffix = 'o'
19521954
else:
19531955
self.suffix = 'a'
19541956
self.filename = self.prefix + self.name + '.' + self.suffix
@@ -2247,6 +2249,8 @@ def process_kwargs(self, kwargs):
22472249
raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.')
22482250
if rust_crate_type == 'proc-macro':
22492251
FeatureNew.single_use('Rust crate type "proc-macro"', '0.62.0', self.subproject)
2252+
if rust_crate_type == 'object':
2253+
FeatureNew.single_use('Rust crate type "object"', '1.1.0', self.subproject)
22502254

22512255
def get_import_filename(self) -> T.Optional[str]:
22522256
"""
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"stdout": [
33
{
4-
"line": "test cases/failing/54 wrong static crate type/meson.build:7:0: ERROR: Crate type \"cdylib\" invalid for static libraries; must be \"rlib\" or \"staticlib\""
4+
"line": "test cases/failing/54 wrong static crate type/meson.build:7:0: ERROR: Crate type \"cdylib\" invalid for static libraries; must be \"rlib\", \"staticlib\" or \"object\""
55
}
66
]
77
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std::os::raw::c_int;
2+
3+
#[no_mangle]
4+
pub unsafe extern "C" fn print_foo() -> c_int {
5+
let foo = "rust compiler is working";
6+
println!("{}", foo);
7+
0
8+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
project('staticprog', 'c')
2+
3+
rustc = find_program('rustc')
4+
add_languages('rust')
5+
6+
libstd_rust = dependency('std-rust', required: false)
7+
8+
librust = static_library(
9+
'rust',
10+
'librust.rs',
11+
dependencies: libstd_rust,
12+
rust_crate_type: 'object')
13+
14+
if libstd_rust.found()
15+
e = executable('c-program', 'prog.c',
16+
link_with: librust,
17+
install : true
18+
)
19+
test('rusttest', e)
20+
else
21+
# Requires a discoverable std library, most likely via pkg-config,
22+
# but there is no common standard so make it optional for now.
23+
error('MESON_SKIP_TEST: libstd-rust dependency not found')
24+
endif

test cases/rust/20 object link/prog.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdio.h>
2+
3+
int print_foo(void);
4+
5+
int main(void) {
6+
print_foo();
7+
return 0;
8+
}

0 commit comments

Comments
 (0)