exp: cross #3

This commit is contained in:
2025-12-21 21:37:56 +01:00
parent 31bcd28c72
commit 0d4ae565dd
5 changed files with 197 additions and 59 deletions

View File

@@ -5,34 +5,28 @@ use std::error::Error;
/// Setup a specific chroot context for native cross builds
pub fn setup_native_context(series: &str) -> Result<(), Box<dyn Error>> {
// Use the system cache directory to store the chroot
let proj_dirs = directories::ProjectDirs::from("com", "pkh", "pkh")
.expect("Could not determine cache directory");
let cache_dir = proj_dirs.cache_dir();
let chroot_path = cache_dir.join(format!("pkh-cross-{series}"));
// Create a temporary directory for the chroot
let chroot_path_str = context::current().create_temp_dir()?;
let chroot_path = std::path::PathBuf::from(chroot_path_str);
// Check if the chroot already exists
if !chroot_path.exists() {
log::debug!(
"Creating new chroot for {} at {}...",
series,
chroot_path.display()
);
std::fs::create_dir_all(&chroot_path)?;
log::debug!(
"Creating new chroot for {} at {}...",
series,
chroot_path.display()
);
let status = context::current()
.command("sudo")
.arg("mmdebstrap")
.arg("--variant=buildd")
.arg(series)
.arg(chroot_path.to_string_lossy().to_string())
.status()?;
let status = context::current()
.command("sudo")
.arg("mmdebstrap")
.arg("--variant=buildd")
.arg(series)
.arg(chroot_path.to_string_lossy().to_string())
.status()?;
if !status.success() {
// Clean up on failure
let _ = std::fs::remove_dir_all(&chroot_path);
return Err(format!("mmdebstrap failed for series {}", series).into());
}
if !status.success() {
// Clean up on failure
let _ = std::fs::remove_dir_all(&chroot_path);
return Err(format!("mmdebstrap failed for series {}", series).into());
}
// Switch to an ephemeral context to build the package in the chroot
@@ -44,6 +38,26 @@ pub fn setup_native_context(series: &str) -> Result<(), Box<dyn Error>> {
Ok(())
}
pub fn clean_native_context() -> Result<(), Box<dyn Error>> {
let ctx = context::current();
if let ContextConfig::Unshare { path, .. } = &ctx.config {
let chroot_path = path.clone();
// Reset to normal context
context::manager().set_current(&context::manager().current_name())?;
// Remove chroot directory
context::current()
.command("sudo")
.arg("rm")
.arg("-rf")
.arg(chroot_path)
.status()?;
}
Ok(())
}
/// Set environment variables for cross-compilation
pub fn setup_environment(
env: &mut HashMap<String, String>,
@@ -109,6 +123,23 @@ pub fn ensure_repositories(arch: &str, series: &str) -> Result<(), Box<dyn Error
.arg(deb822_path)
.status()?;
// Ensure all components are enabled for the primary architecture
ctx.command("sed")
.arg("-i")
.arg("/URIs:.*\\(archive\\|security\\)\\.ubuntu\\.com/,/Components:/ s/^Components:.*/Components: main restricted universe multiverse/")
.arg(deb822_path)
.status()?;
// Ensure all suites (pockets) are enabled for the primary architecture
let suites = format!(
"{series} {series}-updates {series}-backports {series}-security {series}-proposed"
);
ctx.command("sed")
.arg("-i")
.arg(format!("/URIs:.*\\(archive\\|security\\)\\.ubuntu\\.com/,/Suites:/ s/^Suites:.*/Suites: {}/", suites))
.arg(deb822_path)
.status()?;
// Add ports if not already present
let has_ports = ctx
.command("grep")
@@ -130,17 +161,46 @@ pub fn ensure_repositories(arch: &str, series: &str) -> Result<(), Box<dyn Error
} else {
// Traditional sources.list
let sources_path = "/etc/apt/sources.list";
// Scope archive.ubuntu.com and security.ubuntu.com to amd64 if not already scoped
// 1. For lines without [], insert [arch=amd64]
// 2. For lines with [], insert arch=amd64 inside the brackets
// Both only if arch= is not already present on the line
ctx.command("sed")
.arg("-i")
.arg(r"/archive.ubuntu.com\|security.ubuntu.com/ { /arch=/ ! { /^deb \[/ ! s/^deb /deb [arch=amd64] /; /^deb \[/ s/^deb \[\([^]]*\)\]/deb [arch=amd64 \1]/ } }")
.arg(sources_path)
.status()?;
// Ensure all components (main restricted universe multiverse) are present for all archive/security lines
// We match any combination of components at the end and replace with the full set
ctx.command("sed")
.arg("-i")
.arg(r"/archive.ubuntu.com\|security.ubuntu.com/ s/\( main\)\?\([ ]\+restricted\)\?\([ ]\+universe\)\?\([ ]\+multiverse\)\?$/ main restricted universe multiverse/")
.arg(sources_path)
.status()?;
// Ensure all pockets exist. If not, we append them.
// We ignore 'proposed' as it contains unstable software
for pocket in ["", "-updates", "-backports", "-security"] {
let suite = format!("{}{}", series, pocket);
let has_suite = ctx
.command("grep")
.arg("-q")
.arg(format!(" {}", suite))
.arg(sources_path)
.status()?
.success();
if !has_suite {
let line = format!(
"deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ {} main restricted universe multiverse",
suite
);
ctx.command("sh")
.arg("-c")
.arg(format!("echo '{}' >> {}", line, sources_path))
.status()?;
}
}
// Add ports repository to sources.list if not already present
let has_ports = ctx
.command("grep")
@@ -155,8 +215,7 @@ pub fn ensure_repositories(arch: &str, series: &str) -> Result<(), Box<dyn Error
"deb [arch={arch}] http://ports.ubuntu.com/ubuntu-ports {series} main restricted universe multiverse\n\
deb [arch={arch}] http://ports.ubuntu.com/ubuntu-ports {series}-updates main restricted universe multiverse\n\
deb [arch={arch}] http://ports.ubuntu.com/ubuntu-ports {series}-backports main restricted universe multiverse\n\
deb [arch={arch}] http://ports.ubuntu.com/ubuntu-ports {series}-security main restricted universe multiverse\n\
deb [arch={arch}] http://ports.ubuntu.com/ubuntu-ports {series}-proposed main restricted universe multiverse"
deb [arch={arch}] http://ports.ubuntu.com/ubuntu-ports {series}-security main restricted universe multiverse"
);
ctx.command("sh")
.arg("-c")