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
+233
@@ -0,0 +1,233 @@
|
||||
//! Cross-compilation support
|
||||
//!
|
||||
//! Provides configuration for cross-compiling packages with a target triplet prefix.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
/// Cross-compilation configuration
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CrossConfig {
|
||||
/// Target triplet prefix (e.g., "x86_64-linux-musl")
|
||||
pub prefix: String,
|
||||
/// C compiler
|
||||
pub cc: String,
|
||||
/// C++ compiler
|
||||
pub cxx: String,
|
||||
/// Archiver
|
||||
pub ar: String,
|
||||
/// Ranlib
|
||||
pub ranlib: String,
|
||||
/// Strip
|
||||
pub strip: String,
|
||||
/// Linker (ld)
|
||||
pub ld: String,
|
||||
/// nm
|
||||
pub nm: String,
|
||||
/// objcopy
|
||||
pub objcopy: String,
|
||||
/// objdump
|
||||
pub objdump: String,
|
||||
/// readelf
|
||||
pub readelf: String,
|
||||
}
|
||||
|
||||
impl CrossConfig {
|
||||
/// Create a cross-compilation config by discovering tools in PATH
|
||||
pub fn from_prefix(prefix: &str) -> Result<Self> {
|
||||
let cc = find_tool(prefix, &["gcc", "clang"], true)?;
|
||||
let cxx = find_tool(prefix, &["g++", "clang++"], false)
|
||||
.unwrap_or_else(|_| format!("{}-g++", prefix));
|
||||
let ar = find_tool(prefix, &["ar", "llvm-ar"], true)?;
|
||||
let ranlib = find_tool(prefix, &["ranlib", "llvm-ranlib"], false)
|
||||
.unwrap_or_else(|_| format!("{}-ranlib", prefix));
|
||||
let strip = find_tool(prefix, &["strip", "llvm-strip"], false)
|
||||
.unwrap_or_else(|_| format!("{}-strip", prefix));
|
||||
let ld = find_tool(prefix, &["ld", "ld.lld"], false)
|
||||
.unwrap_or_else(|_| format!("{}-ld", prefix));
|
||||
let nm = find_tool(prefix, &["nm", "llvm-nm"], false)
|
||||
.unwrap_or_else(|_| format!("{}-nm", prefix));
|
||||
let objcopy = find_tool(prefix, &["objcopy", "llvm-objcopy"], false)
|
||||
.unwrap_or_else(|_| format!("{}-objcopy", prefix));
|
||||
let objdump = find_tool(prefix, &["objdump", "llvm-objdump"], false)
|
||||
.unwrap_or_else(|_| format!("{}-objdump", prefix));
|
||||
let readelf = find_tool(prefix, &["readelf", "llvm-readelf"], false)
|
||||
.unwrap_or_else(|_| format!("{}-readelf", prefix));
|
||||
|
||||
println!("Cross-compilation tools discovered:");
|
||||
println!(" CC: {}", cc);
|
||||
println!(" CXX: {}", cxx);
|
||||
println!(" AR: {}", ar);
|
||||
println!(" RANLIB: {}", ranlib);
|
||||
println!(" STRIP: {}", strip);
|
||||
|
||||
Ok(Self {
|
||||
prefix: prefix.to_string(),
|
||||
cc,
|
||||
cxx,
|
||||
ar,
|
||||
ranlib,
|
||||
strip,
|
||||
ld,
|
||||
nm,
|
||||
objcopy,
|
||||
objdump,
|
||||
readelf,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the host triple for autotools --host flag
|
||||
pub fn host_triple(&self) -> &str {
|
||||
&self.prefix
|
||||
}
|
||||
|
||||
/// Get the build machine triple (native compiler)
|
||||
pub fn build_triple() -> Result<String> {
|
||||
let output = Command::new("gcc")
|
||||
.arg("-dumpmachine")
|
||||
.output()
|
||||
.or_else(|_| Command::new("cc").arg("-dumpmachine").output())
|
||||
.context("Failed to determine build machine triple")?;
|
||||
|
||||
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
|
||||
}
|
||||
|
||||
/// Generate a CMake toolchain file for cross-compilation
|
||||
pub fn generate_cmake_toolchain(&self, build_dir: &Path) -> Result<PathBuf> {
|
||||
let toolchain_path = build_dir.join("cross-toolchain.cmake");
|
||||
|
||||
let content = format!(
|
||||
r#"# CMake toolchain file for cross-compilation
|
||||
# Generated by nyapm for target: {}
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR {})
|
||||
|
||||
set(CMAKE_C_COMPILER {})
|
||||
set(CMAKE_CXX_COMPILER {})
|
||||
set(CMAKE_AR {} CACHE FILEPATH "Archiver")
|
||||
set(CMAKE_RANLIB {} CACHE FILEPATH "Ranlib")
|
||||
set(CMAKE_STRIP {} CACHE FILEPATH "Strip")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
"#,
|
||||
self.prefix,
|
||||
self.target_arch(),
|
||||
self.cc,
|
||||
self.cxx,
|
||||
self.ar,
|
||||
self.ranlib,
|
||||
self.strip,
|
||||
);
|
||||
|
||||
fs::create_dir_all(build_dir)?;
|
||||
let mut file = fs::File::create(&toolchain_path)?;
|
||||
file.write_all(content.as_bytes())?;
|
||||
|
||||
Ok(toolchain_path)
|
||||
}
|
||||
|
||||
/// Generate a Meson cross file for cross-compilation
|
||||
pub fn generate_meson_cross_file(&self, build_dir: &Path) -> Result<PathBuf> {
|
||||
let cross_path = build_dir.join("cross-file.ini");
|
||||
|
||||
let content = format!(
|
||||
r#"# Meson cross file for cross-compilation
|
||||
# Generated by nyapm for target: {}
|
||||
|
||||
[binaries]
|
||||
c = '{}'
|
||||
cpp = '{}'
|
||||
ar = '{}'
|
||||
strip = '{}'
|
||||
ld = '{}'
|
||||
nm = '{}'
|
||||
objcopy = '{}'
|
||||
objdump = '{}'
|
||||
readelf = '{}'
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = '{}'
|
||||
cpu = '{}'
|
||||
endian = 'little'
|
||||
"#,
|
||||
self.prefix,
|
||||
self.cc,
|
||||
self.cxx,
|
||||
self.ar,
|
||||
self.strip,
|
||||
self.ld,
|
||||
self.nm,
|
||||
self.objcopy,
|
||||
self.objdump,
|
||||
self.readelf,
|
||||
self.cpu_family(),
|
||||
self.target_arch(),
|
||||
);
|
||||
|
||||
fs::create_dir_all(build_dir)?;
|
||||
let mut file = fs::File::create(&cross_path)?;
|
||||
file.write_all(content.as_bytes())?;
|
||||
|
||||
Ok(cross_path)
|
||||
}
|
||||
|
||||
/// Extract target architecture from prefix
|
||||
fn target_arch(&self) -> &str {
|
||||
self.prefix.split('-').next().unwrap_or("unknown")
|
||||
}
|
||||
|
||||
/// Get CPU family for Meson
|
||||
fn cpu_family(&self) -> &str {
|
||||
let arch = self.target_arch();
|
||||
match arch {
|
||||
"x86_64" | "amd64" => "x86_64",
|
||||
"i686" | "i586" | "i486" | "i386" => "x86",
|
||||
"aarch64" | "arm64" => "aarch64",
|
||||
"arm" | "armv7" | "armv7l" => "arm",
|
||||
"riscv64" => "riscv64",
|
||||
"riscv32" => "riscv32",
|
||||
"powerpc64" | "ppc64" => "ppc64",
|
||||
"powerpc" | "ppc" => "ppc",
|
||||
"mips64" => "mips64",
|
||||
"mips" => "mips",
|
||||
_ => arch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Find a cross-compilation tool in PATH
|
||||
fn find_tool(prefix: &str, suffixes: &[&str], required: bool) -> Result<String> {
|
||||
for suffix in suffixes {
|
||||
let tool_name = format!("{}-{}", prefix, suffix);
|
||||
if tool_exists(&tool_name) {
|
||||
return Ok(tool_name);
|
||||
}
|
||||
}
|
||||
|
||||
if required {
|
||||
anyhow::bail!(
|
||||
"Could not find cross tool: {}-{{{}}}",
|
||||
prefix,
|
||||
suffixes.join("|")
|
||||
);
|
||||
}
|
||||
|
||||
Err(anyhow::anyhow!("Tool not found"))
|
||||
}
|
||||
|
||||
/// Check if a tool exists in PATH
|
||||
fn tool_exists(name: &str) -> bool {
|
||||
Command::new("which")
|
||||
.arg(name)
|
||||
.output()
|
||||
.map(|o| o.status.success())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
Reference in New Issue
Block a user