From ffac5e0d14ee4ba2ff961ac278c61ef91717caa3 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 15 Jun 2023 22:08:46 +1000 Subject: [PATCH] Add support for order-only inputs Now actions that trigger the archive tool to be rebuilt will not cause existing downloads/extractions to be redone. --- build/ninja_gen/src/archives.rs | 4 ++-- build/ninja_gen/src/build.rs | 30 +++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/build/ninja_gen/src/archives.rs b/build/ninja_gen/src/archives.rs index 075c22e81..a6392e76a 100644 --- a/build/ninja_gen/src/archives.rs +++ b/build/ninja_gen/src/archives.rs @@ -88,7 +88,7 @@ impl BuildAction for DownloadArchive { let (_, filename) = self.archive.url.rsplit_once('/').unwrap(); let output_path = Utf8Path::new("download").join(filename); - build.add_inputs("archives_bin", inputs![":build:archives"]); + build.add_order_only_inputs("archives_bin", inputs![":build:archives"]); build.add_variable("url", self.archive.url); build.add_variable("checksum", self.archive.sha256); build.add_outputs("out", &[output_path.into_string()]) @@ -135,7 +135,7 @@ where } fn files(&mut self, build: &mut impl crate::build::FilesHandle) { - build.add_inputs("archive_tool", inputs![":build:archives"]); + build.add_order_only_inputs("archive_tool", inputs![":build:archives"]); build.add_inputs("in", inputs![self.archive_path.clone()]); let folder = self.extraction_folder(); diff --git a/build/ninja_gen/src/build.rs b/build/ninja_gen/src/build.rs index 5d4690c14..5ae5696b0 100644 --- a/build/ninja_gen/src/build.rs +++ b/build/ninja_gen/src/build.rs @@ -209,6 +209,7 @@ struct BuildStatement<'a> { implicit_outputs: Vec, explicit_inputs: Vec, explicit_outputs: Vec, + order_only_inputs: Vec, output_subsets: Vec<(String, Vec)>, variables: Vec<(String, String)>, rule_variables: Vec<(String, String)>, @@ -234,6 +235,7 @@ impl BuildStatement<'_> { implicit_outputs: Default::default(), explicit_inputs: Default::default(), explicit_outputs: Default::default(), + order_only_inputs: Default::default(), variables: Default::default(), rule_variables: Default::default(), output_subsets: Default::default(), @@ -269,8 +271,13 @@ impl BuildStatement<'_> { let action_name = self.rule_name; self.implicit_inputs.sort(); self.implicit_outputs.sort(); - let inputs_str = to_ninja_target_string(&self.explicit_inputs, &self.implicit_inputs); - let outputs_str = to_ninja_target_string(&self.explicit_outputs, &self.implicit_outputs); + let inputs_str = to_ninja_target_string( + &self.explicit_inputs, + &self.implicit_inputs, + &self.order_only_inputs, + ); + let outputs_str = + to_ninja_target_string(&self.explicit_outputs, &self.implicit_outputs, &[]); writeln!(buf, "build {outputs_str}: {action_name} {inputs_str}").unwrap(); for (key, value) in self.variables.iter().sorted() { @@ -329,6 +336,7 @@ pub trait FilesHandle { /// this is often `in`. fn add_inputs(&mut self, variable: &'static str, inputs: impl AsRef); fn add_inputs_vec(&mut self, variable: &'static str, inputs: Vec); + fn add_order_only_inputs(&mut self, variable: &'static str, inputs: impl AsRef); /// Add a variable that can be referenced in the command. fn add_variable(&mut self, name: impl Into, value: impl Into); @@ -400,6 +408,14 @@ impl FilesHandle for BuildStatement<'_> { } } + fn add_order_only_inputs(&mut self, variable: &'static str, inputs: impl AsRef) { + let inputs = FilesHandle::expand_inputs(self, inputs); + if !variable.is_empty() { + self.add_variable(variable, space_separated(&inputs)) + } + self.order_only_inputs.extend(inputs); + } + fn add_variable(&mut self, key: impl Into, value: impl Into) { self.variables.push((key.into(), value.into())); } @@ -479,12 +495,20 @@ impl FilesHandle for BuildStatement<'_> { } } -fn to_ninja_target_string(explicit: &[String], implicit: &[String]) -> String { +fn to_ninja_target_string( + explicit: &[String], + implicit: &[String], + order_only: &[String], +) -> String { let mut joined = space_separated(explicit); if !implicit.is_empty() { joined.push_str(" | "); joined.push_str(&space_separated(implicit)); } + if !order_only.is_empty() { + joined.push_str(" || "); + joined.push_str(&space_separated(order_only)); + } joined }