简体   繁体   中英

How can I link libraries to my C code and use that in a Rust binary?

I am trying to include a C file in my Rust project. The C file uses system dependencies. Below is a minimal example that does not compile when I run cargo build .

If I take the failing command that Cargo is running and I append "-l" "nl-genl-3" "-l" "nl-3" the command does succeed. Is it putting the the linker flags in the wrong place, because those flags definitely are in the command?

src/main.rs

#[link(name = "nl-genl-3")]
#[link(name = "nl-3")]
extern "C" {
    fn nl_test(help_me_pls: usize) -> usize;
}

fn main() {
    unsafe {
        println!("nl.c function result: {:?}", nl_test(6));
    }
}

src/nl.c

#include <linux/nl80211.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>

int nl_test(int help_me_pls) {
    struct nl_sock* socket = nl_socket_alloc();
    nl_socket_free(socket);
    return help_me_pls;
}

build.rs

extern crate cc;

fn main() {
    cc::Build::new()
        .include("/usr/include/libnl3")
        .file("src/nl.c")
        .compile("libnl.a");
}

Cargo.toml

[package]
name = "derp"
version = "0.1.0"

[build-dependencies]
cc = "1.0"

I get the following output when I run cargo build

   Compiling cc v1.0.18
   Compiling derp v0.1.0 (file:///root/derp)
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.1vmrdj4gsxr690x4.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.1y16o1qfye96o7m0.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.3rngp6bm2u2q5z0y.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.4oc10dk278mpk1vy.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.4xq48u46a1pwiqn7.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.51s1w397y42gpez1.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.8xzrsc1ux72v29j.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.oa3rad818d8sgn4.rcgu.o" "-o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "/root/derp/target/debug/deps" "-L" "/root/derp/target/debug/build/derp-c3cdcf1fbd0c70b2/out" "-L" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib" "-l" "nl-genl-3" "-l" "nl-3" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "nl" "-Wl,--no-whole-archive" "-Wl,--start-group" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-774f1a5992f88ec5.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libpanic_unwind-a65ab1ab71045d14.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc_jemalloc-5cced33d7a39db8e.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libunwind-76fba694360269fc.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc_system-b3f660c2be971c37.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liblibc-64d840c62d40ace0.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc-b3d8b67c899d207d.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcore-d9124265921c5963.rlib" "-Wl,--end-group" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcompiler_builtins-1aad7d9a81def783.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util"
  = note: /root/derp/target/debug/build/derp-c3cdcf1fbd0c70b2/out/libnl.a(nl.o): In function `nl_test':
          /root/derp/src/nl.c:6: undefined reference to `nl_socket_alloc'
          /root/derp/src/nl.c:7: undefined reference to `nl_socket_free'
          collect2: error: ld returned 1 exit status

From the Cargo documentation for build scripts :

rustc-link-lib=[KIND=]NAME indicates that the specified value is a library name and should be passed to the compiler as a -l flag. The optional KIND can be one of static , dylib (the default), or framework , see rustc --help for more details.

Add this to your build script:

println!("cargo:rustc-link-lib=nl-genl-3");
println!("cargo:rustc-link-lib=nl-3");

And remove the link attributes from your Rust code.


The problem is that your linker flags are stating that the Rust code needs to link to the C libraries, but that's not fully true. Your C code needs to link to the libraries, and your Rust code needs to link to the compiled C code. If you look at the arguments, you'll see this (abridged) output

  • deps/derp-5a7445c256565e2d.1vmrdj4gsxr690x4.rcgu.o (your Rust code)
  • -l nl-genl-3 (system library)
  • -l nl-3 (system library)
  • -l nl (your C shim)

Argument order to linkers is important. If something isn't needed when the object is processed by the linker, it won't be used .

Here, the Rust code adds a dependency on code from the nl library, so the linker is on the lookout for those symbols. When nl-3 and nl-genl-3 are processed, we don't need any of the symbols from them, so they are mostly ignored. When nl is processed, we resolve the dependency from the Rust code, but nl needs the symbols from nl-genl-3 and nl-3 , which will not be processed again.

It's not obvious, but the compile method from cc automatically prints out a cargo:rustc-link-lib line to tie its build result into your Rust code.

See also:

Here it is how I solved it Rust + .so lib . Hope It would help

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM