title: Linking to a local C library for Rust with FFI
body: <p>I am trying to wrap a <a href="https://naif.jpl.nasa.gov/naif/toolkit.html" rel="nofollow noreferrer">quite large C library</a> in Rust. I used bindgen to generate the bindings. Rust seems content with those. However, despite my different attempts and my many reads of the <a href="http://doc.crates.io/build-script.html#case-study-building-some-native-code" rel="nofollow noreferrer">build-script docs</a>, I keep on getting linking issues.</p>
  
  <p>The library I'm using has a set of csh script which end up building two <code>.a</code> files: <code>cspice.a</code> and <code>csupport.a</code>. They are both stored in the <code>cspice_linux_gcc_64bit/lib</code> of my project (cf. the tree at bottom).</p>
  
  <p>I currently test the proper binding by calling constants and functions from my tests, cf. <a href="https://github.com/ChristopherRabotin/SPICE/blob/issue-1/src/lib.rs" rel="nofollow noreferrer">lib.rs</a> (on my Github).</p>
  
  <p>I highly suspect that something is wrong with my <code>build.rs</code> or, less likely, my <code>Cargo.toml</code>.</p>
  
  <h1>Linking error</h1>
  
  <pre class="lang-none prettyprint-override"><code>Running `rustc --crate-name spice src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=94c06ffe4bfd7d5f -C extra-filename=-94c06ffe4bfd7d5f --out-dir /home/chris/Workspace/rust/SPICE/target/debug/deps -L dependency=/home/chris/Workspace/rust/SPICE/target/debug/deps -L native=cspice_linux_gcc_64bit/lib -l static=cspice`
  
  error: could not find native static library `cspice`, perhaps an -L flag is missing?
  
  error: Could not compile `spice`.
  
  Caused by:
    process didn't exit successfully: `rustc --crate-name spice src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=94c06ffe4bfd7d5f -C extra-filename=-94c06ffe4bfd7d5f --out-dir /home/chris/Workspace/rust/SPICE/target/debug/deps -L dependency=/home/chris/Workspace/rust/SPICE/target/debug/deps -L native=cspice_linux_gcc_64bit/lib -l static=cspice` (exit code: 101)
  Build failed, waiting for other jobs to finish...
  error: linking with `cc` failed: exit code: 1
    |
    = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/chris/Workspace/rust/SPICE/target/debug/deps/spice-e22b64d176595306.0.o" "-o" "/home/chris/Workspace/rust/SPICE/target/debug/deps/spice-e22b64d176595306" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "-L" "/home/chris/Workspace/rust/SPICE/target/debug/deps" "-L" "cspice_linux_gcc_64bit/lib" "-L" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "cspice" "-Wl,--no-whole-archive" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-163c20e386ec0612.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-bd312ea730ea22d0.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libterm-4959b4e709084e0a.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-35ad9950c7e5074b.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-fb44afc024bbc636.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-14b8f3202acdad6a.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-20a50a22d4c2b1e9.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-b479831207997444.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-10b591f1a68dd370.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-28913dc5a1e63cd7.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-6ecacccb5bdc4911.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_unicode-f4f0ae88f5ad8ad4.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-bfaa82017ca17cb2.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-863b57a66ba6c3e1.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util"
    = note: /usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: cannot find -lcspice
            collect2: error: ld returned 1 exit status
  
  
  error: aborting due to previous error(s)
  
  error: Could not compile `spice`.
  
  Caused by:
    process didn't exit successfully: `rustc --crate-name spice src/lib.rs --emit=dep-info,link -C debuginfo=2 --test -C metadata=e22b64d176595306 -C extra-filename=-e22b64d176595306 --out-dir /home/chris/Workspace/rust/SPICE/target/debug/deps -L dependency=/home/chris/Workspace/rust/SPICE/target/debug/deps -L native=cspice_linux_gcc_64bit/lib -l static=cspice` (exit code: 101)
  </code></pre>
  
  <h1><code>build.rs</code></h1>
  
  <pre><code>extern crate bindgen;
  
  use std::env;
  use std::path::PathBuf;
  
  
  fn main() {
      let out_dir = env::var("OUT_DIR").unwrap();
      // Tell cargo to tell rustc to link the system bzip2
      // shared library.
      println!("cargo:rustc-link-search=native=cspice_linux_gcc_64bit/lib");
      println!("cargo:rustc-link-lib=static=cspice");
      //println!("cargo:rustc-flags=-L cspice_linux_gcc_64bit/lib");
  
      // The bindgen::Builder is the main entry point
      // to bindgen, and lets you build up options for
      // the resulting bindings.
      let bindings = bindgen::Builder::default()
          // The input header we would like to generate
          // bindings for.
          .header("spice_wrapper.h")
          // Finish the builder and generate the bindings.
          .generate()
          // Unwrap the Result and panic on failure.
          .expect("Unable to generate bindings");
  
  
      let out_path = PathBuf::from(out_dir.clone());
      // Write the bindings to the $OUT_DIR/bindings.rs file.
      bindings
          .write_to_file(out_path.join("spice_bindings.rs"))
          .expect("Couldn't write bindings!");
  }
  </code></pre>
  
  <h1><code>Cargo.toml</code></h1>
  
  <pre class="lang-toml prettyprint-override"><code>[package]
  (...)
  links = "cspice"
  build = "build.rs"
  
  [build-dependencies]
  bindgen = "0.26.3"
  
  [dependencies]
  </code></pre>
  
  <h1>Tree</h1>
  
  <pre class="lang-none prettyprint-override"><code>.
  ├── build.rs
  ├── Cargo.lock
  ├── Cargo.toml
  ├── cspice_linux_gcc_64bit
  │   ├── data
  │   ├── doc
  │   ├── etc
  │   ├── exe
  │   ├── include
  │   ├── lib
  │   ├── makeall.csh
  │   └── src
  ├── spice_wrapper.h
  ├── src
  │   └── lib.rs
  └── target
      └── debug
  </code></pre>