windows - Rust 程序需要 libusb DLL 存在,即使它是静态链接的

标签 windows rust static-libraries libusb

我正在尝试使用 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并通过将其放入您的

来使用 libusb-sys 的补丁版本

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/

相关文章:

c++ - 如何在我的dll中集成第三方库?

c++ - 链接器和图书馆员中的 VC++ 2012 Additional Dependencies 选项

asp.net - 在哪里可以找到 IIS Express 的 appcmd.exe?

c - 将 Solaris/Linux 上的 ANSI 代码移植到 Windows Server 2012

rust - 为什么我必须使用仅由我的依赖项使用的宏

multithreading - 在线程之间传递 hashmap 的 channel |陷入循环 | rust

c++ - Qt 无法将静态库中的 *​​.h 包含到我的程序中

c# - 将文本放入 LibreOffice 文档的程序

windows - 从多个文件中删除行

reference - 无法移出借用的内容/无法移出共享引用