diff --git a/Cargo.lock b/Cargo.lock index 1710f5f..aa49596 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -382,7 +382,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" [[package]] name = "depot" -version = "0.12.1" +version = "0.12.2" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index 458a174..a51d58c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "depot" -version = "0.12.1" +version = "0.12.2" edition = "2024" [lints.rust] diff --git a/meson.build b/meson.build index 308274e..0b3ebf5 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'depot', - version: '0.12.1', + version: '0.12.2', meson_version: '>=0.60.0', ) diff --git a/src/builder/meson.rs b/src/builder/meson.rs index 7532a53..a34d59f 100755 --- a/src/builder/meson.rs +++ b/src/builder/meson.rs @@ -156,6 +156,11 @@ fn has_option(configure: &[String], long: &str) -> bool { false } +fn has_builtin_option(configure: &[String], key: &str) -> bool { + let prefix = format!("-D{key}="); + configure.iter().any(|arg| arg.starts_with(&prefix)) +} + fn meson_setup_args( flags: &crate::package::BuildFlags, cross_file: Option<&Path>, @@ -191,6 +196,14 @@ fn meson_setup_args( if let Some(cf) = cross_file { args.push(format!("--cross-file={}", cf.display())); } + if !flags.ld.trim().is_empty() { + if !has_builtin_option(&flags.configure, "c_ld") { + args.push(format!("-Dc_ld={}", flags.ld)); + } + if !has_builtin_option(&flags.configure, "cpp_ld") { + args.push(format!("-Dcpp_ld={}", flags.ld)); + } + } // Append user flags last so they can override defaults when Meson allows it. for arg in &flags.configure { @@ -354,6 +367,33 @@ mod tests { assert!(args.iter().any(|a| a == "--bindir=/usr/bin")); } + #[test] + fn test_meson_setup_args_include_linker_override() { + let flags = BuildFlags { + ld: "ld.lld".to_string(), + ..BuildFlags::default() + }; + + let args = meson_setup_args(&flags, None, &[]); + assert!(args.iter().any(|a| a == "-Dc_ld=ld.lld")); + assert!(args.iter().any(|a| a == "-Dcpp_ld=ld.lld")); + } + + #[test] + fn test_meson_setup_args_honor_explicit_linker_override() { + let flags = BuildFlags { + ld: "ld.lld".to_string(), + configure: vec!["-Dc_ld=gold".to_string(), "-Dcpp_ld=gold".to_string()], + ..BuildFlags::default() + }; + + let args = meson_setup_args(&flags, None, &[]); + assert_eq!(args.iter().filter(|a| *a == "-Dc_ld=gold").count(), 1); + assert_eq!(args.iter().filter(|a| *a == "-Dcpp_ld=gold").count(), 1); + assert!(!args.iter().any(|a| a == "-Dc_ld=ld.lld")); + assert!(!args.iter().any(|a| a == "-Dcpp_ld=ld.lld")); + } + #[test] fn test_resolve_build_dir_uses_flag() { let flags = BuildFlags { diff --git a/src/builder/mod.rs b/src/builder/mod.rs index eb06b97..ea26fe0 100755 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -189,6 +189,12 @@ pub fn standard_build_env( set_env_var(&mut env_vars, "CC", flags.cc.clone()); set_env_var(&mut env_vars, "CXX", flags.cxx.clone()); set_env_var(&mut env_vars, "AR", flags.ar.clone()); + if !flags.ld.trim().is_empty() { + set_env_var(&mut env_vars, "LD", flags.ld.clone()); + } + if !flags.cpp.trim().is_empty() { + set_env_var(&mut env_vars, "CPP", flags.cpp.clone()); + } } } @@ -448,6 +454,17 @@ mod tests { ); } + #[test] + fn test_standard_build_env_exports_native_linker_and_cpp() { + let mut spec = mk_spec(Vec::new(), Vec::new()); + spec.build.flags.ld = "ld.lld".to_string(); + spec.build.flags.cpp = "clang-cpp".to_string(); + + let env = standard_build_env(&spec, None, true, true); + assert!(env.iter().any(|(k, v)| k == "LD" && v == "ld.lld")); + assert!(env.iter().any(|(k, v)| k == "CPP" && v == "clang-cpp")); + } + #[test] fn test_standard_build_env_respects_export_compiler_flags_toggle() { let mut spec = mk_spec(vec!["-O2"], vec!["-Wl,--as-needed"]); diff --git a/src/package/spec.rs b/src/package/spec.rs index 35922f6..44a4ed1 100755 --- a/src/package/spec.rs +++ b/src/package/spec.rs @@ -337,6 +337,16 @@ impl PackageSpec { self.build.flags.ar = s.to_string(); } } + "ld" => { + if let Some(s) = v.as_str() { + self.build.flags.ld = s.to_string(); + } + } + "cpp" => { + if let Some(s) = v.as_str() { + self.build.flags.cpp = s.to_string(); + } + } "prefix" => { if let Some(s) = v.as_str() { self.build.flags.prefix = s.to_string(); @@ -941,6 +951,16 @@ impl PackageSpec { self.build.flags.ar = s.to_string(); } } + "ld" => { + if let Some(s) = values.last().and_then(|v| v.as_str()) { + self.build.flags.ld = s.to_string(); + } + } + "cpp" => { + if let Some(s) = values.last().and_then(|v| v.as_str()) { + self.build.flags.cpp = s.to_string(); + } + } "prefix" => { if let Some(s) = values.last().and_then(|v| v.as_str()) { self.build.flags.prefix = s.to_string(); @@ -1890,6 +1910,8 @@ type = "custom" r#" [flags] cc = "my-cc" +ld = "ld.lld" +CPP = "clang-cpp" cflags = ["-O2"] cxxflags = ["-O2", "-pipe"] passthrough_env = ["RUSTFLAGS"] @@ -2014,6 +2036,8 @@ post_configure = ["echo configured"] spec.apply_config(&config); assert_eq!(spec.build.flags.cc, "my-cc"); + assert_eq!(spec.build.flags.ld, "ld.lld"); + 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.cxxflags.contains(&"-O2".to_string())); @@ -3273,6 +3297,12 @@ pub struct BuildFlags { /// Archiver #[serde(default = "default_ar")] pub ar: String, + /// Linker executable or linker flavor override for supported builders. + #[serde(default)] + pub ld: String, + /// C preprocessor executable exported as `CPP` when configured. + #[serde(default, alias = "CPP")] + pub cpp: String, /// Dynamic loader path #[serde(default)] pub libc: String, @@ -3536,6 +3566,8 @@ impl Default for BuildFlags { cc: default_cc(), cxx: default_cxx(), ar: default_ar(), + ld: String::new(), + cpp: String::new(), libc: String::new(), rootfs: default_rootfs(), post_configure: Vec::new(),