Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Conditionally run task if files have changed on set directory #611

Closed
kaphula opened this issue Nov 24, 2021 · 11 comments
Closed
Assignees

Comments

@kaphula
Copy link

kaphula commented Nov 24, 2021

Hey,

Is it possible to conditionally skip or include steps based on changes on the filesystem? I read about watch but that's not really what I am looking for, I think. I would like to able to run a separate binary crate on my workspace before compiling and running my main application IF certain directory's contents have changed since the last time cargo make was run.

[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true

[tasks.pre-process-stuff]
# execute this task only if files have changed on a specified directory
condition="..."
command="cargo"
args=["run", "--bin", "name_of_crate"]

[tasks.run-main-app]
command="cargo"
args=["run", "--bin", "run_the_main_app"]

[tasks.go]
dependencies = [
    "pre-process-stuff",
    "run-main-app"
]
@sagiegurari
Copy link
Owner

It is a valid request, however, currently it is not supported.
To support it, i would require to 'cache' some state on the file system that currently I do not manage at all (apart of a global one for the entire machine).
Usually the more specific binaries do that, for example cargo build would not rebuild files that were not changed or not impacted by some change, same goes for other compilers.
i'm guessing in your case, the binary you want to call, doesn't support it so you would prefer to have that logic in cargo-make.

@kaphula
Copy link
Author

kaphula commented Nov 24, 2021

The crate I want to call is my own and in the same Rust workspace as the rest of my application, so I could in theory add the required watch logic in it directly. And yes, I wanted to see if there's a tool available that does this for me automatically, preferably something very close to Rust and Cargo.

I would use the Rust's own build scripts by running the run_the_main_app's build.rs and calling Command::new("cargo run --bin name_of_crate ...") or whatever inside of it, but this does not work because you can't run Cargo within the same workspace again because the Cargo lock file is shared between the crates of the workspace and it will hang the whole process.

@sagiegurari
Copy link
Owner

i wonder if something like in #436 could help?
its using duckscript to check if path is newer than other path and based on it, run a task.
would that help?

@sagiegurari
Copy link
Owner

@kaphula did you look at that issue i mentioned? i have there duckscript script that checks if path is newer than call some cargo make task. maybe it is useful for you as well?

@kaphula
Copy link
Author

kaphula commented Nov 30, 2021

Thanks for the advice, I'll keep that in mind for the future but I don't currently have time to play around with this now. I settled for a solution that is based on pure Cargo/Rust commands. You can close this issue if you want.

@ModProg
Copy link

ModProg commented Feb 25, 2022

I stumbled upon the same issue, I will be able to solve it via duck script I think, but I would still like something like this.

I imagined like a glob that can be specified to be checked for changes.

In my case it is to run yarn in a subfolder to generate some files I include, the command I use is quite slow even without changes so it would be great to be able to have a condition like changed_since_last_build="website/src/*"

@sagiegurari
Copy link
Owner

like i explained before, it would mean cargo-make would need to know what your command does and where the output is.
otherwise, it can't compare timestamps.
using duckscript you can tell it how and what to compare.
basically it means, you would never be really able just to say: 'do if these files were updated' in any tool unless the tool knows what the output of that command is.
for example compilers know what they are creating, so they can do only delta.
tools that create their own cache of the build output also can support it.
cargo-make generates nothing at the moment and i think it helps make things simpler.

using globs in duckscript could make your code pretty generic and no need to maintain much logic.
for example, if its checking if java file was compiled to a class you can do:

[tasks.compile-if-updated]
script = [
'''
#!@duckscript

source_files = glob_array ./src/main/**/*.java
for source_file in ${source_files}
  output_file = replace ${source_file} .java .class
  output_file = replace ${output_file} src/main/java/ ./target/classes/
  existing_file = is_file ${output_file}
  should_compile = set true
  if ${existing_file}
    should_compile = is_path_newer ${source_file} ${output_file}
  end
  echo checking source file: ${source_file} output file: ${output_file} output exists: ${existing_file} should compile: ${should_compile}

  if ${should_compile}
    echo found updates
    cm_run_task compile
    exit 0
  end
end
'''
]

[tasks.compile]
command = "echo"
args = ["compiling...."]

@ModProg
Copy link

ModProg commented Feb 27, 2022

I get what you mean by that, I just wonder if this might be an often enough usecase that I might want to say, run this, if any file in this glob is newer than any file in the other glob.

e.g.

any_newer= {src=["src/*.js", "static/*.html"], target=["out/*"]}

@sagiegurari
Copy link
Owner

the mapping is an issue. js might stay js and html might get converted to js.
i could create some task with the deckscript script that you can extend and just give it the params like source, target and task to invoke but i do not think it would cover all cases

@ModProg
Copy link

ModProg commented Feb 27, 2022

the mapping is an issue. js might stay js and html might get converted to js.

I didn't want anything that advanced.
Just any file in src should be newer than every file in target.

While that does not cover all cases, if one wants specific behavior based on a file to file mapping they probably need to use duckscript.

@sagiegurari
Copy link
Owner

i might be able to do something for that...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants