Workspaces: How to build c library and use it in local project

I have a Cargo workspace with several packages, including a bin project that creates three binaries: a main Rust application and two helper binaries implemented in c. The c binaries are built using a build.rs script.

The two helpers communicate with the main Rust application over stdio using serialized data structures. I wanted to be able to use Serde for the serialization in the c helper programs. So I created another package in the workspace that exposed a c abi and generated a .so library.

Overall here's what it looks like:

  • Cargo Workspace
    • exopticon package
      • exopticon binary, main Rust application
      • captureworker binary
        • implemented in c
        • built by build.rs
        • depends on exserial.so
      • playbackworker binary
        • implemented in c
        • built by build.rs
        • depends on exserial.so
    • exserial package
      • generates libexserial.so

It basically works now for dev builds but Cargo doesn't really understand the dependency and the paths are hardcoded so release builds and "cargo clippy" don't work. Here's a failing build log: https://gitlab.com/dmattli/exopticon/-/jobs/368920941

How can I depend on the .so library generated by the exserial package, in the exopticon package?

Or what's a better way to structure workspace?

Or maybe is there a way to tell Cargo about non-rust artifact dependencies?

You can view the repository here: https://gitlab.com/dmattli/exopticon

Thanks !

Try user-defined metadata

First add a build.rs to your exserial package, in which use std::env::var("OUT_DIR") to get libexserial.so path, and call println!("cargo:root={}", path); ,also add a "links" property in [package] with some dummy value in order to make it works, see cargo#3544

Finally in exopticon build.rs, retrieve it by environment DEP_<YOUR_DUMMY>_ROOT, then you could get correct path of libexserial.so and pass it to make to get ld works.

In case you're using workspace, both exopticon and exserial OUT_DIR should be same and may could needn't user-defined metadata.