exp: cross #2
This commit is contained in:
169
src/deb/cross.rs
Normal file
169
src/deb/cross.rs
Normal file
@@ -0,0 +1,169 @@
|
||||
use crate::context;
|
||||
use crate::context::{Context, ContextConfig};
|
||||
use std::collections::HashMap;
|
||||
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}"));
|
||||
|
||||
// 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)?;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to an ephemeral context to build the package in the chroot
|
||||
context::manager().set_current_ephemeral(Context::new(ContextConfig::Unshare {
|
||||
path: chroot_path.to_string_lossy().to_string(),
|
||||
parent: Some(context::manager().current_name()),
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set environment variables for cross-compilation
|
||||
pub fn setup_environment(
|
||||
env: &mut HashMap<String, String>,
|
||||
arch: &str,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let dpkg_architecture = String::from_utf8(
|
||||
context::current()
|
||||
.command("dpkg-architecture")
|
||||
.arg(format!("-a{}", arch))
|
||||
.output()?
|
||||
.stdout,
|
||||
)?;
|
||||
let env_var_regex = regex::Regex::new(r"(?<key>.*)=(?<value>.*)").unwrap();
|
||||
for l in dpkg_architecture.lines() {
|
||||
let capture = env_var_regex.captures(l).unwrap();
|
||||
let key = capture.name("key").unwrap().as_str().to_string();
|
||||
let value = capture.name("value").unwrap().as_str().to_string();
|
||||
|
||||
env.insert(key.clone(), value.clone());
|
||||
|
||||
if key == "DEB_HOST_GNU_TYPE" {
|
||||
env.insert("CROSS_COMPILE".to_string(), format!("{value}-"));
|
||||
}
|
||||
}
|
||||
env.insert("DEB_BUILD_PROFILES".to_string(), "cross".to_string());
|
||||
env.insert("DEB_BUILD_OPTIONS".to_string(), "nocheck".to_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Ensure that repositories for target architecture are available
|
||||
/// This also handles the 'ports.ubuntu.com' vs 'archive.ubuntu.com' on Ubuntu
|
||||
pub fn ensure_repositories(arch: &str, series: &str) -> Result<(), Box<dyn Error>> {
|
||||
let ctx = context::current();
|
||||
|
||||
// Add target ('host') architecture
|
||||
ctx.command("dpkg")
|
||||
.arg("--add-architecture")
|
||||
.arg(arch)
|
||||
.status()?;
|
||||
|
||||
// Check if we are on Ubuntu
|
||||
let os_release = String::from_utf8(ctx.command("cat").arg("/etc/os-release").output()?.stdout)?;
|
||||
if !os_release.contains("ID=ubuntu") {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Handle DEB822 format (Ubuntu 24.04+)
|
||||
let deb822_path = "/etc/apt/sources.list.d/ubuntu.sources";
|
||||
let has_deb822 = ctx
|
||||
.command("test")
|
||||
.arg("-f")
|
||||
.arg(deb822_path)
|
||||
.status()?
|
||||
.success();
|
||||
|
||||
if has_deb822 {
|
||||
// Scope existing to amd64 if not already scoped
|
||||
// This looks for URIs lines for archive/security and adds Architectures: amd64 on the next line if missing
|
||||
ctx.command("sed")
|
||||
.arg("-i")
|
||||
.arg("/URIs:.*\\(archive\\|security\\)\\.ubuntu\\.com/ { n; /^Architectures:/ ! i Architectures: amd64 }")
|
||||
.arg(deb822_path)
|
||||
.status()?;
|
||||
|
||||
// Add ports if not already present
|
||||
let has_ports = ctx
|
||||
.command("grep")
|
||||
.arg("-q")
|
||||
.arg("ports.ubuntu.com")
|
||||
.arg(deb822_path)
|
||||
.status()?
|
||||
.success();
|
||||
|
||||
if !has_ports {
|
||||
let ports_block = format!(
|
||||
"\nTypes: deb\nURIs: http://ports.ubuntu.com/ubuntu-ports\nSuites: {series} {series}-updates {series}-backports {series}-security {series}-proposed\nComponents: main restricted universe multiverse\nSigned-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\nArchitectures: {arch}\n"
|
||||
);
|
||||
ctx.command("sh")
|
||||
.arg("-c")
|
||||
.arg(format!("echo '{}' >> {}", ports_block, deb822_path))
|
||||
.status()?;
|
||||
}
|
||||
} 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()?;
|
||||
|
||||
// Add ports repository to sources.list if not already present
|
||||
let has_ports = ctx
|
||||
.command("grep")
|
||||
.arg("-q")
|
||||
.arg("ports.ubuntu.com")
|
||||
.arg(sources_path)
|
||||
.status()?
|
||||
.success();
|
||||
|
||||
if !has_ports {
|
||||
let ports_lines = format!(
|
||||
"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"
|
||||
);
|
||||
ctx.command("sh")
|
||||
.arg("-c")
|
||||
.arg(format!("echo '{}' >> {}", ports_lines, sources_path))
|
||||
.status()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user