Reputation: 5271
I'm trying to export a symbol from a Rust executable:
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static exported_symbol: [u8; 1] = *b"\0";
fn main() {
println!("Hello, world!");
}
exported_symbol
doesn't appear to be exported by the resulting binary:
$ cargo build
$ nm ./target/debug/test_export| grep exported_symbol
On the other hand, if I build a library with the same source, the symbol does get exported:
$ rustc --crate-type cdylib src/main.rs
$ nm libmain.so| grep exported_symbol
0000000000016c10 R exported_symbol
I'm using Rust 1.18.0 on Linux x86-64.
Upvotes: 9
Views: 4289
Reputation: 1501
I'd recommend this in the .cargo/config
file instead of the above:
[build]
rustflags = ["-C", "link-args=-rdynamic"]
-rdynamic
is more portable. In particular, it works both on Linux and MacOS.
Also, in current Rust/LLVM versions, unless a symbol is actually used, the linker is very likely to remove it.
In order to avoid this, a dummy function referencing the exported functions should be called (at any point in time, such as in the main
function).
An example of such a function could be:
pub fn init() {
let funcs: &[*const extern "C" fn()] = &[
exported_function_1 as _,
exported_function_2 as _,
exported_function_3 as _
];
std::mem::forget(funcs);
}
And of course, the exported functions should have the #[no_mangle]
property:
#[no_mangle]
pub extern "C" fn exported_function_1() {
// ...
}
Upvotes: 3
Reputation: 288
You can pass linker options to rustc, like:
$ rustc src/main.rs --crate-type bin -C link-args=-Wl,-export-dynamic
$ nm main|grep export
00000000000d79c4 R exported_symbol
You'll probably want to put this in your rustflags in your .cargo/config something like:
[target.x86_64-unknown-linux-gnu]
rustflags = [ "-C", "link-args=-Wl,-export-dynamic" ]
Upvotes: 3