Программа Rust требует наличия библиотеки libusb, даже если она статически связана - PullRequest
3 голосов
/ 12 июня 2019

Я пытаюсь создать программу Rust, которая статически связывается с libusb, используя цепочку инструментов MSVC, но она взрывается во время выполнения из-за отсутствующей 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 , но так как она не работала, я сделал более простой подобный ящик. Я получил libusb от vcpkg.

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 / ЦСИ / 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)

Даже после компиляции libusb с нуля с VS 2017 я все равно получаю ошибку ссылки:

= 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

Когда я вызываю эту функцию напрямую из первого ящика, она работает.

Я недавно начал изучать Rust, поэтому я не уверен, как все это работает. Почему Rust пытается загрузить DLL в этой ситуации?

1 Ответ

0 голосов
/ 23 июля 2019

@ Shepmaster был прав, триплет libusb: x64-windows для vcpkg содержит только определения, которые пытаются вызвать реальные функции из DLL.

Я попытался загрузить эту библиотеку из простой программы на C и получил точно такую ​​же ошибку:

test.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:

test.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" }
...