use crate::context::Context; use std::collections::HashMap; use std::error::Error; use std::sync::Arc; /// Set environment variables for cross-compilation pub fn setup_environment( env: &mut HashMap, arch: &str, ctx: Arc, ) -> Result<(), Box> { let dpkg_architecture = String::from_utf8( ctx.command("dpkg-architecture") .arg("-a") .arg(arch) .output()? .stdout, )?; let env_var_regex = regex::Regex::new(r"(?.*)=(?.*)").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()); 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, pocket: Option<&str>, ctx: Arc, ) -> Result<(), Box> { let local_arch = crate::get_current_arch(); // 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(()); } // Load existing sources let mut sources = crate::apt::sources::load(Some(ctx.clone()))?; // Ensure all components are enabled for the primary architecture for source in &mut sources { if source.uri.contains("archive.ubuntu.com") || source.uri.contains("security.ubuntu.com") { // Scope to local_arch if not already scoped if source.architectures.is_empty() { source.architectures.push(local_arch.clone()); } // Ensure all components are present let required_components = ["main", "restricted", "universe", "multiverse"]; for &comp in &required_components { if !source.components.contains(&comp.to_string()) { source.components.push(comp.to_string()); } } // Ensure all suites (pockets) are enabled, excluding 'proposed' // unless explicitly requested through the 'pocket' option let mut required_suites = vec![ series.to_string(), format!("{}-updates", series), format!("{}-backports", series), format!("{}-security", series), ]; if let Some(p) = pocket { let pocket_suite = format!("{series}-{p}"); if !required_suites.contains(&pocket_suite) { required_suites.push(pocket_suite); } } for suite in required_suites { if !source.suite.contains(&suite) { source.suite.push(suite); } } } } // Check if ports repository already exists for the target architecture let has_ports = sources .iter() .any(|s| s.uri.contains("ports.ubuntu.com") && s.architectures.contains(&arch.to_string())); if !has_ports { // Add ports repository for the target architecture let mut ports_suites = vec![ series.to_string(), format!("{series}-updates"), format!("{series}-backports"), format!("{series}-security"), ]; if let Some(p) = pocket { let pocket_suite = format!("{series}-{p}"); if !ports_suites.contains(&pocket_suite) { ports_suites.push(pocket_suite); } } let ports_entry = crate::apt::sources::SourceEntry { enabled: true, components: vec![ "main".to_string(), "restricted".to_string(), "universe".to_string(), "multiverse".to_string(), ], architectures: vec![arch.to_string()], uri: "http://ports.ubuntu.com/ubuntu-ports".to_string(), suite: ports_suites, }; sources.push(ports_entry); } // Save the updated sources // Try to save in DEB822 format first, fall back to legacy format let deb822_path = "/etc/apt/sources.list.d/ubuntu.sources"; if ctx .command("test") .arg("-f") .arg(deb822_path) .status()? .success() { // For DEB822 format, we need to reconstruct the file content let mut content = String::new(); for source in &sources { if !source.enabled { continue; } content.push_str("Types: deb\n"); content.push_str(&format!("URIs: {}\n", source.uri)); content.push_str(&format!("Suites: {}\n", source.suite.join(" "))); content.push_str(&format!("Components: {}\n", source.components.join(" "))); content.push_str("Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n"); content.push_str(&format!( "Architectures: {}\n", source.architectures.join(" ") )); content.push('\n'); } ctx.write_file(std::path::Path::new(deb822_path), &content)?; } else { // Fall back to legacy format crate::apt::sources::save_legacy(Some(ctx.clone()), sources, "/etc/apt/sources.list")?; } Ok(()) }