Canop / bacon

background rust code check
https://dystroy.org/bacon
GNU Affero General Public License v3.0
1.85k stars 66 forks source link

Use bacon with a build.rs script that modifies source files #85

Closed jsimonrichard closed 2 years ago

jsimonrichard commented 2 years ago

I would like to be able to use bacon with the project I'm currently working on, but the project has a build.rs script that generates source files (from protobuf definitions, if you're curious). When clippy (or check) runs, it runs the build.rs script again to make sure everything is up-to-date. However, this changes the source files, so bacon runs clippy again. It gets stuck in a loop.

Proposed Chage: Add a command line option or a config option for excluding a directory from being watched.

Stargateur commented 2 years ago

build.rs shouldn't re run if nothing change, have you put some strange line in your build.rs to ask cargo to rerun everytime ?

jsimonrichard commented 2 years ago

My build.rs script creates other .rs files inside ./src. It's not asking cargo to run directly, but since it's updating the files inside ./src I assumed that that's what is prompting bacon to rerun clippy.

On a side note, I can confirm that running clippy on its own works just fine. This behavior only occurs when running clippy with bacon.

Stargateur commented 2 years ago

it would help to have a reproduction example.

jsimonrichard commented 2 years ago

Here's one: https://github.com/jsimonrichard/bacon-buildrs-reprex/tree/master

I tried using https://github.com/watchexec/cargo-watch with the following command.

cargo watch -x clippy -i src/mymod.rs

The -i flag tells cargo-watch to ignore mymod.rs, and it fixes the issue. Without it, though, cargo-watch gets stuck in a loop just like bacon. Note: It doesn't work if you use ./src/mymod.rs instead of src/mymod.rs because it's supposed to be a glob. I learned that the hard way.

Stargateur commented 2 years ago

It's more up to how cargo see thing, I recommend to not put generated file in src folder, that not a good practice, you can see the example of build.rs:

// build.rs

use std::env;
use std::fs;
use std::path::Path;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("mymod.rs");
    fs::write(
        &dest_path,
        "pub fn message() -> &'static str {
            \"Hello, World!\"
        }
        "
    ).unwrap();
    println!("cargo:rerun-if-changed=build.rs");
}

OUT_DIR is where you should put your artefact then in your code you can do:

include!(concat!(env!("OUT_DIR"), "/mymod.rs"));

This is both more portable and would avoid your problem if you really wish to keep your generated file in src you could add this to your Cargo.toml:

exclude = ["src/mymod.rs"]
jsimonrichard commented 2 years ago

Makes sense, thanks