exp: cross #6

This commit is contained in:
2025-12-22 23:08:44 +01:00
parent 63389f0bad
commit 3ecfe6dda2
6 changed files with 101 additions and 16 deletions

View File

@@ -19,7 +19,6 @@ pub fn build_source_package(cwd: Option<&Path>) -> Result<(), Box<dyn Error>> {
#[cfg(test)]
mod tests {
use super::*;
// We are not testing the build part, as for now this is just a wrapper
// around dpkg-buildpackage.

View File

@@ -8,8 +8,15 @@ use std::process::Command;
pub struct LocalDriver;
impl ContextDriver for LocalDriver {
fn ensure_available(&self, src: &Path, _dest_root: &str) -> io::Result<PathBuf> {
src.canonicalize()
fn ensure_available(&self, src: &Path, dest_root: &str) -> io::Result<PathBuf> {
let dest_root_path = Path::new(dest_root);
let dest = dest_root_path.join(src.file_name().unwrap_or(src.as_os_str()));
if src != dest {
// Copy src inside dest_root
self.copy_path(src, &dest)?;
}
dest.canonicalize()
}
fn create_temp_dir(&self) -> io::Result<String> {
@@ -17,8 +24,8 @@ impl ContextDriver for LocalDriver {
Ok(temp_dir.keep().to_string_lossy().to_string())
}
fn retrieve_path(&self, _src: &Path, _dest: &Path) -> io::Result<()> {
Ok(())
fn retrieve_path(&self, src: &Path, dest: &Path) -> io::Result<()> {
self.copy_path(src, dest)
}
fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>> {

View File

@@ -103,3 +103,45 @@ fn find_dsc_file(
}
Ok(dsc_path)
}
#[cfg(test)]
mod tests {
async fn test_build_end_to_end(package: &str, series: &str, arch: Option<&str>, cross: bool) {
let temp_dir = tempfile::tempdir().unwrap();
let cwd = temp_dir.path();
crate::pull::pull(
package,
"",
Some(series),
"",
"",
Some("ubuntu"),
Some(cwd),
None,
)
.await
.expect("Cannot pull package");
// Change directory to the package directory
let cwd = cwd.join(package).join(package);
crate::deb::build_binary_package(arch, Some(series), Some(&cwd), cross, None)
.expect("Cannot build binary package (deb)");
// Check that the .deb files are present
let parent_dir = cwd.parent().expect("Cannot find parent directory");
let deb_files = std::fs::read_dir(parent_dir)
.expect("Cannot read build directory")
.filter_map(|entry| entry.ok())
.filter(|entry| entry.path().extension().is_some_and(|ext| ext == "deb"))
.collect::<Vec<_>>();
assert!(!deb_files.is_empty(), "No .deb files found after build");
}
#[tokio::test]
async fn test_deb_hello_ubuntu_end_to_end() {
test_build_end_to_end("hello", "noble", None, false).await;
}
}

View File

@@ -1,21 +1,19 @@
/// Sbuild binary package building
/// Call 'sbuild' with the dsc file to build the package with unshare
use crate::context;
use crate::deb::find_dsc_file;
use std::error::Error;
pub fn build(
package: &str,
version: &str,
_version: &str,
arch: &str,
series: &str,
build_root: &str,
cross: bool,
) -> Result<(), Box<dyn Error>> {
let dsc_path = find_dsc_file(build_root, package, version)?;
let ctx = context::current();
let mut cmd = ctx.command("sbuild");
cmd.current_dir(format!("{}/{}", build_root, package));
cmd.arg("--chroot-mode=unshare");
if cross {
@@ -28,8 +26,7 @@ pub fn build(
// Add output directory argument
cmd.arg(format!("--build-dir={}", build_root));
let status = cmd.arg(dsc_path).status()?;
let status = cmd.status()?;
if !status.success() {
return Err(format!("sbuild failed with status: {}", status).into());
}

View File

@@ -57,7 +57,7 @@ fn main() {
.arg(arg!(-a --arch <arch> "Target architecture").required(false))
.arg(arg!(--cross "Cross-compile for target architecture (instead of qemu-binfmt)")
.long_help("Cross-compile for target architecture (instead of using qemu-binfmt)\nNote that most packages cannot be cross-compiled").required(false))
.arg(arg!(--mode "Change build mode [sbuild, local]").required(false)
.arg(arg!(--mode <mode> "Change build mode [sbuild, local]").required(false)
.long_help("Change build mode [sbuild, local]\nDefault will chose depending on other parameters, don't provide if unsure")),
)
.subcommand(
@@ -151,8 +151,8 @@ fn main() {
let series = sub_matches.get_one::<String>("series").map(|s| s.as_str());
let arch = sub_matches.get_one::<String>("arch").map(|s| s.as_str());
let cross = sub_matches.get_one::<bool>("cross").unwrap_or(&false);
let mode = sub_matches.get_one::<String>("mode").map(|s| s.as_str());
let mode = match mode {
let mode: Option<&str> = sub_matches.get_one::<String>("mode").map(|s| s.as_str());
let mode: Option<pkh::deb::BuildMode> = match mode {
Some("sbuild") => Some(pkh::deb::BuildMode::Sbuild),
Some("local") => Some(pkh::deb::BuildMode::Local),
_ => None,

View File

@@ -262,6 +262,35 @@ async fn fetch_orig_tarball(
Ok(())
}
async fn fetch_dsc_file(
info: &PackageInfo,
cwd: Option<&Path>,
progress: ProgressCallback<'_>,
) -> Result<(), Box<dyn Error>> {
let target_dir = cwd.unwrap_or_else(|| Path::new("."));
// Find the dsc file in the file list
let dsc_file = info
.stanza
.files
.iter()
.find(|f| f.name.ends_with(".dsc"))
.ok_or("Could not find .dsc file in package info")?;
let filename = &dsc_file.name;
debug!("Fetching dsc file: {}", filename);
download_file_checksum(
format!("{}/{}", &info.archive_url, filename).as_str(),
&dsc_file.sha256,
target_dir,
progress,
)
.await?;
Ok(())
}
async fn fetch_archive_sources(
info: &PackageInfo,
cwd: Option<&Path>,
@@ -399,6 +428,7 @@ pub async fn pull(
0,
);
}
clone_repo(
url.as_str(),
package,
@@ -406,6 +436,7 @@ pub async fn pull(
Some(&package_dir),
progress,
)?;
if !package_info.is_native() {
if let Some(cb) = progress {
cb("Fetching orig tarball...", "", 0, 0);
@@ -414,12 +445,17 @@ pub async fn pull(
} else {
debug!("Native package, skipping orig tarball fetch.");
}
if let Some(cb) = progress {
cb("Fetching dsc file...", "", 0, 0);
}
fetch_dsc_file(&package_info, Some(&package_dir), progress).await?;
} else {
// Fallback to archive fetching
if let Some(cb) = progress {
cb("Downloading from archive...", "", 0, 0);
}
fetch_archive_sources(&package_info, Some(cwd.unwrap_or(Path::new("."))), progress).await?;
fetch_archive_sources(&package_info, Some(&package_dir), progress).await?;
}
Ok(package_info)
@@ -482,16 +518,20 @@ mod tests {
// Check for orig tarball in package dir
let mut found_tarball = false;
let mut found_dsc = false;
for entry in std::fs::read_dir(package_dir).unwrap() {
let entry = entry.unwrap();
let name = entry.file_name().to_string_lossy().to_string();
if name.contains(".orig.tar.") {
found_tarball = true;
break;
}
if name.ends_with(".dsc") {
found_dsc = true;
}
}
assert!(found_tarball, "Orig tarball not found in package dir");
assert!(found_dsc, "DSC file not found in package dir");
}
#[tokio::test]