Is there any way to set dependency between 2 sub-projects in a workspaces?

I'm building a Tauri app which has a sidecar binary, so conceptually the Tauri app depends on another subproject's output.

The problem is, I cannot set this dependency in anywhere, the sidecar subproject is not a lib but an executable, so I cannot directly put it into the [dependencies] section of the main app.

Right now I've to write a build script to build the sidecar before building the main app, but it's too ad-hoc-ish, and it's a mess to re-implement all update-then-rebuild logic comprehensively.

Can anyone help to provide some idea about this?

This will be possible with artifact dependencies, which is currently an unstable feature usable only on nightly Rust. Give it a try, if you can, and report back how it works for your use case.

Thanks for the info!

The feature works great in my scenario, except one thing.

Tauri supports Universal Binaries on macOS, which bundle both x86_64 and arm64 architectures into a single executable, that means the sidecar binary also needs to be a Universal Binary, so the building process will be:

  1. Build sidecar for both x86_64 and aarch64
  2. Use lipo to combine them into a single Universal Binary
  3. Build the main app for both architectures
  4. Bundle the Universal Binary sidecar into the main app

In this case, the build script needs to build both arch for sidecar, before building any arch for the main app, so this feature seems not fit well here.

If you are building a macOS gui app you aren't going to be able to use just cargo for building anyway. You need something wrapping around cargo that bundles your executable together with Info.plist into an apl bundle. This something can be responsible for building your sidecar executable too, right? As well as for invoking cargo both for x86_64 and arm64 and producing a universal binary from the cargo output. As for what that something could be, some options are: Shell scripts, the cargo-xtask pattern and a makefile.

Yup, you're absolutely right.
That's why I've to write a script (2 actually, 1 JS and 1 Makefile) to do all things right now.
Seems there is no better way.

OTOH, it could be really useful if Rust can provide a universal-apple-darwin target which can do lipo merging under the hood automatically. Some projects already implement such feature, namely pyo3-maturin and tauri (although sidecar support is half-done).

What targets would that contain? Sure today x86_64 + arm64 makes most sense, but in the past powerpc + x86_64 was the obvious choice and after that x86_64 + x86_64h (regular x86 and x86 for Intel cpus at least as new as Haswell). And who knows, maybe we get arm64 + riscv64 as obvious choice in the future if Apple decides to migrate to riscv64 (although I think that is unlikely to happen for at least a decade if ever).

1 Like

Rust never supported PowerPC version of MacOS, and the latest PowerPC version of MacOS reached EOL 15 years ago.
Apple is actually using the term "Universal2" for x86_64/aarch64 fat binaris right now, that means they may use something like "Universal3" when aarch64+riscv64 appears, then we can use target name like "universal3-apple-darwin".