feat: initial implementation of Depot package manager
- Implement source-based package management with support for archives and Git - Add multi-system build support (Autotools, CMake, Meson, Rust/Cargo, Custom) - Implement atomic installation logic using transactions and fakeroot - Add dependency resolution for build-time and runtime requirements - Implement package indexing and local repository management - Add comprehensive configuration system with system/package overrides - Include Project guidelines (AGENTS.md) and README.md
This commit is contained in:
Executable
+179
@@ -0,0 +1,179 @@
|
||||
//! Rust/Cargo build system
|
||||
|
||||
use crate::cross::CrossConfig;
|
||||
use crate::package::PackageSpec;
|
||||
use crate::source::hooks;
|
||||
use anyhow::{Context, Result};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn build(
|
||||
spec: &PackageSpec,
|
||||
src_dir: &Path,
|
||||
destdir: &Path,
|
||||
cross: Option<&CrossConfig>,
|
||||
) -> Result<()> {
|
||||
let flags = &spec.build.flags;
|
||||
|
||||
// Create destdir
|
||||
fs::create_dir_all(destdir)?;
|
||||
|
||||
// Isolate from parent workspace by adding empty [workspace] if not present
|
||||
// This prevents "believes it's in a workspace when it's not" errors
|
||||
let cargo_toml = src_dir.join("Cargo.toml");
|
||||
if cargo_toml.exists() {
|
||||
let contents = fs::read_to_string(&cargo_toml)
|
||||
.with_context(|| format!("Failed to read {}", cargo_toml.display()))?;
|
||||
if !contents.contains("[workspace]") {
|
||||
let isolated = format!("{}\n\n[workspace]\n", contents);
|
||||
fs::write(&cargo_toml, isolated).with_context(|| {
|
||||
format!("Failed to isolate Cargo.toml: {}", cargo_toml.display())
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine profile
|
||||
let is_release = flags.profile == "release";
|
||||
let profile_dir = if is_release { "release" } else { "debug" };
|
||||
|
||||
// Determine target triple
|
||||
let target = if !flags.target.is_empty() {
|
||||
Some(flags.target.clone())
|
||||
} else {
|
||||
cross.map(|cc_cfg| cc_cfg.prefix.clone())
|
||||
};
|
||||
|
||||
// Build environment
|
||||
let mut env_vars: Vec<(&str, String)> = vec![];
|
||||
|
||||
// RUSTFLAGS
|
||||
if !flags.rustflags.is_empty() {
|
||||
env_vars.push(("RUSTFLAGS", flags.rustflags.join(" ")));
|
||||
}
|
||||
|
||||
// If cross-compiling, set linker via CARGO_TARGET_*_LINKER
|
||||
if let Some(cc_cfg) = cross {
|
||||
// Convert target triple to uppercase with underscores for env var
|
||||
let target_env = target
|
||||
.as_ref()
|
||||
.unwrap_or(&cc_cfg.prefix)
|
||||
.to_uppercase()
|
||||
.replace('-', "_");
|
||||
let linker_var = format!("CARGO_TARGET_{}_LINKER", target_env);
|
||||
env_vars.push((linker_var.leak(), cc_cfg.cc.clone()));
|
||||
env_vars.push(("CC".to_string().leak(), cc_cfg.cc.clone()));
|
||||
env_vars.push(("AR".to_string().leak(), cc_cfg.ar.clone()));
|
||||
}
|
||||
|
||||
// Set default rustup toolchain if not already set
|
||||
if std::env::var("RUSTUP_TOOLCHAIN").is_err() {
|
||||
env_vars.push(("RUSTUP_TOOLCHAIN", "stable".to_string()));
|
||||
}
|
||||
|
||||
// Run cargo build
|
||||
println!(
|
||||
"Running cargo build ({})...",
|
||||
if is_release { "release" } else { "debug" }
|
||||
);
|
||||
let mut cargo_cmd = Command::new("cargo");
|
||||
cargo_cmd.current_dir(src_dir);
|
||||
cargo_cmd.arg("build");
|
||||
|
||||
if is_release {
|
||||
cargo_cmd.arg("--release");
|
||||
}
|
||||
|
||||
// Add target if specified
|
||||
if let Some(ref t) = target {
|
||||
cargo_cmd.arg("--target").arg(t);
|
||||
}
|
||||
|
||||
// Add additional cargo args
|
||||
for arg in &flags.cargs {
|
||||
cargo_cmd.arg(arg);
|
||||
}
|
||||
|
||||
// Set environment
|
||||
crate::builder::prepare_command(&mut cargo_cmd, &env_vars);
|
||||
|
||||
let status = cargo_cmd
|
||||
.status()
|
||||
.with_context(|| format!("Failed to run cargo build for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("cargo build failed");
|
||||
}
|
||||
|
||||
// Run post-compile hooks
|
||||
hooks::run_post_compile_commands(spec, src_dir, destdir)?;
|
||||
|
||||
// Install binaries to destdir
|
||||
println!("Installing binaries to DESTDIR...");
|
||||
|
||||
// Determine target directory
|
||||
let target_dir = if let Some(ref t) = target {
|
||||
src_dir.join("target").join(t).join(profile_dir)
|
||||
} else {
|
||||
src_dir.join("target").join(profile_dir)
|
||||
};
|
||||
|
||||
// Use bindir from flags (default: /usr/bin)
|
||||
let bin_dir = destdir.join(flags.bindir.trim_start_matches('/'));
|
||||
fs::create_dir_all(&bin_dir)?;
|
||||
|
||||
// Find and copy executable files
|
||||
if target_dir.exists() {
|
||||
for entry in fs::read_dir(&target_dir)
|
||||
.with_context(|| format!("Failed to read target directory: {}", target_dir.display()))?
|
||||
{
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
// Skip directories and non-executable files
|
||||
if path.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if it's an executable (no extension on Linux, or special check)
|
||||
let file_name = path.file_name().unwrap().to_string_lossy();
|
||||
|
||||
// Skip common non-binary files
|
||||
if file_name.ends_with(".d")
|
||||
|| file_name.ends_with(".rlib")
|
||||
|| file_name.ends_with(".rmeta")
|
||||
|| file_name.contains(".so")
|
||||
|| file_name.starts_with("lib")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if file is executable
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
if path
|
||||
.metadata()
|
||||
.ok()
|
||||
.filter(|m| m.permissions().mode() & 0o111 != 0 && m.is_file())
|
||||
.is_some()
|
||||
{
|
||||
let dest = bin_dir.join(&*file_name);
|
||||
println!(" Installing: {}", file_name);
|
||||
fs::copy(&path, &dest).with_context(|| {
|
||||
format!("Failed to copy {} to {}", path.display(), dest.display())
|
||||
})?;
|
||||
|
||||
// Preserve executable permission
|
||||
let mut perms = fs::metadata(&dest)?.permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(&dest, perms)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run post-install hooks
|
||||
hooks::run_post_install_commands(spec, src_dir, destdir)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user