Unable to export not mangled symbol in an executable as libraries can do
trying something like this:
#[no_mangle]
pub extern "C" fn foo()
{
//...stuff...
}
foo() seems to get exported if compiled inside a library, but if compiled in a binary crate it doesn't.
I found this out trying to use gtk builder's "gtk_builder_connect_signals", which requires for not mangled symbols to be exported.
Is this behaviour a bug? or is it a design choice? if so, why?
I'm told by @Aatch that this works on nightly. Which version did you try with?
Steve Klabnik at 2015-05-07 08:59:15
This is actually possible in nightly, though I'm not sure if it's intentional. You can use the linkage attribute
#[linkage = "<linkage>"], replacing "<linkage>" with one of the options on this list: http://llvm.org/docs/LangRef.html#linkage-typesTo export a symbol, you'll want to use "external".
James Miller at 2015-05-07 08:59:22
I'm also surprised that this doesn't work, I would expect this to work:
$ cat foo.rs #[no_mangle] pub extern fn foo() {} fn main() {} $ rustc foo.rs $ nm -g foo | foo # should see the symbol `foo` defined hereAlex Crichton at 2015-05-07 16:30:24
@steveklabnik I tried this on one of the latest nightly (can't remember exactly which, surely not older than a week though)
Maxxie at 2015-05-09 15:53:10
@Aatch I just tried that, no luck (latest nightly).
Maxxie at 2015-05-09 15:55:19
Triaging:
The following does not produce the
foosymbol.cat > foo.rs <<EOF #[no_mangle] pub extern fn foo() {} fn main() {} EOF rustc foo.rs nm -g foo | grep foo # should see the symbol `foo` defined hereTested on
rustc 1.7.0-nightly (d0bac3f14 2016-01-18)Bruno Tavares at 2016-01-18 21:17:27
Taking another look at this after some time I think it's not the exporting symbol part that's not working, but it's got something to do with #[allow(dead_code)], maybe it just suppresses the warning but will still refuse (silently) to compile in the dead code function. I'm thinking this because if I link with a C library requiring the function it's compiled and exported. To test this I used two identical functions, both calling println!() but with different messages. The one function that's needed by the C library works when called from the C library and will have its message in the strings of the program, but the other message from the function not needed by the C library won't be found. Perhaps extern functions shouldn't be considered dead code in any case
Maxxie at 2016-01-21 18:18:42
To support (I hope) the above:
cat > foo.rs <<EOF #[no_mangle] pub extern fn foo() {} fn main() {foo();} EOF rustc foo.rs nm -g foo | grep fooThe code produces the symbol line, it seems that referencing the function makes it being exported properly, if I understand correctly. If I remove
no_mangleandpub externfrom the code abovenmno longer gives the symbol in the outputrustc 1.23.0-nightly (8b22e70b2 2017-10-31)
Cyryl Płotnicki at 2017-11-01 13:54:13
It looks like exporting top-level functions is supported now, but re-exports are still DCE'd.
#[no_mangle] pub use my_helper_lib::exported_fn; // not exported #[no_mangle] extern "C" fn another_fn() {} // this is exported fine fn main() { let lib = libloading::Library::new("my_lib.so").unwrap(); }Not even wrapping the
exported_fnintest::black_boxprevents DCE.Any update on this?
Nick Hynes at 2019-01-27 21:13:49
@nhynes that looks similar to rust-lang/rfcs#2771
Daniel Sommermann at 2021-08-03 23:49:59