How to export a symbol from a Rust executable?

rust

Solution

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() {
  // ...
}

Problem

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.

Original source