Shared scratch for build scripts

github crates.io docs.rs build status

This crate exposes a compile-time temporary directory sharable by multiple crates in a build graph and erased by cargo clean.

The intended usage is from a build.rs Cargo build script, or more likely from a library which is called by other crates' build scripts.

```toml

Cargo.toml

[build-dependencies] scratch = "1.0" ```

```rust // build.rs

fn main() { let dir = scratch::path("mycrate"); // ... write or read inside of that path } ```


Comparisons

Comparison to std::env::var_os("OUT_DIR"):

Comparison to std::env::temp_dir():


Tips

You'll want to consider what happens when Cargo runs multiple build scripts concurrently that access the same scratch dir. In some use cases you likely want some synchronization over the contents of the scratch directory, such as by an advisory [file lock]. On Unix-like and Windows host systems the simplest way to sequence the build scripts such that each one gets exclusive access one after the other is something like:

```rust use std::fs::File; use std::io;

fn main() -> io::Result<()> { let dir = scratch::path("demo"); let flock = File::create(dir.join(".lock"))?; fs2::FileExt::lock_exclusive(&flock)?;

// ... now do work

} ```

This simplest approach is fine for a cache which is slow to fill (maybe a large download) but fast/almost immediate to use. On the other hand if the build scripts using your cache will take a while to complete even if they only read from the scratch directory, a different approach which allows readers to make progress in parallel would perform better.

```rust use std::fs::{self, File}; use std::io;

fn main() -> io::Result<()> { let dir = scratch::path("demo"); let flock = File::create(dir.join(".lock"))?; let sdk = dir.join("thing.sdk");

if !sdk.exists() {
    fs2::FileExt::lock_exclusive(&flock)?;
    if !sdk.exists() {
        let download_location = sdk.with_file_name("thing.sdk.partial");
        download_sdk_to(&download_location)?;
        fs::rename(&download_location, &sdk)?;
    }
    fs2::FileExt::unlock(&flock)?;
}

// ... now use the SDK

} ```

For use cases that are not just a matter of the first build script writing to the directory and the rest reading, more elaborate schemes involving lock_shared might be something to consider.


License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.