我正在尝试使用 MSVC 工具链制作一个静态链接到 libusb 的 Rust 程序,但它在运行时因缺少 DLL 而崩溃:
error: process didn't exit successfully: `target\debug\test_libusb.exe` (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)
我用了Dependency Walker发现丢失的DLL是LIBUSB-1.0.DLL。将它添加到项目中可以解决问题,动态链接所有内容也是如此,但我想避免使用此解决方案。
我的起点是这个 libusb-sys crate ,但由于它不起作用,我制作了一个更简单的类似 crate 。我从 vcpkg 得到了 libusb。
libusb-sys/src/lib.rs
extern crate libc;
use libc::c_char;
#[repr(C)]
pub struct libusb_version {
pub major: u16,
pub minor: u16,
pub micro: u16,
pub nano: u16,
pub rc: *const c_char,
pub describe: *const c_char,
}
#[link(name = "libusb-1.0", kind = "static")]
extern "C" {
pub fn libusb_get_version() -> *const libusb_version;
}
libusb-sys/Cargo.toml
[package]
name = "libusb-sys"
version = "0.1.0"
build = "build.rs"
link = "libusb-1.0"
[dependencies]
libc = "0.2"
libusb-sys/build.rs
fn main() {
println!("
cargo:rustc-link-lib=static=libusb-1.0
cargo:rustc-link-search=native=C:/vcpkg/packages/libusb_x64-windows/lib")
}
然后我在程序的箱子上使用了它:
test_libusb/src/main.rs
extern crate libusb_sys as ffi;
fn main() {
unsafe {
let version = ffi::libusb_get_version();
println!(
"libusb v{}.{}.{}.{}",
(*version).major,
(*version).minor,
(*version).micro,
(*version).nano
);
}
}
test_libusb/Cargo.toml
[package]
name = "test_libusb"
version = "0.1.0"
[dependencies]
"libusb-sys" = { path = "../libusb-sys" }
这是完整的编译器输出,以防有帮助:
G:\programming\rust\test_libusb> cargo run --verbose
Compiling libc v0.2.58
Compiling libusb-sys v0.1.0 (G:\programming\rust\libusb-sys)
Running `rustc --crate-name build_script_build C:\Users\slysherz\.cargo\registry\src\github.com-1ecc6299db9ec823\libc-0.2.58\build.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 --cfg "feature=\"default\"" --cfg "feature=\"std\"" -C metadata=f83941a94611be11 -C extra-filename=-f83941a94611be11 --out-dir G:\programming\rust\test_libusb\target\debug\build\libc-f83941a94611be11 -L dependency=G:\programming\rust\test_libusb\target\debug\deps --cap-lints allow`
Running `rustc --crate-name build_script_build G:\programming\rust\libusb-sys\build.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=71e53c2aee584c72 -C extra-filename=-71e53c2aee584c72 --out-dir G:\programming\rust\test_libusb\target\debug\build\libusb-sys-71e53c2aee584c72 -C incremental=G:\programming\rust\test_libusb\target\debug\incremental -L dependency=G:\programming\rust\test_libusb\target\debug\deps`
Running `G:\programming\rust\test_libusb\target\debug\build\libusb-sys-71e53c2aee584c72\build-script-build`
Running `G:\programming\rust\test_libusb\target\debug\build\libc-f83941a94611be11\build-script-build`
Running `rustc --crate-name libc C:\Users\slysherz\.cargo\registry\src\github.com-1ecc6299db9ec823\libc-0.2.58\src\lib.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg "feature=\"default\"" --cfg "feature=\"std\"" -C metadata=b67580e06366e753 -C extra-filename=-b67580e06366e753 --out-dir G:\programming\rust\test_libusb\target\debug\deps -L dependency=G:\programming\rust\test_libusb\target\debug\deps --cap-lints allow --cfg libc_priv_mod_use --cfg libc_union --cfg libc_const_size_of --cfg libc_align --cfg libc_core_cvoid --cfg libc_packedN`
Running `rustc --crate-name libusb_sys G:\programming\rust\libusb-sys\src\lib.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=94e8ef72b03c18f5 -C extra-filename=-94e8ef72b03c18f5 --out-dir G:\programming\rust\test_libusb\target\debug\deps -C incremental=G:\programming\rust\test_libusb\target\debug\incremental -L dependency=G:\programming\rust\test_libusb\target\debug\deps --extern libc=G:\programming\rust\test_libusb\target\debug\deps\liblibc-b67580e06366e753.rlib -L native=C:/vcpkg/packages/libusb_x64-windows/lib -l static=libusb-1.0`
Compiling test_libusb v0.1.0 (G:\programming\rust\test_libusb)
Running `rustc --crate-name test_libusb src\main.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=8f2bb1a8f56e2223 -C extra-filename=-8f2bb1a8f56e2223 --out-dir G:\programming\rust\test_libusb\target\debug\deps -C incremental=G:\programming\rust\test_libusb\target\debug\incremental -L dependency=G:\programming\rust\test_libusb\target\debug\deps --extern libusb_sys=G:\programming\rust\test_libusb\target\debug\deps\liblibusb_sys-94e8ef72b03c18f5.rlib -L native=C:/vcpkg/packages/libusb_x64-windows/lib`
Finished dev [unoptimized + debuginfo] target(s) in 1.20s
Running `target\debug\test_libusb.exe`
error: process didn't exit successfully: `target\debug\test_libusb.exe` (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)
即使在使用 VS 2017 从头开始编译 libusb 后,我仍然收到链接错误:
= note: test_libusb-528eb6acc7e5c681.3w5rrhap2r2yw5if.rcgu.o : error LNK2019: unresolved external symbol libusb_get_version referenced in function _ZN11test_libusb4main17hcb0c36db62706c3bE
G:\programming\rust\test_libusb\target\debug\deps\test_libusb-528eb6acc7e5c681.exe : fatal error LNK1120: 1 unresolved externals
当我直接从第一个 crate 调用这个函数时,它仍然有效。
我最近开始学习 Rust,所以我不确定它是如何工作的。为什么 Rust 会尝试在这种情况下加载 DLL?
最佳答案
@Shepmaster 是对的,vcpkg 的 libusb:x64-windows 三元组仅包含尝试从 DLL 调用实际函数的定义。
我试图从一个简单的 C 程序加载这个库,但我得到了完全相同的错误:
测试.c
#include "C:\vcpkg\installed\x64-windows\include\libusb-1.0\libusb.h"
int main()
{
const struct libusb_version *version = libusb_get_version();
printf("Version %d.%d.%d", version->major, version->minor, version->micro);
}
编译:
cl test.c /link C:\vcpkg\installed\x64-windows\lib\libusb-1.0.lib
导致相同的缺少 DLL 错误。但是,如果我使用不同的 libusb:x64-windows-static 三元组:
测试.c
#pragma comment(lib, "Advapi32.lib")
#include "C:\vcpkg\installed\x64-windows-static\include\libusb-1.0\libusb.h"
int main()
{
const struct libusb_version *version = libusb_get_version();
printf("Version %d.%d.%d", version->major, version->minor, version->micro);
}
编译:
cl test.c /link C:\vcpkg\installed\x64-windows-static\lib\libusb-1.0.lib
工作得很好:
>test.exe
Version 1.0.22
总而言之,如果您想将 Rust 程序静态链接到 libusb,请下载 vspkg并安装
vcpkg.exe install libusb:x64-windows-static
.
设置环境变量 LIBUSB_DIR
指向C:\vcpkg\installed\x64-windows-static
并通过将其放入您的
Cargo.toml:
[dependencies]
libusb = "0.3"
libusb-sys = "0.2.3"
[patch.crates-io]
"libusb-sys" = { git = "https://github.com/cmsd2/libusb-sys" }
关于windows - Rust 程序需要 libusb DLL 存在,即使它是静态链接的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56564751/