How to specify CMake dep in Rust, if Rust exe is built within CMake?

I use CMake+ninjabuild as the top level build system

Within CMake:

  1. there is a C++ static library called foo which is built by CMake add_library
  2. There is a C++ executable called bar which links foo
  3. There is a Rust execuable called example-rs, which is built inside CMake by
    add_custom_command(COMMAND cargo build -p example-rs)
    This executable need to link foo

What is the best way to specify that example-rs needs to build after foo?

I need cmake --build . --target all to build all of foo, bar and example-rs
Currently it is done by add_custom_command(COMMAND cargo build -p example-rs DEPENDS foo)

But this makes cargo test be unware of the dependency, so I have to manually rebuild foo,
before cargo test during development

The alternative solution would be using cmake crate in,
which build foo within,
but I do not know how to solve the diamond problem.

The top level cmake and the cmake called within uses the same CMAKE_BINARY_DIR,
The top level cmake and cmake may both compile foo in parallel,
so this may cause a conflict in disk file.

The problem above may be solved by using both add_custom_command(DEPENDS) and,
but what if there are two Rust executables within CMake project, which both needs to link foo?
When cargo test, if both of them rebuilding foo within, there is also a conflict.

NOTE: Creating multiple cmake build directory (CMAKE_BINARY_DIR) is not preferred.
The project is big and CMake configuration takes several minutes.

Can't you somehow launch cargo test as a custom command from cmake and make it depend on foo?

add_custom_command(COMMAND cargo test -p example-rs DEPENDS foo)

This is very complicate, and I want to simplify run cargo test without need to -p

Also I found this project example that claims to also be able to call rust unit tests from cmake

The standard way to do that is to make foo-sys crate that has which checks an env variable like FOO_LIB_DIR to emit linking instructions for Cargo. It will have to assume the foo lib is already built, as otherwise you'd end up with a sandwich of cmake -> cargo -> -> cmake.

1 Like