From 6129edb50c09a31f8ffcecef98fbb24ea046c03c Mon Sep 17 00:00:00 2001 From: SFG545 Date: Sun, 15 Mar 2026 16:49:53 -0500 Subject: [PATCH] feat: update depot version to 0.24.1 and enhance lib32 installation handling --- Cargo.lock | 2 +- Cargo.toml | 2 +- meson.build | 2 +- src/builder/cmake.rs | 30 ++++++++- src/builder/meson.rs | 30 ++++++++- src/builder/mod.rs | 150 ++++++++++++++++++++++++++++++++++++++++++- src/commands.rs | 42 ++++++------ 7 files changed, 224 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e3c2d3..258c224 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" [[package]] name = "depot" -version = "0.24.0" +version = "0.24.1" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index e412a68..707877f 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "depot" -version = "0.24.0" +version = "0.24.1" edition = "2024" [lints.rust] diff --git a/meson.build b/meson.build index 90a1e28..395f615 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'depot', - version: '0.24.0', + version: '0.24.1', meson_version: '>=0.60.0', default_options: ['buildtype=release'], ) diff --git a/src/builder/cmake.rs b/src/builder/cmake.rs index 80bf7ea..8a7e6ef 100755 --- a/src/builder/cmake.rs +++ b/src/builder/cmake.rs @@ -188,7 +188,26 @@ pub fn build( let install_targets = phase_targets(&flags.make_install_target, &flags.make_install_targets); - let mut install_cmd = fakeroot::wrap_install_command("cmake", destdir); + let install_destdir = + crate::builder::install_destdir_path(&build_dir, destdir, flags.lib32_variant); + if flags.lib32_variant { + if install_destdir.exists() { + fs::remove_dir_all(&install_destdir).with_context(|| { + format!( + "Failed to clean temporary lib32 install dir: {}", + install_destdir.display() + ) + })?; + } + fs::create_dir_all(&install_destdir).with_context(|| { + format!( + "Failed to create temporary lib32 install dir: {}", + install_destdir.display() + ) + })?; + } + + let mut install_cmd = fakeroot::wrap_install_command("cmake", &install_destdir); if !install_targets.is_empty() { install_cmd.arg("--build").arg(&build_dir); install_cmd.arg("--target"); @@ -202,7 +221,7 @@ pub fn build( let mut install_env = env_vars.clone(); install_env.push(( "DESTDIR".to_string(), - destdir.to_string_lossy().into_owned(), + install_destdir.to_string_lossy().into_owned(), )); crate::builder::prepare_tool_command(&mut install_cmd, &install_env); @@ -218,7 +237,12 @@ pub fn build( anyhow::bail!("cmake install failed"); } - crate::source::hooks::run_post_install_commands(spec, &actual_src, destdir)?; + if flags.lib32_variant { + crate::builder::stage_lib32_install_tree(&install_destdir, destdir)?; + crate::source::hooks::run_post_install_commands_in_dir(spec, &build_dir, destdir)?; + } else { + crate::source::hooks::run_post_install_commands(spec, &actual_src, destdir)?; + } state.mark_done(BuildStep::PostInstallDone)?; } else { crate::log_info!("Skipping cmake install and post-install hooks (already done)"); diff --git a/src/builder/meson.rs b/src/builder/meson.rs index e650610..042d882 100755 --- a/src/builder/meson.rs +++ b/src/builder/meson.rs @@ -132,14 +132,33 @@ pub fn build( } ); - let mut install_cmd = fakeroot::wrap_install_command("meson", destdir); + let install_destdir = + crate::builder::install_destdir_path(&build_dir, destdir, flags.lib32_variant); + if flags.lib32_variant { + if install_destdir.exists() { + fs::remove_dir_all(&install_destdir).with_context(|| { + format!( + "Failed to clean temporary lib32 install dir: {}", + install_destdir.display() + ) + })?; + } + fs::create_dir_all(&install_destdir).with_context(|| { + format!( + "Failed to create temporary lib32 install dir: {}", + install_destdir.display() + ) + })?; + } + + let mut install_cmd = fakeroot::wrap_install_command("meson", &install_destdir); install_cmd.arg("install"); install_cmd.arg("-C").arg(&build_dir); let mut install_env = env_vars.clone(); install_env.push(( "DESTDIR".to_string(), - destdir.to_string_lossy().into_owned(), + install_destdir.to_string_lossy().into_owned(), )); crate::builder::prepare_tool_command(&mut install_cmd, &install_env); @@ -149,7 +168,12 @@ pub fn build( anyhow::bail!("meson install failed"); } - crate::source::hooks::run_post_install_commands(spec, &actual_src, destdir)?; + if flags.lib32_variant { + crate::builder::stage_lib32_install_tree(&install_destdir, destdir)?; + crate::source::hooks::run_post_install_commands_in_dir(spec, &build_dir, destdir)?; + } else { + crate::source::hooks::run_post_install_commands(spec, &actual_src, destdir)?; + } state.mark_done(BuildStep::PostInstallDone)?; } else { crate::log_info!("Skipping meson install and post-install hooks (already done)"); diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 4ade7bc..502bb5b 100755 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -13,10 +13,12 @@ pub mod state; use crate::cross::CrossConfig; use crate::package::{BuildType, PackageSpec}; -use anyhow::Result; +use anyhow::{Context, Result}; use std::ffi::OsString; -use std::path::Path; +use std::fs; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use walkdir::WalkDir; pub type EnvVars = Vec<(String, String)>; @@ -165,6 +167,97 @@ pub(crate) fn install_dirs(flags: &crate::package::BuildFlags) -> InstallDirs { } } +pub(crate) fn install_destdir_path( + build_dir: &Path, + destdir: &Path, + lib32_variant: bool, +) -> PathBuf { + if lib32_variant { + build_dir.join("destdir") + } else { + destdir.to_path_buf() + } +} + +pub(crate) fn stage_lib32_install_tree(staging_destdir: &Path, destdir: &Path) -> Result<()> { + let staged_lib32 = staging_destdir.join("usr/lib32"); + if staged_lib32.exists() { + return copy_tree_preserving_links(&staged_lib32, &destdir.join("usr/lib32")); + } + + let staged_lib = staging_destdir.join("usr/lib"); + if staged_lib.exists() { + crate::log_warn!( + "lib32 install populated {} instead of usr/lib32; relocating staged libraries", + staged_lib.display() + ); + return copy_tree_preserving_links(&staged_lib, &destdir.join("usr/lib32")); + } + + anyhow::bail!( + "lib32 install did not populate {} or {}", + staged_lib32.display(), + staged_lib.display() + ); +} + +fn copy_tree_preserving_links(src: &Path, dst: &Path) -> Result<()> { + fs::create_dir_all(dst) + .with_context(|| format!("Failed to create destination dir: {}", dst.display()))?; + + for entry in WalkDir::new(src) { + let entry = entry?; + let rel = entry + .path() + .strip_prefix(src) + .with_context(|| format!("Failed to strip prefix: {}", src.display()))?; + let target = dst.join(rel); + + if entry.file_type().is_dir() { + fs::create_dir_all(&target) + .with_context(|| format!("Failed to create dir: {}", target.display()))?; + continue; + } + + if let Some(parent) = target.parent() { + fs::create_dir_all(parent) + .with_context(|| format!("Failed to create dir: {}", parent.display()))?; + } + + if entry.file_type().is_symlink() { + let link_target = fs::read_link(entry.path()) + .with_context(|| format!("Failed to read symlink: {}", entry.path().display()))?; + #[cfg(unix)] + { + use std::os::unix::fs as unix_fs; + unix_fs::symlink(&link_target, &target).with_context(|| { + format!( + "Failed to create symlink {} -> {}", + target.display(), + link_target.display() + ) + })?; + } + #[cfg(not(unix))] + { + anyhow::bail!( + "Symlink-preserving lib32 staging copy is only supported on unix hosts" + ); + } + } else { + fs::copy(entry.path(), &target).with_context(|| { + format!( + "Failed to copy {} to {}", + entry.path().display(), + target.display() + ) + })?; + } + } + + Ok(()) +} + fn compiler_flag_sets( flags: &crate::package::BuildFlags, ) -> (Vec, Vec, Vec, Vec) { @@ -867,4 +960,57 @@ mod tests { assert_eq!(dirs.datarootdir, "/opt/share-root"); assert_eq!(dirs.datadir, "/opt/share-root"); } + + #[test] + fn test_install_destdir_path_uses_build_dir_for_lib32() { + let build_dir = Path::new("/tmp/build"); + let destdir = Path::new("/tmp/pkg"); + assert_eq!(install_destdir_path(build_dir, destdir, false), destdir); + assert_eq!( + install_destdir_path(build_dir, destdir, true), + build_dir.join("destdir") + ); + } + + #[test] + fn test_stage_lib32_install_tree_uses_usr_lib32_when_present() -> Result<()> { + let temp = tempfile::tempdir()?; + let staging = temp.path().join("staging"); + let dest = temp.path().join("dest"); + fs::create_dir_all(staging.join("usr/lib32"))?; + fs::write(staging.join("usr/lib32/libfoo.so.1"), "lib32")?; + + stage_lib32_install_tree(&staging, &dest)?; + + assert_eq!( + fs::read_to_string(dest.join("usr/lib32/libfoo.so.1"))?, + "lib32" + ); + Ok(()) + } + + #[test] + #[cfg(unix)] + fn test_stage_lib32_install_tree_relocates_usr_lib_when_needed() -> Result<()> { + use std::os::unix::fs as unix_fs; + + let temp = tempfile::tempdir()?; + let staging = temp.path().join("staging"); + let dest = temp.path().join("dest"); + fs::create_dir_all(staging.join("usr/lib"))?; + fs::write(staging.join("usr/lib/libfoo.so.1"), "relocated")?; + unix_fs::symlink("libfoo.so.1", staging.join("usr/lib/libfoo.so"))?; + + stage_lib32_install_tree(&staging, &dest)?; + + assert_eq!( + fs::read_to_string(dest.join("usr/lib32/libfoo.so.1"))?, + "relocated" + ); + assert_eq!( + fs::read_link(dest.join("usr/lib32/libfoo.so"))?, + PathBuf::from("libfoo.so.1") + ); + Ok(()) + } } diff --git a/src/commands.rs b/src/commands.rs index 838fcf2..c6e56db 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -3730,29 +3730,25 @@ fn execute_install_plan_with_child_commands( step.package )); - let mut cmd = std::process::Command::new(&exe); - cmd.arg("-r").arg(rootfs); - cmd.arg("--no-deps"); - cmd.arg("--yes"); - if options.no_flags { - cmd.arg("--no-flags"); - } - if let Some(p) = options.cross_prefix { - cmd.arg("--cross-prefix").arg(p); - } - if options.clean { - cmd.arg("--clean"); - } - if step_requests_only_lib32(step, &options) { - cmd.arg("--lib32-only"); - } - cmd.arg("install").arg(path); - - let status = crate::interrupts::command_status(&mut cmd) - .context("Failed to spawn planned install step")?; - if !status.success() { - anyhow::bail!("Planned install step for '{}' failed", step.package); - } + run_install_command_with_program( + &exe, + std::slice::from_ref(path), + rootfs, + ChildInstallCommandOptions { + no_deps: true, + assume_yes: true, + no_flags: options.no_flags, + cross_prefix: options.cross_prefix, + clean: options.clean, + lib32_only: step_requests_only_lib32(step, &options), + install_test_deps: options.install_test_deps, + install_context: Some(INSTALL_CONTEXT_PLANNED), + dep_chain: None, + }, + ) + .with_context(|| { + format!("Failed to spawn planned install step '{}'", step.package) + })?; } planner::PlanOrigin::Binary { repo_name, record } => { let cached = binary_archives