Xaldew
Xaldew

Reputation: 668

Rust Cargo CMake Integration with C++ Library Dependencies

Let us say that I have Rust project that wants to use a CMake based C++ library. For that, I use a build.rs script something like below that uses the cmake and cxx packages to build an external project (spikes):

let path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let external = path.join("external");
let spikes = external.join("spikes");
if spikes.exists()
{
    println!("cargo:rustc-cfg=spikes");
    let ccl_includes = spikes.join("src");
    let dst = cmake::Config::new(spikes).build();
    let lib = "spikes_common";
    println!("cargo:rustc-link-search=native={}/lib/spikes", dst.display());
    println!("cargo:rustc-link-lib=static={}", lib);

    // Attempt to build the C++-bridge.
    cxx_build::bridge("src/imageio_cxx.rs")
        .file("external/imageio-bridge.cpp")
        .include(spikes_includes)
        .flag_if_supported("-std=c++17")
        .compile("libimageio-bridge");
    println!("cargo:rerun-if-changed=external/imageio-bridge.h");
    println!("cargo:rerun-if-changed=external/imageio-bridge.cpp");
}

This works fine for the most part, but I can't seem to find any documentation on how to handle link dependencies from the C++ project. E.g., in the above example the C++ library uses OpenEXR, but naturally, the linker flags are not propagated to the Rust project, making it fail during the compilation linking step. What is the current best practice for propagating linker flags from a C++ project to Cargo?

Upvotes: 2

Views: 1227

Answers (1)

Milan Š.
Milan Š.

Reputation: 1638

So based on what I've read about this cargo crate I can forsee 3 options:

  • You scrape the cmake files for the appropriate flags construct a string slice and pass it to the bridge
  • You manually type them out
  • Or this hackish solution: via pkg-config if applicable pkg-config just pastes out what you specify to paste out.

If you go with option 3 you have then two options on how to get it in

  1. I don't see under the hood of cxx.rs, but perhaps you could pass it to the flags_if_possible - I've done similar hacks before in qmake.
  2. You could just execute the command, grab the output and create a string slice that you input into the same method.

Hope it helps!

EDIT: If there is a cmake file then IIRC cmake has a feature to generate pkg-config files from its targets.

Upvotes: 2

Related Questions