diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 5a1d72f..c8d9c84 100755 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -62,6 +62,61 @@ fn configured_install_dir(value: &str, default: &str) -> String { } } +fn split_replacement_spec<'a>(current: &[String], spec: &'a str) -> Option<(&'a str, &'a str)> { + let trimmed = spec.trim(); + if trimmed.is_empty() { + return None; + } + + if let Some((from, to)) = trimmed.split_once("=>") { + return (!from.is_empty() && !to.is_empty()).then_some((from, to)); + } + + let eq_positions: Vec = trimmed.match_indices('=').map(|(idx, _)| idx).collect(); + if eq_positions.is_empty() { + return None; + } + if eq_positions.len() == 1 { + let (from, to) = trimmed.split_once('=')?; + return (!from.is_empty() && !to.is_empty()).then_some((from, to)); + } + + eq_positions + .into_iter() + .filter_map(|idx| { + let from = &trimmed[..idx]; + let to = &trimmed[idx + 1..]; + (!from.is_empty() && !to.is_empty() && current.iter().any(|flag| flag.contains(from))) + .then_some((from, to)) + }) + .max_by_key(|(from, _)| from.len()) +} + +fn apply_replacement_rules(current: &mut [String], replacements: &[String], label: &str) { + for spec in replacements { + let Some((from, to)) = split_replacement_spec(current, spec) else { + if !spec.trim().is_empty() && !current.is_empty() { + crate::log_warn!( + "Skipping invalid {} entry '{}'; expected 'old=>new' or an unambiguous 'old=new'", + label, + spec + ); + } + continue; + }; + + for flag in current.iter_mut() { + *flag = flag.replace(from, to); + } + } +} + +fn replaced_flags(values: &[String], replacements: &[String], label: &str) -> Vec { + let mut current = values.to_vec(); + apply_replacement_rules(&mut current, replacements, label); + current +} + pub(crate) fn install_dirs(flags: &crate::package::BuildFlags) -> InstallDirs { let libdir = configured_install_dir( &flags.libdir, @@ -90,10 +145,26 @@ pub(crate) fn install_dirs(flags: &crate::package::BuildFlags) -> InstallDirs { fn compiler_flag_sets( flags: &crate::package::BuildFlags, ) -> (Vec, Vec, Vec, Vec) { - let mut cflags = flags.cflags.clone(); - let mut cxxflags = flags.cxxflags.clone(); - let mut ldflags = flags.ldflags.clone(); - let ltoflags = flags.ltoflags.clone(); + let mut cflags = replaced_flags( + &flags.cflags, + &flags.replace_cflags, + "build.flags.replace_cflags", + ); + let mut cxxflags = replaced_flags( + &flags.cxxflags, + &flags.replace_cxxflags, + "build.flags.replace_cxxflags", + ); + let mut ldflags = replaced_flags( + &flags.ldflags, + &flags.replace_ldflags, + "build.flags.replace_ldflags", + ); + let ltoflags = replaced_flags( + &flags.ltoflags, + &flags.replace_ltoflags, + "build.flags.replace_ltoflags", + ); if flags.use_lto && !ltoflags.is_empty() { cflags.extend(ltoflags.iter().cloned()); @@ -104,6 +175,14 @@ fn compiler_flag_sets( (cflags, cxxflags, ldflags, ltoflags) } +pub(crate) fn effective_rustflags(flags: &crate::package::BuildFlags) -> Vec { + replaced_flags( + &flags.rustflags, + &flags.replace_rustflags, + "build.flags.replace_rustflags", + ) +} + pub fn standard_build_env( spec: &PackageSpec, cross: Option<&CrossConfig>, @@ -550,6 +629,40 @@ mod tests { ); } + #[test] + fn test_standard_build_env_applies_replace_flag_rules() { + let mut spec = mk_spec(vec!["-D_FORTIFY_SOURCE=3", "-O2"], vec!["-Wl,-O3"]); + spec.build.flags.cxxflags = vec!["-O2".into(), "-stdlib=libc++".into()]; + spec.build.flags.replace_cflags = vec!["_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".into()]; + spec.build.flags.replace_cxxflags = vec!["-stdlib=libc++=>-stdlib=libstdc++".into()]; + spec.build.flags.replace_ldflags = vec!["-O3=>-O2".into()]; + spec.build.flags.ltoflags = vec!["-flto=auto".into()]; + spec.build.flags.replace_ltoflags = vec!["auto=>thin".into()]; + spec.build.flags.use_lto = true; + + let env = standard_build_env(&spec, None, true, true); + assert!( + env.iter() + .any(|(k, v)| k == "CFLAGS" && v == "-D_FORTIFY_SOURCE=2 -O2 -flto=thin"), + "expected replace_cflags and replace_ltoflags to be applied" + ); + assert!( + env.iter() + .any(|(k, v)| { k == "CXXFLAGS" && v == "-O2 -stdlib=libstdc++ -flto=thin" }), + "expected replace_cxxflags to be applied" + ); + assert!( + env.iter() + .any(|(k, v)| k == "LDFLAGS" && v == "-Wl,-O2 -flto=thin"), + "expected replace_ldflags to be applied" + ); + assert!( + env.iter() + .any(|(k, v)| k == "LTOFLAGS" && v == "-flto=thin"), + "expected replace_ltoflags to affect exported LTOFLAGS" + ); + } + #[test] fn test_standard_build_env_skips_lto_injection_when_disabled() { let mut spec = mk_spec(vec!["-O2"], vec!["-Wl,--as-needed"]); @@ -607,6 +720,15 @@ mod tests { ); } + #[test] + fn test_effective_rustflags_applies_replace_rules() { + let mut flags = BuildFlags::default(); + flags.rustflags = vec!["-C".into(), "debuginfo=2".into()]; + flags.replace_rustflags = vec!["debuginfo=2=>opt-level=2".into()]; + + assert_eq!(effective_rustflags(&flags), vec!["-C", "opt-level=2"]); + } + #[test] fn test_standard_build_env_passthrough_does_not_override_default_vars() { let mut spec = mk_spec(Vec::new(), Vec::new()); diff --git a/src/builder/rust.rs b/src/builder/rust.rs index 6938abd..8eed8a6 100755 --- a/src/builder/rust.rs +++ b/src/builder/rust.rs @@ -50,8 +50,9 @@ pub fn build( crate::builder::standard_build_env(spec, cross, false, export_compiler_flags); // RUSTFLAGS - if !flags.rustflags.is_empty() { - crate::builder::set_env_var(&mut env_vars, "RUSTFLAGS", flags.rustflags.join(" ")); + let rustflags = crate::builder::effective_rustflags(flags); + if !rustflags.is_empty() { + crate::builder::set_env_var(&mut env_vars, "RUSTFLAGS", rustflags.join(" ")); } // If cross-compiling, set linker via CARGO_TARGET_*_LINKER diff --git a/src/commands.rs b/src/commands.rs index f0c34e4..a449b12 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -719,9 +719,19 @@ fn make_lib32_build_spec(base: &package::PackageSpec) -> package::PackageSpec { if !flags.cflags_lib32.is_empty() { flags.cflags.extend(flags.cflags_lib32.clone()); } + if !flags.replace_cflags_lib32.is_empty() { + flags + .replace_cflags + .extend(flags.replace_cflags_lib32.clone()); + } if !flags.cxxflags_lib32.is_empty() { flags.cxxflags.extend(flags.cxxflags_lib32.clone()); } + if !flags.replace_cxxflags_lib32.is_empty() { + flags + .replace_cxxflags + .extend(flags.replace_cxxflags_lib32.clone()); + } if !flags.configure_lib32.is_empty() { flags.configure = flags.configure_lib32.clone(); } @@ -5901,4 +5911,31 @@ optional = [] "/tmp/depot-test-rootfs" ))); } + + #[test] + fn make_lib32_build_spec_merges_replace_flag_rules() { + let mut base = test_package_spec(package::BuildType::Custom, None, &[]); + base.build.flags.cflags = vec!["-O2".into()]; + base.build.flags.replace_cflags = vec!["-O2=>-O3".into()]; + base.build.flags.cflags_lib32 = vec!["-m32".into()]; + base.build.flags.replace_cflags_lib32 = vec!["-m32=>-mstackrealign".into()]; + base.build.flags.cxxflags = vec!["-O2".into()]; + base.build.flags.replace_cxxflags = vec!["-O2=>-O3".into()]; + base.build.flags.cxxflags_lib32 = vec!["-fno-rtti".into()]; + base.build.flags.replace_cxxflags_lib32 = vec!["-fno-rtti=>-fno-exceptions".into()]; + + let lib32 = make_lib32_build_spec(&base); + + assert!(lib32.build.flags.lib32_variant); + assert_eq!(lib32.build.flags.cflags, vec!["-O2", "-m32"]); + assert_eq!( + lib32.build.flags.replace_cflags, + vec!["-O2=>-O3", "-m32=>-mstackrealign"] + ); + assert_eq!(lib32.build.flags.cxxflags, vec!["-O2", "-fno-rtti"]); + assert_eq!( + lib32.build.flags.replace_cxxflags, + vec!["-O2=>-O3", "-fno-rtti=>-fno-exceptions"] + ); + } } diff --git a/src/package/spec.rs b/src/package/spec.rs index d90ad0c..75e4b34 100755 --- a/src/package/spec.rs +++ b/src/package/spec.rs @@ -270,6 +270,17 @@ impl PackageSpec { self.build.flags.cflags = vec![s.to_string()]; } } + "replace_cflags" | "replace-cflags" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_cflags = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cflags = vec![s.to_string()]; + } + } "cflags-lib32" | "cflags_lib32" => { if let Some(arr) = v.as_array() { self.build.flags.cflags_lib32 = arr @@ -281,6 +292,17 @@ impl PackageSpec { self.build.flags.cflags_lib32 = vec![s.to_string()]; } } + "replace_cflags-lib32" | "replace_cflags_lib32" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_cflags_lib32 = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cflags_lib32 = vec![s.to_string()]; + } + } "cxxflags" => { if let Some(arr) = v.as_array() { self.build.flags.cxxflags = arr @@ -292,6 +314,17 @@ impl PackageSpec { self.build.flags.cxxflags = vec![s.to_string()]; } } + "replace_cxxflags" | "replace-cxxflags" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_cxxflags = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cxxflags = vec![s.to_string()]; + } + } "cxxflags-lib32" | "cxxflags_lib32" => { if let Some(arr) = v.as_array() { self.build.flags.cxxflags_lib32 = arr @@ -303,6 +336,17 @@ impl PackageSpec { self.build.flags.cxxflags_lib32 = vec![s.to_string()]; } } + "replace_cxxflags-lib32" | "replace_cxxflags_lib32" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_cxxflags_lib32 = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cxxflags_lib32 = vec![s.to_string()]; + } + } "ldflags" => { if let Some(arr) = v.as_array() { self.build.flags.ldflags = arr @@ -314,6 +358,17 @@ impl PackageSpec { self.build.flags.ldflags = vec![s.to_string()]; } } + "replace_ldflags" | "replace-ldflags" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_ldflags = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_ldflags = vec![s.to_string()]; + } + } "ltoflags" | "lto_flags" | "lto-flags" => { if let Some(arr) = v.as_array() { self.build.flags.ltoflags = arr @@ -325,6 +380,39 @@ impl PackageSpec { self.build.flags.ltoflags = vec![s.to_string()]; } } + "replace_ltoflags" | "replace_lto-flags" | "replace_lto_flags" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_ltoflags = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_ltoflags = vec![s.to_string()]; + } + } + "rustflags" => { + if let Some(arr) = v.as_array() { + self.build.flags.rustflags = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.rustflags = vec![s.to_string()]; + } + } + "replace_rustflags" | "replace-rustflags" => { + if let Some(arr) = v.as_array() { + self.build.flags.replace_rustflags = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_rustflags = vec![s.to_string()]; + } + } "keep" => { if let Some(arr) = v.as_array() { self.build.flags.keep = arr @@ -746,6 +834,18 @@ impl PackageSpec { } } } + "replace_cflags" | "replace-cflags" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_cflags + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cflags.push(s.to_string()); + } + } + } "cflags-lib32" | "cflags_lib32" => { for v in values { if let Some(arr) = v.as_array() { @@ -758,6 +858,18 @@ impl PackageSpec { } } } + "replace_cflags-lib32" | "replace_cflags_lib32" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_cflags_lib32 + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cflags_lib32.push(s.to_string()); + } + } + } "cxxflags" => { for v in values { if let Some(arr) = v.as_array() { @@ -770,6 +882,18 @@ impl PackageSpec { } } } + "replace_cxxflags" | "replace-cxxflags" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_cxxflags + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cxxflags.push(s.to_string()); + } + } + } "cxxflags-lib32" | "cxxflags_lib32" => { for v in values { if let Some(arr) = v.as_array() { @@ -782,6 +906,18 @@ impl PackageSpec { } } } + "replace_cxxflags-lib32" | "replace_cxxflags_lib32" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_cxxflags_lib32 + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_cxxflags_lib32.push(s.to_string()); + } + } + } "ldflags" => { for v in values { if let Some(arr) = v.as_array() { @@ -794,6 +930,18 @@ impl PackageSpec { } } } + "replace_ldflags" | "replace-ldflags" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_ldflags + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_ldflags.push(s.to_string()); + } + } + } "ltoflags" | "lto_flags" | "lto-flags" => { for v in values { if let Some(arr) = v.as_array() { @@ -806,6 +954,18 @@ impl PackageSpec { } } } + "replace_ltoflags" | "replace_lto-flags" | "replace_lto_flags" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_ltoflags + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_ltoflags.push(s.to_string()); + } + } + } "keep" => { for v in values { if let Some(arr) = v.as_array() { @@ -955,6 +1115,18 @@ impl PackageSpec { } } } + "replace_rustflags" | "replace-rustflags" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .replace_rustflags + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.replace_rustflags.push(s.to_string()); + } + } + } "cc" => { if let Some(s) = values.last().and_then(|v| v.as_str()) { self.build.flags.cc = s.to_string(); @@ -1941,7 +2113,9 @@ cc = "my-cc" ld = "ld.lld" CPP = "clang-cpp" cflags = ["-O2"] +replace_cflags = ["-O2=>-O3"] cxxflags = ["-O2", "-pipe"] +replace_cxxflags = ["-pipe=>-fPIC"] passthrough_env = ["RUSTFLAGS"] bindir = "/opt/bin" sbindir = "/opt/sbin" @@ -1954,6 +2128,9 @@ make_dirs = ["lib"] make_test_dirs = ["tests"] make_install_dirs = ["lib"] ltoflags = ["-flto=auto"] +replace_ltoflags = ["auto=>thin"] +rustflags = ["-C", "debuginfo=2"] +replace_rustflags = ["debuginfo=2=>opt-level=2"] use_lto = true no_flags = true no_strip = true @@ -1971,10 +2148,22 @@ post_configure = ["echo configured"] "build.flags.cflags".to_string(), vec![toml::Value::String("-g".to_string())], ); + config.appends.insert( + "build.flags.replace_cflags".to_string(), + vec![toml::Value::String( + "-D_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".to_string(), + )], + ); config.appends.insert( "build.flags.cxxflags".to_string(), vec![toml::Value::String("-stdlib=libc++".to_string())], ); + config.appends.insert( + "build.flags.replace_cxxflags".to_string(), + vec![toml::Value::String( + "-stdlib=libc++=>-stdlib=libstdc++".to_string(), + )], + ); config.appends.insert( "build.flags.rustflags".to_string(), vec![toml::Value::Array(vec![ @@ -1982,6 +2171,10 @@ post_configure = ["echo configured"] toml::Value::String("opt-level=3".to_string()), ])], ); + config.appends.insert( + "build.flags.replace_rustflags".to_string(), + vec![toml::Value::String("opt-level=3=>opt-level=z".to_string())], + ); config.appends.insert( "build.flags.keep".to_string(), vec![toml::Value::Array(vec![toml::Value::String( @@ -1994,6 +2187,12 @@ post_configure = ["echo configured"] "-fno-fat-lto-objects".to_string(), )])], ); + config.appends.insert( + "build.flags.replace_ltoflags".to_string(), + vec![toml::Value::String( + "-fno-fat-lto-objects=>-flto-jobs=8".to_string(), + )], + ); config.appends.insert( "build.flags.use_lto".to_string(), vec![toml::Value::Boolean(false)], @@ -2068,6 +2267,18 @@ post_configure = ["echo configured"] assert_eq!(spec.build.flags.cpp, "clang-cpp"); assert!(spec.build.flags.cflags.contains(&"-O2".to_string())); assert!(spec.build.flags.cflags.contains(&"-g".to_string())); + assert!( + spec.build + .flags + .replace_cflags + .contains(&"-O2=>-O3".to_string()) + ); + assert!( + spec.build + .flags + .replace_cflags + .contains(&"-D_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".to_string()) + ); assert!(spec.build.flags.cxxflags.contains(&"-O2".to_string())); assert!(spec.build.flags.cxxflags.contains(&"-pipe".to_string())); assert!( @@ -2076,13 +2287,43 @@ post_configure = ["echo configured"] .cxxflags .contains(&"-stdlib=libc++".to_string()) ); + assert!( + spec.build + .flags + .replace_cxxflags + .contains(&"-pipe=>-fPIC".to_string()) + ); + assert!( + spec.build + .flags + .replace_cxxflags + .contains(&"-stdlib=libc++=>-stdlib=libstdc++".to_string()) + ); assert!(spec.build.flags.rustflags.contains(&"-C".to_string())); + assert!( + spec.build + .flags + .rustflags + .contains(&"debuginfo=2".to_string()) + ); assert!( spec.build .flags .rustflags .contains(&"opt-level=3".to_string()) ); + assert!( + spec.build + .flags + .replace_rustflags + .contains(&"debuginfo=2=>opt-level=2".to_string()) + ); + assert!( + spec.build + .flags + .replace_rustflags + .contains(&"opt-level=3=>opt-level=z".to_string()) + ); assert!( spec.build .flags @@ -2095,6 +2336,18 @@ post_configure = ["echo configured"] .ltoflags .contains(&"-fno-fat-lto-objects".to_string()) ); + assert!( + spec.build + .flags + .replace_ltoflags + .contains(&"auto=>thin".to_string()) + ); + assert!( + spec.build + .flags + .replace_ltoflags + .contains(&"-fno-fat-lto-objects=>-flto-jobs=8".to_string()) + ); assert!(!spec.build.flags.use_lto); assert!(spec.build.flags.no_flags); assert!(!spec.build.flags.no_strip); @@ -2707,9 +2960,13 @@ extract_dir = "foo" type = "custom" [build.flags] +replace_cflags = ["-O2=>-O3"] +replace_rustflags = ["debuginfo=2=>opt-level=2"] cxxflags = ["-O2"] cxxflags += [ "-Wno-gnu-statement-expression-from-macro-expansion" ] ldflags += "-Wl,--as-needed" +replace_cflags += [ "_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2" ] +replace_rustflags += "opt-level=3=>opt-level=z" "#, ) .unwrap(); @@ -2726,6 +2983,20 @@ ldflags += "-Wl,--as-needed" spec.build.flags.ldflags, vec!["-Wl,--as-needed".to_string()] ); + assert_eq!( + spec.build.flags.replace_cflags, + vec![ + "-O2=>-O3".to_string(), + "_FORTIFY_SOURCE=3=_FORTIFY_SOURCE=2".to_string() + ] + ); + assert_eq!( + spec.build.flags.replace_rustflags, + vec![ + "debuginfo=2=>opt-level=2".to_string(), + "opt-level=3=>opt-level=z".to_string() + ] + ); } #[test] @@ -3259,8 +3530,19 @@ pub enum BuildType { /// Build flags and toolchain configuration #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct BuildFlags { + /// Extra flags exported to `CFLAGS`. #[serde(default, deserialize_with = "deserialize_string_or_array")] pub cflags: Vec, + /// Ordered replacement rules applied to `cflags` before export. + /// + /// Each entry may use `old=>new`. Plain `old=new` is also accepted and + /// disambiguated against the current flag set when possible. + #[serde( + default, + alias = "replace-cflags", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_cflags: Vec, /// Extra flags exported to `CFLAGS` only for the lib32 build variant. #[serde( default, @@ -3271,9 +3553,25 @@ pub struct BuildFlags { deserialize_with = "deserialize_string_or_array" )] pub cflags_lib32: Vec, + /// Ordered replacement rules applied to lib32-only `cflags`. + #[serde( + default, + alias = "replace-cflags-lib32", + alias = "replace_cflags-lib32", + alias = "replace_cflags_lib32", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_cflags_lib32: Vec, /// Extra flags exported to `CXXFLAGS`. #[serde(default, deserialize_with = "deserialize_string_or_array")] pub cxxflags: Vec, + /// Ordered replacement rules applied to `cxxflags` before export. + #[serde( + default, + alias = "replace-cxxflags", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_cxxflags: Vec, /// Extra flags exported to `CXXFLAGS` only for the lib32 build variant. #[serde( default, @@ -3284,8 +3582,25 @@ pub struct BuildFlags { deserialize_with = "deserialize_string_or_array" )] pub cxxflags_lib32: Vec, + /// Ordered replacement rules applied to lib32-only `cxxflags`. + #[serde( + default, + alias = "replace-cxxflags-lib32", + alias = "replace_cxxflags-lib32", + alias = "replace_cxxflags_lib32", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_cxxflags_lib32: Vec, + /// Extra flags exported to `LDFLAGS`. #[serde(default, deserialize_with = "deserialize_string_or_array")] pub ldflags: Vec, + /// Ordered replacement rules applied to `ldflags` before export. + #[serde( + default, + alias = "replace-ldflags", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_ldflags: Vec, /// Link-time optimization flags exported to `LTOFLAGS`. /// /// When `use_lto` is true (default), these flags are also appended to @@ -3298,6 +3613,15 @@ pub struct BuildFlags { deserialize_with = "deserialize_string_or_array" )] pub ltoflags: Vec, + /// Ordered replacement rules applied to `ltoflags` before export/injection. + #[serde( + default, + alias = "replace-ltoflags", + alias = "replace_lto-flags", + alias = "replace_lto_flags", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_ltoflags: Vec, /// Keep existing files and install package-provided replacement as `.depotnew`. #[serde(default, deserialize_with = "deserialize_string_or_array")] pub keep: Vec, @@ -3552,6 +3876,13 @@ pub struct BuildFlags { /// RUSTFLAGS environment variable #[serde(default, deserialize_with = "deserialize_string_or_array")] pub rustflags: Vec, + /// Ordered replacement rules applied to `rustflags` before export. + #[serde( + default, + alias = "replace-rustflags", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub replace_rustflags: Vec, /// Additional cargo arguments (short name) #[serde(default)] pub cargs: Vec, @@ -3617,11 +3948,17 @@ impl Default for BuildFlags { fn default() -> Self { BuildFlags { cflags: Vec::new(), + replace_cflags: Vec::new(), cflags_lib32: Vec::new(), + replace_cflags_lib32: Vec::new(), cxxflags: Vec::new(), + replace_cxxflags: Vec::new(), cxxflags_lib32: Vec::new(), + replace_cxxflags_lib32: Vec::new(), ldflags: Vec::new(), + replace_ldflags: Vec::new(), ltoflags: Vec::new(), + replace_ltoflags: Vec::new(), keep: Vec::new(), use_lto: default_use_lto(), no_flags: false, @@ -3671,6 +4008,7 @@ impl Default for BuildFlags { profile: default_profile(), target: String::new(), rustflags: Vec::new(), + replace_rustflags: Vec::new(), cargs: Vec::new(), bindir: default_bindir(), sbindir: String::new(),