diff --git a/src/cmd/script.rs b/src/cmd/script.rs index a06b1b95..53ca3253 100644 --- a/src/cmd/script.rs +++ b/src/cmd/script.rs @@ -462,7 +462,7 @@ fn emit_template( all_defines.extend( src.defines .iter() - .map(|(k, &v)| (k.to_string(), v.map(String::from))), + .map(|(k, (_, v))| (k.to_string(), v.map(String::from))), ); all_incdirs.extend(src.clone().get_incdirs()); @@ -569,7 +569,7 @@ fn emit_template( local_defines.extend( src.defines .iter() - .map(|(k, &v)| (k.to_string(), v.map(String::from))), + .map(|(k, (_, v))| (k.to_string(), v.map(String::from))), ); add_defines(&mut local_defines, &args.define); diff --git a/src/config.rs b/src/config.rs index fc0a64af..52440cf0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -232,8 +232,8 @@ pub struct Sources { pub target: TargetSpec, /// The directories to search for include files, with their target specs. pub include_dirs: Vec<(TargetSpec, PathBuf)>, - /// The preprocessor definitions. - pub defines: IndexMap>, + /// The preprocessor definitions, with their target specs. + pub defines: IndexMap)>, /// The source files. pub files: Vec, /// The files in this source will override other files. @@ -918,6 +918,46 @@ impl Validate for PartialIncludeDir { } } +/// A partial filtered preprocessor define +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct PartialDefine { + /// The target spec for which the define applies + pub target: Option, + /// The define value (None for valueless defines) + pub value: Option, + /// Unknown extra fields + #[serde(flatten)] + pub extra: HashMap, +} + +impl FromStr for PartialDefine { + type Err = Void; + fn from_str(s: &str) -> std::result::Result { + Ok(PartialDefine { + target: None, + value: Some(s.into()), + extra: HashMap::new(), + }) + } +} + +impl Validate for PartialDefine { + type Output = (TargetSpec, Option); + type Error = Error; + fn validate(self, vctx: &ValidationContext) -> Result<(TargetSpec, Option)> { + if !vctx.pre_output { + self.extra.iter().for_each(|(k, _)| { + Warnings::IgnoreUnknownField { + field: k.clone(), + pkg: vctx.package_name.to_string(), + } + .emit(); + }); + } + Ok((self.target.unwrap_or(TargetSpec::Wildcard), self.value)) + } +} + /// A partial group of source files. #[derive(Serialize, Deserialize, Debug, Default)] pub struct PartialSources { @@ -926,7 +966,7 @@ pub struct PartialSources { /// The directories to search for include files. pub include_dirs: Option>>, /// The preprocessor definitions. - pub defines: Option>>, + pub defines: Option>>>, /// The source file paths. pub files: Option>, /// A sv file. @@ -1139,7 +1179,10 @@ impl Validate for PartialSources { if let Some(eq_idx) = file.find("=") { ( file[..eq_idx].to_string(), - Some(file[eq_idx + 1..].to_string()), + Some(StringOrStruct(PartialDefine { + value: Some(file[eq_idx + 1..].to_string()), + ..Default::default() + })), ) } else { (file.to_string(), None) @@ -1251,7 +1294,18 @@ impl Validate for PartialSources { }) .collect::>>()?; - let defines = defines.unwrap_or_default(); + let defines: IndexMap)> = defines + .unwrap_or_default() + .into_iter() + .map(|(name, partial)| { + let (trgt, value) = if let Some(partial) = partial { + partial.validate(vctx)? + } else { + (TargetSpec::Wildcard, None) + }; + Ok((name, (trgt, value))) + }) + .collect::>()?; let files: Result> = post_glob_files .into_iter() .map(|f| f.validate(vctx)) diff --git a/src/sess.rs b/src/sess.rs index 490c0df8..485af82d 100644 --- a/src/sess.rs +++ b/src/sess.rs @@ -410,7 +410,12 @@ impl<'ctx> Session<'ctx> { let defines = sources .defines .iter() - .map(|(k, v)| (k.clone(), v.as_ref().map(|v| self.intern_string(v)))) + .map(|(k, (trgt, v))| { + ( + k.clone(), + (trgt.clone(), v.as_ref().map(|v| self.intern_string(v))), + ) + }) .collect(); let files = sources .files diff --git a/src/src.rs b/src/src.rs index 6cb37feb..37a84044 100644 --- a/src/src.rs +++ b/src/src.rs @@ -33,8 +33,8 @@ pub struct SourceGroup<'ctx> { pub include_dirs: Vec<(TargetSpec, &'ctx Path)>, /// The directories exported by dependent package for include files, with their target specs. pub export_incdirs: IndexMap>, - /// The preprocessor definitions. - pub defines: IndexMap>, + /// The preprocessor definitions, with their target specs. + pub defines: IndexMap)>, /// The files in this group. pub files: Vec>, /// Package dependencies of this source group @@ -148,14 +148,23 @@ impl<'ctx> SourceGroup<'ctx> { .cloned() .collect(); + let mut defines: IndexMap)> = self + .defines + .iter() + .filter(|(_, (trgt, _))| trgt.matches(&all_targets)) + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); let mut target_defs = all_targets .into_iter() .map(|t| "TARGET_".to_owned() + &t.to_uppercase()) .collect::>(); target_defs.sort(); - let mut defines: IndexMap> = self.defines.clone(); if self.package.is_some() { - defines.extend(target_defs.into_iter().map(|t| (t, None))); + defines.extend( + target_defs + .into_iter() + .map(|t| (t, (TargetSpec::Wildcard, None))), + ); } let export_incdirs = self @@ -356,7 +365,7 @@ impl<'ctx> SourceGroup<'ctx> { grp.defines = self .defines .iter() - .map(|(k, v)| (k.clone(), *v)) + .map(|(k, v)| (k.clone(), v.clone())) .chain(grp.defines.into_iter()) .collect(); grp.flatten_into(into); diff --git a/src/util.rs b/src/util.rs index b05281cc..029ab065 100644 --- a/src/util.rs +++ b/src/util.rs @@ -107,6 +107,34 @@ where Ok(T::from_str(value).unwrap()) } + fn visit_bool(self, value: bool) -> std::result::Result + where + E: de::Error, + { + self.visit_str(if value { "true" } else { "false" }) + } + + fn visit_i64(self, value: i64) -> std::result::Result + where + E: de::Error, + { + self.visit_str(&value.to_string()) + } + + fn visit_u64(self, value: u64) -> std::result::Result + where + E: de::Error, + { + self.visit_str(&value.to_string()) + } + + fn visit_f64(self, value: f64) -> std::result::Result + where + E: de::Error, + { + self.visit_str(&value.to_string()) + } + fn visit_map(self, visitor: M) -> std::result::Result where M: de::MapAccess<'de>,