Linker error on FFI for crate with both lib and bin

I have been working on a project that is based on a lot of legacy C code. And when I got done, I was faced with a linker error that I can't seem to successfully troubleshoot. So I recreated the structure and the build script and implemented a small tutorial project and faced the same exact issue. I was wondering if anyone here can point out the to me what I am doing wrong:

Tree

.
├── build.rs
├── Cargo.lock
├── Cargo.toml
├── doubler
│   ├── doubler.c
│   ├── doubler.h
│   ├── libdoubler.a
│   ├── main.c
│   └── Makefile
├── src
│   ├── bin
│   │   └── main.rs
│   ├── lib.rs
│   └── mylib
│       ├── doubler_wrapper.rs
│       └── mod.rs
└── target

build.rs

extern crate bindgen;
use std::env;
use std::path::PathBuf;
fn main() {
	println!("cargo:rustc-link-search=native={}", "./doubler");
	let bindings = bindgen::Builder::default().header("doubler/doubler.h")
                                                  .trust_clang_mangling(false)
						  .generate_comments(false)
						  .generate().expect("Unable to generate doubler bindings");
        let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
	bindings.write_to_file(out_path.join("doubler.rs")).expect("Could not write doubler bindings");

Cargo.toml

[package]
name = "testproj"
version = "0.1.0"
authors = [""]
edition = "2018"
build = "build.rs"
# links = "doubler"

[lib]
name = "mylib"
path = "src/mylib/mod.rs"

[[bin]]
name = "exe"
path = "src/bin/main.rs"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[build-dependencies]
bindgen="0.51.1"

the bindgen created file

/* automatically generated by rust-bindgen */

extern "C" {
    pub fn doubler(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
}

build error

cargo build --verbose

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.173ey04vu9qrvl76.rcgu.o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.2alj5l3z0mo8w7xx.rcgu.o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.3brkxe18mmvlh010.rcgu.o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.3diojq9si1uzocch.rcgu.o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.3eyal9vq0rg34fxi.rcgu.o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.45uslm8ch3ejm1mx.rcgu.o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.4dcrl0f2u7gus6pi.rcgu.o" "-o" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/exe-ac4fca04e515e330.5074ti90ysowlmin.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps" "-L" "./doubler" "-L" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/ratnadeepb/rust_projs/testproj/target/debug/deps/libmylib-d11f4046302a3935.rlib" "-Wl,--start-group" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-4a76ff35a356aedf.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-e11c7b3b3225afe2.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-13217ede3d276f16.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-621a9ee22da6caa1.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-546c844e8071bbeb.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-be9569e4d599746f.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-47d8845cef2a3bc5.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-017511bce73a530c.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-be7979c57a08057b.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-d6459c4f0817c67c.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-580035dd98451925.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-aee5c24fff305dea.rlib" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-8a55a4098920125a.rlib" "-Wl,--end-group" "/home/ratnadeepb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-9fc4b5be2ba5cc19.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /home/ratnadeepb/rust_projs/testproj/target/debug/deps/libmylib-d11f4046302a3935.rlib(mylib-d11f4046302a3935.4zkvin6clk6h6zmo.rcgu.o): In function `mylib::local_doubler':
          /home/ratnadeepb/rust_projs/testproj/src/mylib/mod.rs:7: undefined reference to `doubler'
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: Could not compile `testproj`.

Caused by:
  process didn't exit successfully: `rustc --edition=2018 --crate-name exe src/bin/main.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=ac4fca04e515e330 -C extra-filename=-ac4fca04e515e330 --out-dir /home/ratnadeepb/rust_projs/testproj/target/debug/deps -C incremental=/home/ratnadeepb/rust_projs/testproj/target/debug/incremental -L dependency=/home/ratnadeepb/rust_projs/testproj/target/debug/deps --extern mylib=/home/ratnadeepb/rust_projs/testproj/target/debug/deps/libmylib-d11f4046302a3935.rlib -L native=./doubler` (exit code: 1)

Your current println!("cargo:..."); in build.rs is specifying the -L flag to the linker, but you are missing the -ldoubler flags.

That's why you need to add:

    println!(
        "cargo:rustc-link-lib=static=doubler"
    );

to the fn main() of your build.rs

These are the two things I found:

  1. Can't simply create a src/bin/main.rs -- needs some more investigation.

  2. This environment variable needs to be added - ./doubler is the library path here
    export LD_LIBRARY_PATH=./doubler/

Thank you for pointing that out. I missed that out in the formatting.

Here is an asciinema with the exact contents of each file:

asciicast