Avoiding locking issues / finding build artifacts

I have a workspace with two crates; one builds a wasm library, and the other builds a http server (for using the wasm client lib). wasm-pack is used to build the wasm library and generate its bindgen js file.

I'd like the http server crate to automatically build/generate the wasm library, and perform some post-processing on it. The naive solution to this is to call wasm-pack on the wasm library crate from the http server's build script, and then have the build script do the post-processing. However, calling cargo build from a build script on another crate that shares the same target-dir causes a deadlock.

A primary reason I want to build the wasm library from the http server's build script is because I want the wasm library to be written to the http server's OUT_DIR.

I need to find a way to build the wasm library at an alternative location that doesn't cause a deadlock. I can think of a few ways to do this, none make me happy, but some are more soul-crushing than others:

  • Have the developer pass an environment variable to the alternative location. (This is the sort of thing I've been working hard to avoid since I started using cargo for project management, so it would be particularly painful to do this).
  • Use some de-facto standard location for temporary storage, like $TMP or $TEMP. I don't like this either; Rust build directories can be massive, and it's kind of rude to dump massive amounts of data in tmp.
  • Based on the http server's OUT_DIR, traverse up the parent directories until an sibling target directory can be constructed that will avoid locking issues. The annoying thing with this is that the only guarantee cargo seems to provide with regards to the target directory, from a crate's build script's perspective, is that OUT_DIR is safe to use, but it doesn't say anything about it's specific location (read: depth) in target-dir.

Not to mention that for all of these cargo clean won't clean the alternative target-dir.

Looking for ideas on how to solve this, in particular if there are any prior art solutions that are not frowned upon [too much].

My solution to wasm-related build problems (not locking specifically, but mutually incompatible dependencies/features, and I might eventually do the build script thing you’re doing) is to keep the wasm package not a member of the main workspace, while still being in a subdirectory. This means the build can proceed independently and there’s a standard no-configuration location for its separate build directory.

Of course, this does mean that you need to run separate Cargo commands (cargo clean, cargo update, etc.) on it, which is a significant disadvantage. I work around that with an xtask to manage running all desired commands.

1 Like

I have configured rust-analyzer to enable the rust-analyzer.cargo.targetDir setting to avoid target dir collisions. (And I had to do the same kind of configuration for a separate Rust IDE package that I use for displaying prettier error messages).

If your server build tool doesn't already pass something like --target-dir target/my-builder to cargo, I highly recommend it. It's important to make sure it's a subdirectory of ./target so that cargo clean will remove them all at once.

I haven't had any more problems with "waiting for lock file" messages since I did all of this extra work to separate the target dirs. Everything that needs to run cargo can do so independently, but it takes some effort to find and configure them all.

One minor problem with this is that running cargo with a different working directory than your top-level repository will end up with target dirs littering the file system. And cargo clean will not be able to find those. Try to limit cargo invocations to the top-level directory only.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.