From 18e376e4f78ee1d0ab2e8c0102c84418f16fdfe9 Mon Sep 17 00:00:00 2001 From: SFG545 Date: Mon, 23 Mar 2026 17:08:03 -0500 Subject: [PATCH] feat: update depot version to 0.32.0 and add support for environment variable declarations in build flags --- Cargo.lock | 2 +- Cargo.toml | 2 +- meson.build | 2 +- src/builder/mod.rs | 71 ++++++++++++++++++++++++++++++ src/package/interactive.rs | 18 ++++++++ src/package/spec.rs | 90 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 182 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e754e1..37dcca6 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" [[package]] name = "depot" -version = "0.31.1" +version = "0.32.0" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index 5cc8a20..81bb6a6 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "depot" -version = "0.31.1" +version = "0.32.0" edition = "2024" [lints.rust] diff --git a/meson.build b/meson.build index ae75bc6..dece09b 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'depot', - version: '0.31.1', + version: '0.32.0', meson_version: '>=0.60.0', default_options: ['buildtype=release'], ) diff --git a/src/builder/mod.rs b/src/builder/mod.rs index e9566fa..bcba999 100755 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -54,6 +54,35 @@ pub fn set_env_var(env_vars: &mut EnvVars, key: &str, value: impl Into) } } +fn apply_declared_env_vars(spec: &PackageSpec, env_vars: &mut EnvVars) { + for raw in &spec.build.flags.env_vars { + let expanded = spec.expand_vars(raw); + let entry = expanded.trim(); + if entry.is_empty() { + continue; + } + + let Some((key, value)) = entry.split_once('=') else { + crate::log_warn!( + "Skipping invalid build.flags.env_vars entry '{}'; expected KEY=VALUE", + raw + ); + continue; + }; + + let key = key.trim(); + if key.is_empty() || key.chars().any(char::is_whitespace) { + crate::log_warn!( + "Skipping invalid build.flags.env_vars entry '{}'; expected KEY=VALUE", + raw + ); + continue; + } + + set_env_var(env_vars, key, value.to_string()); + } +} + fn default_libdir_for_variant(lib32_variant: bool) -> &'static str { if lib32_variant { "/usr/lib32" @@ -525,6 +554,8 @@ pub fn standard_build_env( } } + apply_declared_env_vars(spec, &mut env_vars); + env_vars } @@ -1117,6 +1148,46 @@ mod tests { ); } + #[test] + fn test_standard_build_env_exports_declared_env_vars() { + let mut spec = mk_spec(Vec::new(), Vec::new()); + spec.package.version = "2.4.1".to_string(); + spec.spec_dir = PathBuf::from("/tmp/specs/demo"); + spec.build.flags.env_vars = vec![ + "SETUPTOOLS_SCM_PRETEND_VERSION=$version".into(), + "PYO3_CONFIG_FILE=$specdir/pyo3.toml".into(), + ]; + + let env = standard_build_env(&spec, None, false, true); + assert!( + env.iter() + .any(|(k, v)| k == "SETUPTOOLS_SCM_PRETEND_VERSION" && v == "2.4.1"), + "expected env_vars values to expand package variables" + ); + assert!( + env.iter() + .any(|(k, v)| k == "PYO3_CONFIG_FILE" && v == "/tmp/specs/demo/pyo3.toml"), + "expected env_vars values to expand specdir variables" + ); + } + + #[test] + fn test_standard_build_env_declared_env_vars_override_defaults_and_passthrough() { + let mut spec = mk_spec(Vec::new(), Vec::new()); + spec.build.flags.cc = "spec-cc".to_string(); + spec.build.flags.passthrough_env = vec!["CC".into()]; + spec.build.flags.env_vars = vec!["CC=custom-cc".into()]; + + let mut env = TestEnv::new(); + env.set_var("CC", "host-cc"); + + let env = standard_build_env(&spec, None, true, true); + assert!( + env.iter().any(|(k, v)| k == "CC" && v == "custom-cc"), + "expected explicit env_vars assignments to override default and passthrough values" + ); + } + #[test] fn test_effective_rustflags_applies_replace_rules() { let flags = BuildFlags { diff --git a/src/package/interactive.rs b/src/package/interactive.rs index d48ae18..515ec52 100644 --- a/src/package/interactive.rs +++ b/src/package/interactive.rs @@ -1286,6 +1286,19 @@ pub fn spec_to_minimal_toml(spec: &PackageSpec) -> anyhow::Result { ), ); } + if !spec.build.flags.env_vars.is_empty() { + flags_tbl.insert( + "env_vars".into(), + Value::Array( + spec.build + .flags + .env_vars + .iter() + .map(|s| Value::String(s.clone())) + .collect(), + ), + ); + } if !spec.build.flags.post_compile.is_empty() { flags_tbl.insert( "post_compile".into(), @@ -1830,6 +1843,10 @@ mod tests { make_test_dirs: vec!["tests".into()], make_install_vars: vec!["STRIPPROG=true".into()], make_install_dirs: vec!["lib".into(), "apps".into()], + env_vars: vec![ + "SETUPTOOLS_SCM_PRETEND_VERSION=$version".into(), + "PYO3_CONFIG_FILE=$specdir/pyo3.toml".into(), + ], ..BuildFlags::default() }; @@ -1906,6 +1923,7 @@ mod tests { assert!(toml.contains("make_test_dirs = [")); assert!(toml.contains("make_install_vars = [")); assert!(toml.contains("make_install_dirs = [")); + assert!(toml.contains("env_vars = [")); assert!(toml.contains("patches = [")); assert!(toml.contains("post_extract = [")); } diff --git a/src/package/spec.rs b/src/package/spec.rs index c4993ba..656da88 100755 --- a/src/package/spec.rs +++ b/src/package/spec.rs @@ -822,6 +822,17 @@ impl PackageSpec { s.split_whitespace().map(String::from).collect(); } } + "env_vars" | "env-vars" => { + if let Some(arr) = v.as_array() { + self.build.flags.env_vars = arr + .iter() + .filter_map(|x| x.as_str()) + .map(String::from) + .collect(); + } else if let Some(s) = v.as_str() { + self.build.flags.env_vars = vec![s.to_string()]; + } + } "no_flags" | "no-flags" => { if let Some(b) = v.as_bool() { self.build.flags.no_flags = b; @@ -1587,6 +1598,18 @@ impl PackageSpec { } } } + "env_vars" | "env-vars" => { + for v in values { + if let Some(arr) = v.as_array() { + self.build + .flags + .env_vars + .extend(arr.iter().filter_map(|x| x.as_str()).map(String::from)); + } else if let Some(s) = v.as_str() { + self.build.flags.env_vars.push(s.to_string()); + } + } + } "no_flags" | "no-flags" => { if let Some(b) = values.last().and_then(|v| v.as_bool()) { self.build.flags.no_flags = b; @@ -2407,6 +2430,7 @@ replace_cflags = ["-O2=>-O3"] cxxflags = ["-O2", "-pipe"] replace_cxxflags = ["-pipe=>-fPIC"] passthrough_env = ["RUSTFLAGS"] +env_vars = ["SETUPTOOLS_SCM_PRETEND_VERSION=$version"] bindir = "/opt/bin" sbindir = "/opt/sbin" libdir = "/opt/lib64" @@ -2504,6 +2528,12 @@ post_configure = ["echo configured"] "build.flags.passthrough_env".to_string(), vec![toml::Value::String("CARGO_HOME".to_string())], ); + config.appends.insert( + "build.flags.env_vars".to_string(), + vec![toml::Value::String( + "SOURCE_DATE_EPOCH=1700000000".to_string(), + )], + ); config.appends.insert( "build.flags.make_test_vars".to_string(), vec![toml::Value::String("TESTS=smoke".to_string())], @@ -2668,6 +2698,18 @@ post_configure = ["echo configured"] .passthrough_env .contains(&"CARGO_HOME".to_string()) ); + assert!( + spec.build + .flags + .env_vars + .contains(&"SETUPTOOLS_SCM_PRETEND_VERSION=$version".to_string()) + ); + assert!( + spec.build + .flags + .env_vars + .contains(&"SOURCE_DATE_EPOCH=1700000000".to_string()) + ); assert_eq!(spec.build.flags.bindir, "/opt/bin"); assert_eq!(spec.build.flags.sbindir, "/opt/sbin"); assert_eq!(spec.build.flags.libdir, "/opt/lib64"); @@ -3387,6 +3429,45 @@ passthrough_env = ["RUSTFLAGS", "CARGO_HOME"] ); } + #[test] + fn parse_env_vars_from_spec() { + let tmp = tempfile::tempdir().unwrap(); + let path = tmp.path().join("pkg.toml"); + + std::fs::write( + &path, + r#" +[package] +name = "foo" +version = "1.0" +description = "d" +homepage = "h" +license = "MIT" + +[source] +url = "https://example.com/foo.tar.gz" +sha256 = "skip" +extract_dir = "foo" + +[build] +type = "python" + +[build.flags] +env_vars = ["SETUPTOOLS_SCM_PRETEND_VERSION=$version", "PYO3_CONFIG_FILE=$specdir/pyo3.toml"] +"#, + ) + .unwrap(); + + let spec = PackageSpec::from_file(&path).unwrap(); + assert_eq!( + spec.build.flags.env_vars, + vec![ + "SETUPTOOLS_SCM_PRETEND_VERSION=$version".to_string(), + "PYO3_CONFIG_FILE=$specdir/pyo3.toml".to_string() + ] + ); + } + #[test] fn parse_test_dependencies_from_spec() { let tmp = tempfile::tempdir().unwrap(); @@ -4339,6 +4420,14 @@ pub struct BuildFlags { deserialize_with = "deserialize_string_or_array" )] pub passthrough_env: Vec, + /// Explicit environment variable assignments exported to build commands. + /// Each entry must be `KEY=VALUE`. + #[serde( + default, + alias = "env-vars", + deserialize_with = "deserialize_string_or_array_no_split" + )] + pub env_vars: Vec, // Rust-specific fields /// Rust build profile: "debug" or "release" (default: release) @@ -4487,6 +4576,7 @@ impl Default for BuildFlags { make_install_targets: Vec::new(), make_install_dirs: Vec::new(), passthrough_env: Vec::new(), + env_vars: Vec::new(), profile: default_profile(), target: String::new(), rustflags: Vec::new(),