15

I'm currently trying to write a dynamic library with Rust which will be loaded from a existing program. I need to export a few functions with specific names and calling conventions. Everything works, but as soon as I use anything from the standard library:

  • The DLL size balloons to over 3MiB (Not exactly pretty, but I could live with that)
  • The whole standard library gets exported from the DLL. Here is a lists with all exports: http://pastebin.com/LsG1u96C (5100 functions)

Am I missing some compiler switch? I compile the following code with rustc without any options:

#![crate_type = "dylib"]
#![feature(std_misc)]

use std::ffi::CString;

#[link(name = "user32")]
#[allow(non_snake_case)]
extern "stdcall" {
    fn MessageBoxA(hWnd: u32, lpText: *const i8, lpCaption: *const i8, uType: u32) -> u32;
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "stdcall" fn _AddLuaState(lua_state_ptr: u32)
{
    let info_str = format!("Lua State Created: {}!", lua_state_ptr);
    let info_cstring = CString::new(info_str).unwrap();
    let caption = CString::new("Hello from my Rust Library!").unwrap();
    MessageBoxA(0, info_cstring.as_ptr(), caption.as_ptr(), 0);
}

_AddLuaState@4 is the only function that should be exported.

This is on a Windows 8.1 machine with rustc 1.0.0-nightly (522d09dfe 2015-02-19) (x86)

Update: It looks like when compiling a dynamically linked file with rustc -C prefer-dynamic, the DLL size shrinks to 60kiB and there are only 3 extra exports (http://pastebin.com/G0AYZrpF) which all look quite reasonable. But I'd still prefer a statically linked library.

dbeinder
  • 153
  • 1
  • 6
  • Does compiling with optimizations (`rustc -O`, `cargo build --release`) have any effect? Note that cargo puts release / non-release binaries in different directories. – Shepmaster Feb 21 '15 at 22:19
  • 1
    Compiling with optimizations only shrinks the library by a few kiB, but has no other effect, the same happens with the cargo release build. But compiling with `-C prefer-dynamic` has an effect, please see my updated post. – dbeinder Feb 21 '15 at 22:39
  • Do `-C lto` or `-C link-args=--gc-sections` do anything? I've got no idea myself, just chucking it out there. – Lambda Fairy Feb 22 '15 at 00:23
  • Link-Time-Optimization only works on static libraries, but I could get it to compile with `rustc -C link-args=-Wl,--gc-sections ldbg.rs`. Unfortunately, no effect here either. – dbeinder Feb 22 '15 at 09:40

1 Answers1

5

Recently the new crate type "cdylib" has been added that likely better fits your use-case. Replace the first line of your source file with:

#![crate_type = "cdylib"]

When using the Cargo package manager instead of directly calling rustc update Cargo.toml to contain the following lines:

[lib]
crate-type = ["cdylib"]

For more details have a look at Rust pull request #33553.

In my test it decreased the size of the following simple "Hello World" DLL from 650k (dylib) down to 8k (cdylib). Also the number of exported symbols is decreased massively.

#[no_mangle]
pub extern fn hello_rust() -> *const u8 {
    "Hello, world!\0".as_ptr()
}
blerontin
  • 2,892
  • 5
  • 34
  • 60