cargo-px
                                
                                 cargo-px copied to clipboard
                                
                                    cargo-px copied to clipboard
                            
                            
                            
                        Avoid regenerating crates unnecessarily
First of all, thanks for the awesome tool. It really feels like an improvement over build scripts for code generation.
I use cargo px to generate ICU data for display purposes with icu_datagen.
However, cargo px regenerates the data module every build, which means that dependent crates also get rebuilt on every run.
It would be nice if we could tell cargo px a set of "input files" and it only regenerates the crate when those files change.
For now, I work around that by running cargo px only to regenerate the crate and using cargo normally otherwise.
But long term, it would be nice to not have to keep the difference in mind.
Hey!
This behaviour is by design. Generators can be fairly complex and cargo px defaults to always invoking the generator, making it responsible for determining if there is any work to be done.
I plan to build some auxiliary libraries to make this straightforward for the most common cases, such as keeping track of changes to a set of files.
It looks somewhat like this:
use std::path::Path;
use std::fs::File;
use std::io::{self, Read};
use sha2::{Sha256, Digest};
fn compute_checksum(paths: &[&Path]) -> io::Result<String> {
    let mut hasher = Sha256::new();
    for path in paths {
        if let Ok(file) = File::open(path) {
            let mut reader = io::BufReader::new(file);
            let mut buffer = [0; 8192]; // Buffer size (adjust as needed)
            loop {
                let bytes_read = reader.read(&mut buffer)?;
                if bytes_read == 0 {
                    break;
                }
                hasher.update(&buffer[..bytes_read]);
            }
        } else {
            // If file doesn't exist or cannot be opened, consider it as an empty file
            let empty_data: &[u8] = &[];
            hasher.update(empty_data);
        }
    }
    let result = hasher.finalize();
    Ok(format!("{:x}", result))
}
You can store the checksum in the metadata section of the manifest of the generated crate using toml_edit.
If the checksum is unchanged, you skip re-generating the module:
// Read the contents of the Cargo.toml file
let toml_content = fs::read_to_string(
    cargo_px_env::generated_pkg_manifest_path().unwrap()
).expect("Failed to read Cargo.toml");
// Parse it
let mut doc = toml_content.parse::<toml_edit::Document>().expect("Failed to parse Cargo.toml");
// Access the metadata.source.checksum field
let old_checksum = doc["package"]["metadata"]["source"]["checksum"]
        .as_value();
I hope this helps!