使用 Cargo,如何将系统库添加到 link 命令?

Using Cargo, how can I add a system library to the link command?

我正在尝试调用我系统上的标准 C 库 (libstatgrab),但不知道如何将库包含在 link 行中。

我有 Cargo 运行 a build.rs ,输出是:

cargo:rustc-link-lib=statgrab
cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu/

由于我的例子是一个小原型,这里是所有涉及的文件:

src/systemstats.rs

extern crate libc;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct sg_load_stats {
    min1: libc::c_double,
    min5: libc::c_double,
    min15: libc::c_double,
    systime: libc::time_t,
}

extern "C" {
    fn sg_get_load_stats() -> *mut sg_load_stats;
}


fn main() {
    unsafe {
        let load_stats = sg_get_load_stats();
        println!("[load_stats] {:?}", *load_stats);
    }
}

Cargo.toml

[package]
name = "palimpsest"
version = "0.1.0"
authors = ["Savanni D'Gerinel <savanni@luminescent-dreams.com>"]
build = "build.rs"

[dependencies]
libc = "0.2.43"

[[bin]]
name = "systemstats"
path = "src/systemstats.rs"

build.rs

fn main() {
    println!("cargo:rustc-link-lib=statgrab");
    println!("cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu/");
}

最后,构建输出:

root@0a2938cbf3b7:/src/palimpsest# cargo build
   Compiling palimpsest v0.1.0 (file:///src/palimpsest)
   Compiling libc v0.2.43
ls -l error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.1y16o1qfye96o7m0.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.3ewjf7fna93e7dd4.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.3rngp6bm2u2q5z0y.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.4oc10dk278mpk1vy.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.4xq48u46a1pwiqn7.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.51s1w397y42gpez1.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.8xzrsc1ux72v29j.rcgu.o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.oa3rad818d8sgn4.rcgu.o" "-o" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e" "/src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/src/palimpsest/target/debug/deps" "-L" "/usr/lib/x86_64-linux-gnu/" "-L" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/src/palimpsest/target/debug/deps/liblibc-fe86c4c07bd339cb.rlib" "-Wl,--start-group" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-448e7f800092c158.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-187d239173779b21.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-1016cb92bf3e0c0f.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-404ca41e10f51fe1.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-3c640c2d04fa8073.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-6ea835c502ac484a.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-b77d79244be470bc.rlib" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-a51c1c47035430ae.rlib" "-Wl,--end-group" "/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-0413689b51de5d7d.rlib" "-Wl,-Bdynamic" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /src/palimpsest/target/debug/deps/systemstats-a71368fbbfd6ba9e.3ewjf7fna93e7dd4.rcgu.o: In function `systemstats::main':
          /src/palimpsest/src/systemstats.rs:19: undefined reference to `sg_get_load_stats'
          collect2: error: ld returned 1 exit status


error: aborting due to previous error

构建输出读起来很痛苦,但我在其中看到 "-L" "/usr/lib/x86_64-linux-gnu/" 的地方却没有看到 -lstatgrab。我对文件的理解是 cargo:rustc-link-lib=statgrab 应该添加那个标志,但它没有。

令人沮丧的是,我在 MacOS 上完成了一些 linking 到 Cocoa 的工作,我唯一需要的是我的源代码中的一行:#[link(name = "Cocoa", kind = "framework")],所以我不明白为什么我不能在这里使用类似的行,#[link(name = "statgrab", kind = "dylib")]

原来我根本不需要 build.rs。或者,如果库安装在非标准位置,我可能会这样做。不过,我现在可以成功link和运行申请了。

首先,我从 Cargo.toml 中删除了 build = "build.rs"

其次,我回到我的代码并将 #[link(name = "statgrab", kind = "dylib")] 移动到 extern "C" 节之前。

systemstats.rs

extern crate libc;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct sg_load_stats {
    min1: libc::c_double,
    min5: libc::c_double,
    min15: libc::c_double,
    systime: libc::time_t,
}

#[link(name = "statgrab", kind = "dylib")]
extern "C" {
    fn sg_init(ignore_errors: libc::c_int) -> libc::c_int;
    fn sg_get_load_stats() -> *mut sg_load_stats;
}


fn main() {
    unsafe {
        sg_init(1);
        let load_stats = sg_get_load_stats();
        println!("[load_stats] {:?}", *load_stats);
    }
}

然后输出:

root@040ee947460c:/src/palimpsest# cargo run
   Compiling palimpsest v0.1.0 (file:///src/palimpsest)
    Finished dev [unoptimized + debuginfo] target(s) in 1.54s
     Running `target/debug/systemstats`
[load_stats] sg_load_stats { min1: 0.09, min5: 0.05, min15: 0.01, systime: 1540037934 }
root@040ee947460c:/src/palimpsest#