Binding C lib - build.rs

Hello,
i have a strange problem.
If I change path to relative - it doesn't compile.

Error:

error: could not find native static library `mylib`, perhaps an -L flag is missing?

My builds.rs :


fn main()
{
    let man_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
     
    // absolute path - it's working
    //println!("cargo:rustc-link-search=native=/home/mhanusek/work/VersionControl/my_lib_c/stack/lib");

    // it's not working 
    println!("cargo:rustc-link-search=native={}/../../", man_dir);

    println!("cargo:rustc-flags=-l dylib=stdc++");
    println!("cargo:rerun-if-changed=build.rs");
}

What is the full path of the Cargo.toml?

/home/mhanusek/work/VersionControl/my_lib_c/stack/lib/rust/mylib-sys/Cargo.toml

any ideas?

CARGO_MANIFEST_DIR is a path to the directory containing the Cargo.toml , not a path to the toml itself. Try remove one level of .. from your code.

Edit: miscalculated the directory depth :stuck_out_tongue: Try format!("cargo:rustc-link-search=native={}/../..", man_dir) and see what it contains?

path is ok.

format!("{}/../..", man_dir) == /home/mhanusek/work/VersionControl/my_lib_c/stack/lib

Try fs::canonicalize just in case (or dunce to also support Windows).

It's slightly problematic that the path is outside of your crate. You don't really control where your crate is. If it was published, it would have been inside registry cache in Cargo's private directory. Ideally you should copy stuff to OUT_DIR if you generate it, or expect stuff to be in system-wide directories like /usr/lib which you search for with pkg-config, etc.

1 Like

I tried. Has no effect.

I have a C library /home/mhanusek/work/VersionControl/my_lib_c/stack/lib/mylibc.a

If using fs::canonicalize path doesn't work either, then the problem is not the fact that the path is relative.

Your build.rs lacks rustc-link-lib=static=mylib. Have you just omitted that part in the question, or are you trying to use build.rs of one crate to fix bad paths in another crate? I think you should link and set search path in the same script.

Have you tried

cargo build --verbose

and see what linker command it builds? Are all dirs there?

I'm solved it.
The library file - mylib.a was not creating.

added to build.rs:

    let man_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let lib_path = format!("{}/../../", man_dir);
    let stack_path = format!("{}/../../../", man_dir);

    let lib_abs_path = fs::canonicalize(&lib_path).unwrap().to_string_lossy().to_string();
    let stack_abs_path = fs::canonicalize(&stack_path).unwrap().to_string_lossy().to_string();

    println!("cargo:rustc-link-search=native={}", lib_abs_path);
    println!("cargo:rustc-link-lib=static=mylibc");

    Command::new("make").args(&["APPDIR=lib_c", "PLATFORM=linux", "libmylibc.a"])
        .current_dir(&Path::new(&stack_abs_path))
        .status().unwrap();