为什么 Rust 在构建 DLL 时导出其整个标准库?
Why does Rust export its whole standard library when building a DLL?
我目前正在尝试用 Rust 编写一个动态库,它将从现有程序中加载。我需要导出一些具有特定名称和调用约定的函数。一切正常,但一旦我 use
标准库中的任何内容:
- DLL 大小膨胀到超过 3MiB(不是很漂亮,但我可以接受)
- 整个标准库从 DLL 中导出。这是包含所有导出的列表:http://pastebin.com/LsG1u96C(5100 个函数)
我是否遗漏了一些编译器开关?
我用 rustc
编译了以下代码,没有任何选项:
#![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
是唯一应该导出的函数。
这是在 Windows 8.1 机器上 rustc 1.0.0-nightly (522d09dfe 2015-02-19)
(x86)
更新:看起来用rustc -C prefer-dynamic
编译动态链接文件时,DLL大小缩小到60kiB,只有3个额外的导出(http://pastebin.com/G0AYZrpF),看起来都很合理。但我还是更喜欢静态链接库。
最近添加了新的 crate 类型 "cdylib",它可能更适合您的用例。将源文件的第一行替换为:
#![crate_type = "cdylib"]
当使用 Cargo 包管理器而不是直接调用 rustc
更新 Cargo.toml
以包含以下行时:
[lib]
crate-type = ["cdylib"]
有关详细信息,请查看 Rust pull request #33553。
在我的测试中,它将以下简单 "Hello World" DLL 的大小从 650k (dylib) 减小到 8k (cdylib)。导出符号的数量也大幅减少。
#[no_mangle]
pub extern fn hello_rust() -> *const u8 {
"Hello, world![=12=]".as_ptr()
}
我目前正在尝试用 Rust 编写一个动态库,它将从现有程序中加载。我需要导出一些具有特定名称和调用约定的函数。一切正常,但一旦我 use
标准库中的任何内容:
- DLL 大小膨胀到超过 3MiB(不是很漂亮,但我可以接受)
- 整个标准库从 DLL 中导出。这是包含所有导出的列表:http://pastebin.com/LsG1u96C(5100 个函数)
我是否遗漏了一些编译器开关?
我用 rustc
编译了以下代码,没有任何选项:
#![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
是唯一应该导出的函数。
这是在 Windows 8.1 机器上 rustc 1.0.0-nightly (522d09dfe 2015-02-19)
(x86)
更新:看起来用rustc -C prefer-dynamic
编译动态链接文件时,DLL大小缩小到60kiB,只有3个额外的导出(http://pastebin.com/G0AYZrpF),看起来都很合理。但我还是更喜欢静态链接库。
最近添加了新的 crate 类型 "cdylib",它可能更适合您的用例。将源文件的第一行替换为:
#![crate_type = "cdylib"]
当使用 Cargo 包管理器而不是直接调用 rustc
更新 Cargo.toml
以包含以下行时:
[lib]
crate-type = ["cdylib"]
有关详细信息,请查看 Rust pull request #33553。
在我的测试中,它将以下简单 "Hello World" DLL 的大小从 650k (dylib) 减小到 8k (cdylib)。导出符号的数量也大幅减少。
#[no_mangle]
pub extern fn hello_rust() -> *const u8 {
"Hello, world![=12=]".as_ptr()
}