How to handle diamond dependency when use Rust with CMake?

I am using CMake as the top level build tool.

The target all is used to build everything, which can be called by

I am trying to:

all depends on Bar, which is a CMake target
all depends on Alice, which is added to CMake by calling cargo by add_custom_command
Bar depends on Foo, which is specified by CMake builtin function add_dependencies
Alice also depends on Foo, which is specified by cargo build.rs by using cmake crate to build Foo

The problem:
I want to use the following single command to build everything

cmake --build . --target all

which will build Foo, AND run cmake --build . --target Foo, in parallel
This would cause race condition that Foo may be built twice in parallel.

What is the good practice to solve this problem?

Note:
I want Rust code to be re-built using cargo without callling cmake

You could make all build Foo before building Alice, and modify build.rs of Alice to use a pre-built Foo library (crates usually use an env var like FOO_LIB=dir for this).

1 Like

This is what I currently doing,
but I lost the ability to keep track of all deps using cargo

I think a solution should specify dependency of Alice -> Foo in both CMake and build.rs,
and pass some environment variables to skip building in build.rs,
when using CMake to build all.

You'll have to deal with this on case-by-case basis. Cargo has no integration with cmake. There were some plans to do so, but they never went anywhere. Handling of arbitrary C dependencies is painfully hard to unify.

You can use cargo tree and look for -sys crates that need handling.

Alternatively, you can make Cargo handle your top-level all project, and convert everything else to sys crates, potentially avoiding use of cmake entirely.

You may have a better experience asking on a cmake-specific forum, as most people here are glad they don't have to use cmake and that rust has cargo instead.

Ditch Cargo and cmake and use a buildsystem that can build Rust and C++. Like Buck 2 (which is actually written in Rust, so it's easy to install).