How to run other workspace binaries in `build.rs`?

I have a cargo workspace with two crates: A binary crate, asset-packer, that does some code generation and another, gui, that should invoke asset-packer as part of its build script. Currently, cargo build (in gui) deadlocks with the message "Blocking waiting for file lock on build directory." What's the best way to locate and run the program?

Edit: I've worked around this by putting the build-time code into asset-packer's library. I'm still interested in the answer to my original question, though.

gui/build.rs:

fn main() {
    std::process::Command::new("cargo")
        .args(vec!["run", "-p", "asset-packer"])
        .status()
        .unwrap();
}

gui/Cargo.toml:

[package]
name = "gui"
version = "0.1.0"
authors = ["e"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[[bin]]
name = "demo"

[lib]

[dependencies]
sdl2 = {version = "0.34.3", features=["bundled", "static-link"]}
crossbeam = "0.8.0"

[dev-dependencies]
asset-packer = { path = "../asset-packer" }

Root Cargo.toml:

[workspace]

members = ["gui", "asset-packer"]

asset-packer/Cargo.toml:

[package]
name = "asset-packer"
version = "0.1.0"
authors = ["e"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

If you turn asset-packer into a library crate, then you can add is as a build-dependency of the gui crate.
In your build.rs you can then invoke asset-packer by calling the necessary functions.
asset-packer can still provide a binary, that is a small wrapper around the library itself for manual invocation.

If that's not an option for you then the best way will be to use some external tooling to build asset-packer first, e.g. using a Makefile, then invoking it by a full path directly.

2 Likes