diff --git a/flowey/flowey/src/lib.rs b/flowey/flowey/src/lib.rs index a940ac58dd..a414b127ed 100644 --- a/flowey/flowey/src/lib.rs +++ b/flowey/flowey/src/lib.rs @@ -14,6 +14,7 @@ pub mod node { pub mod prelude { // include all user-facing types in the prelude + pub use flowey_core::match_arch; pub use flowey_core::node::user_facing::*; // ...in addition, export various types/traits that node impls are diff --git a/flowey/flowey_core/src/node.rs b/flowey/flowey_core/src/node.rs index 5f0a95f422..cc7c64b27b 100644 --- a/flowey/flowey_core/src/node.rs +++ b/flowey/flowey_core/src/node.rs @@ -103,6 +103,20 @@ pub mod user_facing { Ok(()) } + + /// Helper method to handle Linux distros that are supported only on one + /// host architecture. + /// match_arch!(var, arch, result) + #[macro_export] + macro_rules! match_arch { + ($host_arch:expr, $match_arch:pat, $expr:expr) => { + if matches!($host_arch, $match_arch) { + $expr + } else { + anyhow::bail!("Linux distro not supported on host arch {}", $host_arch); + } + }; + } } /// Check if `ReadVar` / `WriteVar` instances are backed by the same underlying @@ -908,6 +922,8 @@ pub enum FlowPlatformLinuxDistro { Fedora, /// Ubuntu (including WSL2) Ubuntu, + /// Arch Linux (including WSL2) + Arch, /// An unknown distribution Unknown, } diff --git a/flowey/flowey_core/src/pipeline.rs b/flowey/flowey_core/src/pipeline.rs index b37fa876b4..7f63278b02 100644 --- a/flowey/flowey_core/src/pipeline.rs +++ b/flowey/flowey_core/src/pipeline.rs @@ -66,6 +66,8 @@ fn linux_distro() -> FlowPlatformLinuxDistro { FlowPlatformLinuxDistro::Ubuntu } else if etc_os_release.contains("ID=fedora") { FlowPlatformLinuxDistro::Fedora + } else if etc_os_release.contains("ID=arch") { + FlowPlatformLinuxDistro::Arch } else { FlowPlatformLinuxDistro::Unknown } diff --git a/flowey/flowey_lib_common/src/_util/extract.rs b/flowey/flowey_lib_common/src/_util/extract.rs index 958fc749d7..9244154101 100644 --- a/flowey/flowey_lib_common/src/_util/extract.rs +++ b/flowey/flowey_lib_common/src/_util/extract.rs @@ -38,6 +38,7 @@ pub fn extract_zip_if_new_deps(ctx: &mut NodeCtx<'_>) -> ExtractZipDeps { FlowPlatform::Linux(linux_distribution) => match linux_distribution { FlowPlatformLinuxDistro::Fedora => vec!["bsdtar".into()], FlowPlatformLinuxDistro::Ubuntu => vec!["libarchive-tools".into()], + FlowPlatformLinuxDistro::Arch => vec!["libarchive".into()], FlowPlatformLinuxDistro::Unknown => vec![], }, _ => { diff --git a/flowey/flowey_lib_common/src/download_azcopy.rs b/flowey/flowey_lib_common/src/download_azcopy.rs index ffb6971205..5a19791fc4 100644 --- a/flowey/flowey_lib_common/src/download_azcopy.rs +++ b/flowey/flowey_lib_common/src/download_azcopy.rs @@ -69,6 +69,7 @@ impl FlowNode for Node { FlowPlatform::Linux(linux_distribution) => match linux_distribution { FlowPlatformLinuxDistro::Fedora => vec!["bsdtar".into()], FlowPlatformLinuxDistro::Ubuntu => vec!["libarchive-tools".into()], + FlowPlatformLinuxDistro::Arch => vec!["libarchive".into()], FlowPlatformLinuxDistro::Unknown => vec![], }, _ => { diff --git a/flowey/flowey_lib_common/src/install_dist_pkg.rs b/flowey/flowey_lib_common/src/install_dist_pkg.rs index c0abaa79ee..e456d7e9d3 100644 --- a/flowey/flowey_lib_common/src/install_dist_pkg.rs +++ b/flowey/flowey_lib_common/src/install_dist_pkg.rs @@ -60,6 +60,9 @@ impl PackageManager { let fmt = "%{NAME}\n"; xshell::cmd!(sh, "rpm -q --queryformat={fmt} {packages_to_check...}") } + FlowPlatformLinuxDistro::Arch => { + xshell::cmd!(sh, "pacman -Qq {packages_to_check...}") + } FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"), } .ignore_status() @@ -85,6 +88,8 @@ impl PackageManager { match distro { FlowPlatformLinuxDistro::Ubuntu => xshell::cmd!(sh, "sudo apt-get update").run()?, FlowPlatformLinuxDistro::Fedora => xshell::cmd!(sh, "sudo dnf update").run()?, + // Running `pacman -Sy` without a full system update can break everything; do nothing + FlowPlatformLinuxDistro::Arch => (), FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"), } @@ -109,6 +114,10 @@ impl PackageManager { let auto_accept = (!interactive).then_some("-y"); xshell::cmd!(sh, "sudo dnf install {auto_accept...} {packages...}").run()?; } + FlowPlatformLinuxDistro::Arch => { + let auto_accept = (!interactive).then_some("--noconfirm"); + xshell::cmd!(sh, "sudo pacman -S {auto_accept...} {packages...}").run()?; + } FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"), } diff --git a/flowey/flowey_lib_hvlite/src/build_openhcl_initrd.rs b/flowey/flowey_lib_hvlite/src/build_openhcl_initrd.rs index f0f9bdcc5a..64f8069a3d 100644 --- a/flowey/flowey_lib_hvlite/src/build_openhcl_initrd.rs +++ b/flowey/flowey_lib_hvlite/src/build_openhcl_initrd.rs @@ -59,10 +59,19 @@ impl FlowNode for Node { fn emit(requests: Vec, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> { // ambient deps required by `update-rootfs.py` + let platform = ctx.platform(); + let python_pkg = match platform { + FlowPlatform::Linux(linux_distribution) => match linux_distribution { + FlowPlatformLinuxDistro::Fedora | FlowPlatformLinuxDistro::Ubuntu => "python3", + FlowPlatformLinuxDistro::Arch => "python", + FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"), + }, + _ => anyhow::bail!("Unsupported platform"), + }; let pydeps = ctx.reqv( |side_effect| flowey_lib_common::install_dist_pkg::Request::Install { - package_names: ["python3"].map(Into::into).into(), + package_names: [python_pkg].map(Into::into).into(), done: side_effect, }, ); diff --git a/flowey/flowey_lib_hvlite/src/init_cross_build.rs b/flowey/flowey_lib_hvlite/src/init_cross_build.rs index 75de2f0fb2..0629ded775 100644 --- a/flowey/flowey_lib_hvlite/src/init_cross_build.rs +++ b/flowey/flowey_lib_hvlite/src/init_cross_build.rs @@ -54,32 +54,46 @@ impl FlowNode for Node { if !native(&target) { let platform = ctx.platform(); - let gcc_arch_str = match target.architecture { - Architecture::X86_64 => match platform { - FlowPlatform::Linux(linux_distribution) => match linux_distribution { - FlowPlatformLinuxDistro::Fedora => "x86_64", - FlowPlatformLinuxDistro::Ubuntu => "x86-64", - FlowPlatformLinuxDistro::Unknown => { - anyhow::bail!("Unknown Linux distribution") - } - }, - _ => anyhow::bail!("Unsupported platform"), - }, - Architecture::Aarch64(_) => "aarch64", - arch => anyhow::bail!("unsupported arch {arch}"), - }; match (platform, target.operating_system) { (FlowPlatform::Linux(_), target_lexicon::OperatingSystem::Linux) => { let (gcc_pkg, bin) = match target.architecture { - Architecture::Aarch64(_) => ( - format!("gcc-{gcc_arch_str}-linux-gnu"), - "aarch64-linux-gnu-gcc".to_string(), - ), - Architecture::X86_64 => ( - format!("gcc-{gcc_arch_str}-linux-gnu"), - "x86_64-linux-gnu-gcc".to_string(), - ), + Architecture::X86_64 => match platform { + FlowPlatform::Linux(linux_distribution) => { + let pkg = match linux_distribution { + FlowPlatformLinuxDistro::Fedora => "gcc-x86_64-linux-gnu", + FlowPlatformLinuxDistro::Ubuntu => "gcc-x86-64-linux-gnu", + FlowPlatformLinuxDistro::Arch => { + match_arch!(host_arch, FlowArch::X86_64, "gcc") + } + FlowPlatformLinuxDistro::Unknown => { + anyhow::bail!("Unknown Linux distribution") + } + }; + (pkg.to_string(), "x86_64-linux-gnu-gcc".to_string()) + } + _ => anyhow::bail!("Unsupported platform"), + }, + Architecture::Aarch64(_) => match platform { + FlowPlatform::Linux(linux_distribution) => { + let pkg = match linux_distribution { + FlowPlatformLinuxDistro::Fedora + | FlowPlatformLinuxDistro::Ubuntu => { + "gcc-aarch64-linux-gnu" + } + FlowPlatformLinuxDistro::Arch => match_arch!( + host_arch, + FlowArch::X86_64, + "aarch64-linux-gnu-gcc" + ), + FlowPlatformLinuxDistro::Unknown => { + anyhow::bail!("Unknown Linux distribution") + } + }; + (pkg.to_string(), "aarch64-linux-gnu-gcc".to_string()) + } + _ => anyhow::bail!("Unsupported platform"), + }, arch => anyhow::bail!("unsupported arch {arch}"), }; diff --git a/flowey/flowey_lib_hvlite/src/run_split_debug_info.rs b/flowey/flowey_lib_hvlite/src/run_split_debug_info.rs index adebaacb74..e35b27501d 100644 --- a/flowey/flowey_lib_hvlite/src/run_split_debug_info.rs +++ b/flowey/flowey_lib_hvlite/src/run_split_debug_info.rs @@ -32,23 +32,47 @@ impl SimpleFlowNode for Node { out_dbg_info, } = request; + let host_arch = ctx.arch(); let platform = ctx.platform(); - let arch_str = match arch { + let (objcopy_pkg, objcopy_bin) = match arch { CommonArch::X86_64 => match platform { FlowPlatform::Linux(linux_distribution) => match linux_distribution { - FlowPlatformLinuxDistro::Fedora => "x86_64", - FlowPlatformLinuxDistro::Ubuntu => "x86-64", + FlowPlatformLinuxDistro::Fedora => { + ("binutils-x86_64-linux-gnu", "x86_64-linux-gnu-objcopy") + } + FlowPlatformLinuxDistro::Ubuntu => { + ("binutils-x86-64-linux-gnu", "x86_64-linux-gnu-objcopy") + } + FlowPlatformLinuxDistro::Arch => { + match_arch!(host_arch, FlowArch::X86_64, ("binutils", "objcopy")) + } FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"), }, _ => anyhow::bail!("Unsupported platform"), }, - CommonArch::Aarch64 => "aarch64", + CommonArch::Aarch64 => { + let pkg = match platform { + FlowPlatform::Linux(linux_distribution) => match linux_distribution { + FlowPlatformLinuxDistro::Fedora | FlowPlatformLinuxDistro::Ubuntu => { + "binutils-aarch64-linux-gnu" + } + FlowPlatformLinuxDistro::Arch => { + match_arch!(host_arch, FlowArch::X86_64, "aarch64-linux-gnu-binutils") + } + FlowPlatformLinuxDistro::Unknown => { + anyhow::bail!("Unknown Linux distribution") + } + }, + _ => anyhow::bail!("Unsupported platform"), + }; + (pkg, "aarch64-linux-gnu-objcopy") + } }; let installed_objcopy = ctx.reqv( |side_effect| flowey_lib_common::install_dist_pkg::Request::Install { - package_names: vec![format!("binutils-{arch_str}-linux-gnu")], + package_names: vec![objcopy_pkg.into()], done: side_effect, }, ); @@ -63,11 +87,10 @@ impl SimpleFlowNode for Node { let sh = xshell::Shell::new()?; let output = sh.current_dir().join(in_bin.file_name().unwrap()); - let objcopy = format!("{}-linux-gnu-objcopy", arch.as_arch()); - xshell::cmd!(sh, "{objcopy} --only-keep-debug {in_bin} {output}.dbg").run()?; + xshell::cmd!(sh, "{objcopy_bin} --only-keep-debug {in_bin} {output}.dbg").run()?; xshell::cmd!( sh, - "{objcopy} --strip-all --keep-section=.build_info --add-gnu-debuglink={output}.dbg {in_bin} {output}" + "{objcopy_bin} --strip-all --keep-section=.build_info --add-gnu-debuglink={output}.dbg {in_bin} {output}" ) .run()?;