Skip to content

Commit bd6003c

Browse files
author
Krusty/Benediction
committed
[bndbuild] Improve behavior of --watch when target is phony
1 parent 318965e commit bd6003c

5 files changed

Lines changed: 72 additions & 20 deletions

File tree

Readme.mkd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
Several demos have been released using this toolchain. However they may not build with the very last version due to its evolution.
77

8+
- 4deKades (2025) <https://www.pouet.net/prod.php?which=103970>, <https://github.com/rgiot/demo.revision2025.4deKades>
89
- J'AI PÉ-TÉLÉCRAN (2024) <https://www.pouet.net/prod.php?which=96575>, <https://github.com/rgiot/demo.revision2024.etchy>
910
- Come Join Us (2024) <https://www.pouet.net/prod.php?which=96537>
1011
- Can Robots Take Control? (2021) <https://www.pouet.net/prod.php?which=88554>

cpclib-bndbuild/src/app.rs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::ops::Deref;
33
use std::process::{Command, Stdio};
44
use std::str::FromStr;
55
use std::sync::Arc;
6+
use std::time::{Duration, Instant};
67

78
use anyhow::Context;
89
use camino::{Utf8Path, Utf8PathBuf};
@@ -40,6 +41,34 @@ pub struct BndBuilderApp {
4041
observers: Arc<ListOfBndBuilderObserverRc>
4142
}
4243

44+
#[derive(Debug, Clone)]
45+
pub enum WatchState {
46+
NoWatch,
47+
WatchFirstRound,
48+
WatchNextRounds{last_build: Instant},
49+
}
50+
51+
impl WatchState {
52+
pub fn request_watch(&self) -> bool {
53+
!matches!(self, WatchState::NoWatch)
54+
}
55+
56+
pub fn disable_phony(&self) -> bool {
57+
match self {
58+
Self::NoWatch => false,
59+
Self::WatchFirstRound => false,
60+
Self::WatchNextRounds{..} => true
61+
}
62+
}
63+
64+
pub fn last_build(&self) -> Option<&Instant> {
65+
match self {
66+
Self::WatchNextRounds{last_build} => Some(last_build),
67+
_ => None
68+
}
69+
}
70+
}
71+
4372
#[derive(Debug)]
4473
pub enum BndBuilderCommandInner {
4574
/// Print the help of the given command
@@ -68,7 +97,7 @@ pub enum BndBuilderCommandInner {
6897
/// Build the corresponding targets
6998
Build {
7099
targets: Option<Vec<Utf8PathBuf>>,
71-
watch: bool,
100+
watch: WatchState,
72101
current_step: usize,
73102
builder: BndBuilder
74103
},
@@ -202,11 +231,12 @@ impl BndBuilderCommand {
202231
/// TODO wire parallal execution
203232
fn execute_build(
204233
init_targets: Option<Vec<Utf8PathBuf>>,
205-
watch: bool,
234+
watch: WatchState,
206235
mut current_step: usize,
207236
builder: BndBuilder,
208237
observers: Arc<ListOfBndBuilderObserverRc>
209238
) -> Result<Option<Self>, BndBuilderError> {
239+
210240
let targets_provided = init_targets.is_some();
211241

212242
// get the list of targets
@@ -227,7 +257,7 @@ impl BndBuilderCommand {
227257
let tgt = &targets[current_step];
228258

229259
// execute if needed
230-
if builder.outdated(tgt)? {
260+
let last_build = if builder.outdated(&watch, tgt)? {
231261
builder.execute(tgt).map_err(|e| {
232262
if targets_provided {
233263
e
@@ -238,7 +268,10 @@ impl BndBuilderCommand {
238268
}
239269
}
240270
})?;
241-
}
271+
Some(Instant::now())
272+
} else {
273+
None
274+
};
242275

243276
// set up the next step if any
244277
let over = init_targets.as_ref().map(|v| v.len() - 1).unwrap_or(0) == current_step;
@@ -250,14 +283,15 @@ impl BndBuilderCommand {
250283
current_step += 1;
251284
}
252285

253-
if over && !watch {
286+
if over && !watch.request_watch() {
254287
Ok(None)
255288
}
256289
else {
290+
std::thread::sleep(Duration::from_millis(2000)); // duration to wait
257291
Ok(Some(BndBuilderCommand {
258292
inner: BndBuilderCommandInner::Build {
259293
targets: init_targets,
260-
watch,
294+
watch: WatchState::WatchNextRounds{last_build: last_build.unwrap_or_else(|| watch.last_build().cloned().unwrap())},
261295
current_step,
262296
builder
263297
},
@@ -834,7 +868,7 @@ impl BndBuilderApp {
834868

835869
Ok(BndBuilderCommandInner::Build {
836870
targets,
837-
watch: watch_requested,
871+
watch: if watch_requested {WatchState::WatchFirstRound} else {WatchState::NoWatch},
838872
current_step: 0,
839873
builder
840874
})

cpclib-bndbuild/src/builder.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use cpclib_common::camino::{Utf8Path, Utf8PathBuf};
88
use cpclib_common::itertools::Itertools;
99
use minijinja::{Environment, Error, ErrorKind, context};
1010

11+
use crate::app::WatchState;
1112
use crate::BndBuilderError;
1213
use crate::event::{
1314
BndBuilderObserved, BndBuilderObserver, BndBuilderObserverRc, ListOfBndBuilderObserverRc,
@@ -287,7 +288,7 @@ impl BndBuilder {
287288
return Err(BndBuilderError::DisabledTarget(p.to_string()));
288289
}
289290

290-
let done = rule.is_up_to_date(Some(p));
291+
let done = rule.is_up_to_date(None, Some(p));
291292
if done {
292293
self.emit_stdout(&format!("Rule {p} already exists\n"));
293294
// nothing to do
@@ -322,8 +323,8 @@ impl BndBuilder {
322323

323324
impl BndBuilder {
324325
#[inline]
325-
pub fn outdated<P: AsRef<Utf8Path>>(&self, target: P) -> Result<bool, BndBuilderError> {
326-
self.inner.borrow_dependent().outdated(target, true)
326+
pub fn outdated<P: AsRef<Utf8Path>>(&self, watch: &WatchState, target: P) -> Result<bool, BndBuilderError> {
327+
self.inner.borrow_dependent().outdated(target, watch,true)
327328
}
328329

329330
#[inline]

cpclib-bndbuild/src/rules/graph.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
use std::collections::{BTreeMap, HashSet};
1+
use std::{collections::{BTreeMap, HashSet}, time::{Instant, SystemTime}};
22

33
use camino::Utf8PathBuf;
4+
use cpclib_asm::file;
45
use cpclib_common::camino::Utf8Path;
56
use cpclib_common::itertools::Itertools;
67
use topologic::AcyclicDependencyGraph;
78

89
use super::{Rule, Rules};
9-
use crate::BndBuilderError;
10+
use crate::{app::WatchState, BndBuilderError};
1011

1112
#[derive(Clone)]
1213
pub struct Graph<'r> {
@@ -62,11 +63,14 @@ impl<'r> Graph<'r> {
6263
pub fn outdated<P: AsRef<Utf8Path>>(
6364
&self,
6465
p: P,
66+
watch: &WatchState,
6567
skip_rules_without_commands: bool
6668
) -> Result<bool, BndBuilderError> {
69+
70+
6771
let p = p.as_ref();
6872
// a phony rule is always outdated
69-
if self.rule(p)?.is_phony() {
73+
if !watch.disable_phony() && self.rule(p)?.is_phony() {
7074
return Ok(true);
7175
}
7276

@@ -77,15 +81,19 @@ impl<'r> Graph<'r> {
7781
let res = match self.rule(p) {
7882
Ok(r) => {
7983
if skip_rules_without_commands {
80-
if r.is_phony() {
81-
false
84+
if r.is_phony() {
85+
match watch {
86+
WatchState::NoWatch => false,
87+
WatchState::WatchFirstRound => { false },
88+
WatchState::WatchNextRounds { last_build } => { false }
89+
}
8290
}
8391
else {
84-
!r.is_up_to_date::<Utf8PathBuf>(None)
92+
!r.is_up_to_date::<Utf8PathBuf>(watch.last_build().cloned(), None)
8593
}
8694
}
8795
else {
88-
!r.is_up_to_date::<Utf8PathBuf>(None)
96+
!r.is_up_to_date::<Utf8PathBuf>(watch.last_build().cloned(),None)
8997
}
9098
},
9199

@@ -94,7 +102,14 @@ impl<'r> Graph<'r> {
94102
return Err(BndBuilderError::UnknownTarget(msg));
95103
}
96104
else {
97-
false
105+
if let Some(last_build) = watch.last_build() {
106+
let file_modification= p.metadata().unwrap().modified().unwrap();
107+
let file_modification = file_modification.elapsed().unwrap();
108+
let last_build = last_build.elapsed();
109+
last_build > file_modification
110+
} else {
111+
false
112+
}
98113
}
99114
},
100115
_ => todo!()

cpclib-bndbuild/src/rules/rule.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::fmt::Display;
2+
use std::time::Instant;
23

34
use cpclib_common::camino::{Utf8Path, Utf8PathBuf};
45
use cpclib_common::itertools::Itertools;
@@ -286,10 +287,10 @@ impl Rule {
286287
}
287288
}
288289

289-
pub fn is_up_to_date<P: AsRef<Utf8Path>>(&self, for_target: Option<P>) -> bool {
290+
pub fn is_up_to_date<P: AsRef<Utf8Path>>(&self, last_build: Option<Instant>, for_target: Option<P>) -> bool {
290291

291292
// phony rules are never up to date
292-
if self.is_phony() {
293+
if self.is_phony() && last_build.is_none() {
293294
return false;
294295
}
295296

0 commit comments

Comments
 (0)