Build the ISO for the host architecture, adding aarch64 support - #121
Build the ISO for the host architecture, adding aarch64 support#121oceanapplications wants to merge 11 commits into
Conversation
Greptile SummaryThis PR makes ISO construction and installation derive architecture-specific behavior from the build host, adding an aarch64 path while retaining the existing x86_64 selections.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains in the previously reported architecture, boot-path, initramfs, or archive-enumeration fixes. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| builder/build-iso.sh | Centralizes host-architecture selection, stages matching profile and boot inputs, filters unsupported ARM packages, and safely indexes both supported package archive formats. |
| configs/profiledef.sh | Selects the Archiso architecture, firmware boot modes, and SquashFS compression appropriate to the host architecture. |
| configs/aarch64/customize_airootfs.sh | Adapts ALARM kernel naming, creates the live preset and initramfs, and now stops assembly when the required initramfs is absent or empty. |
| configs/airootfs/root/configurator | Emits architecture-correct Limine and mirror settings and selects the ALARM kernel on aarch64. |
| configs/airootfs/usr/share/omarchy-iso/orchestrator/context.py | Makes legacy/default boot intent use the architecture-correct Limine EFI filename. |
| configs/airootfs/usr/share/omarchy-iso/orchestrator/phases_impl.py | Copies, registers, refreshes, and validates the Limine EFI binary appropriate to the installed architecture. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
H[Build host architecture] --> S{uname -m}
S -->|x86_64| X[linux-t2 / Node x64 / zstd]
S -->|aarch64| A[linux-aarch64 / Node arm64 / xz]
X --> P[Stage Archiso profile]
A --> P
P --> G[Rewrite active GRUB kernel paths]
P --> M[Resolve and index offline package mirror]
G --> I[Build bootable ISO]
M --> I
I --> C[Live installer configuration]
C --> L[Install matching Limine EFI binary]
L --> T[Bootable target system]
Reviews (9): Last reviewed commit: "builder: enumerate offline mirror packag..." | Re-trigger Greptile
7625239 to
784d7a2
Compare
784d7a2 to
82c80ab
Compare
82c80ab to
b6289d1
Compare
builder/build-iso.sh hardcodes x86_64 in the places that pick a kernel, a Node
tarball and a package list, and assumes the archiso package is installable.
Derive all of them instead, so the same script builds for either architecture.
Architecture selection:
- one case statement sets ISO_ARCH / ISO_NODE_ARCH / ISO_KERNEL from uname -m;
everything downstream uses those rather than a literal
- packages.$ISO_ARCH for the live environment's own package list
- the Node tarball follows ISO_NODE_ARCH, since Node names its builds
linux-x64 / linux-arm64 rather than by uname
- phases_impl.py, which consumes that tarball during the install, derives the
same suffix from platform.machine(). Both ends have to agree or the
installer aborts with "no bundled Node tarball in /opt/packages" after the
build has already bundled the right file.
- on x86_64 every one of these resolves to exactly the previous value:
linux-t2, packages.x86_64, linux-x64.tar.gz
Host portability, not architecture-specific:
- prefer the archiso package, and fall back to the vendored submodule when the
repository has no archiso (Arch Linux ARM does not). Installing from source
skips the package's dependency closure, so squashfs-tools, dosfstools,
mtools, libisoburn, erofs-utils, arch-install-scripts and e2fsprogs are
requested explicitly on that path. Use install-scripts and install-profiles
rather than the default install target, which runs rst2man for man pages
this build does not use.
- match both .pkg.tar.zst and .pkg.tar.xz when indexing the offline mirror.
Arch ships zstd, Arch Linux ARM still ships xz, and matching only zstd makes
repo-add index almost nothing. It fails silently: repo-add succeeds, the db
exists, pacman -Sy succeeds, and only the resolve reports "target not found"
for everything including base. Both extensions are enumerated rather than
globbed so .sig files are not swept in.
aarch64 package selection, gated on uname -m:
- OMARCHY_ARCH_DROP plus a filter, since pacman -Syw aborts the whole
transaction on the first missing target. Applied to every consumed list, not
just the mirror's download set: filtering only that one produces an ISO that
builds cleanly and then fails partway through a real install.
- quickshell-git and mise substituted for their packaged equivalents.
Verified by building an aarch64 ISO end to end on Arch Linux ARM natively.
b6289d1 to
c90ad3a
Compare
8348de7 to
6197891
Compare
mkarchiso reads packages.$arch from the profile directory. The build seeds the profile from archiso's releng configs, which ship only packages.x86_64, so an aarch64 build had no live package list of its own and would pacstrap only the handful of names appended by build-iso.sh. Derived from releng's packages.x86_64 with the entries that do not exist for aarch64 removed, each checked against the Arch Linux ARM repositories rather than by inspection.
6197891 to
ff59434
Compare
customize_airootfs.sh removed the existing initramfs and then downgraded both mkinitcpio failing and the image being absent to log messages, so an aarch64 ISO could build cleanly and be unbootable -- the GRUB entries load initramfs-linux-aarch64.img by name. mkinitcpio's exit status cannot be used directly here: it exits non-zero on this platform even when it produces a complete image, because archiso's memdisk hook wants the phram module and the memdiskfind binary and neither exists for aarch64 (memdiskfind ships in syslinux, which is x86-only). So the check is on the artefact instead -- a missing or empty image now exits 1, which mkarchiso propagates since it runs under set -e. The same applies to the kernel image the preset points at: if neither /boot/Image nor /boot/vmlinuz-linux-aarch64 exists, say so rather than letting mkinitcpio fail confusingly further down.
The script read as though it hand-rolls initramfs generation for aarch64. It
does not, and should not: on Arch that is automatic, because the kernel package
installs usr/lib/modules/<ver>/{vmlinuz,pkgbase}, 90-mkinitcpio-install.hook
triggers on the former and the alpm script reads the latter for the kernel name.
Arch Linux ARM installs neither, which is proposed upstream as
archlinuxarm/PKGBUILDs#2215.
With that applied the hook does fire, verified by staging both files into a
pacstrapped root and installing them: the initramfs is generated automatically.
Two naming gaps remain, and closing those is this script's actual job:
- ALARM's preset writes /boot/initramfs-linux.img while the GRUB entries load
initramfs-linux-aarch64.img
- nothing creates /boot/vmlinuz-*, which is the glob mkarchiso copies the
kernel from
Also records why the deprecated customize_airootfs.sh hook is used at all: the
work has to happen inside the chroot after packages install, since the kernel
image does not exist before that, and shipping the preset through airootfs/ does
not work because the overlay is copied before pacstrap and linux-aarch64's own
preset overwrites it.
Comments only; no behaviour change.
archiso hardcodes a GRUB module list taken from an x86 bug report. at_keyboard is PS/2, and keylayouts, usb and the four usbserial_* drivers are x86-oriented, so none of them are built for arm64-efi and grub-mkstandalone aborts on the first one it cannot find. Without this an aarch64 ISO cannot be built at all. The fix belongs in archiso rather than here, so it is carried as a patch against the vendored copy and applied where the submodule is staged for installation. It uses --forward, so it becomes a no-op once the submodule is bumped past a release containing the change. A check after installation confirms the mkarchiso actually in use can build for this platform, whether it came from the submodule or from a distro package. Failing there with an explanation is better than failing several minutes later inside grub-mkstandalone. The seven modules were confirmed absent by installing grub in an aarch64 container and testing each path under /usr/lib/grub/arm64-efi/.
build-iso.sh checks the installed mkarchiso for _filter_grubmodules before building, but the patch inlined its filtering and never defined that name, so an aarch64 build failed at the guard every time. Move the filtering into a _filter_grubmodules helper that build-iso.sh can find. Its diagnostic goes to stderr, since stdout carries the module list.
The configurator hands archinstall three custom mirror servers, which it prepends to the target's /etc/pacman.d/mirrorlist. All three are Arch x86_64 mirrors laid out as $repo/os/$arch. Arch Linux ARM lays its tree out as $arch/$repo on different hosts, so on aarch64 every one of them 404s ahead of the mirror the distribution's own pacman-mirrorlist package installed, and each pacman -Sy walks through a dozen failures before reaching it. Pass an empty list on aarch64 so archinstall leaves the mirrorlist alone. The x86_64 rendering is byte-identical to before.
repo-add was handed both *.pkg.tar.zst and *.pkg.tar.xz as inline globs. A mirror holding only one format, which is every x86_64 build, leaves the other pattern unmatched; bash passes it to repo-add literally, repo-add reports the file as not found, and set -e aborts the build. Collect the existing files first, as build-omarchy-packages.sh already does, and fail with a clear message if there are none.
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
|
Hardware note from an ASUS Vivobook S 15 S5507QA (Snapdragon X Elite X1E-78-100) that is running Omarchy aarch64 today. The aarch64 pitfalls this PR documents match what we hit:
121 alone does not boot this Snapdragon laptop. We still need the Snapdragon DTB/UKI path (PR 129) and a device kernel ( Happy to boot a 121+129 ISO on this machine once the aarch64 — Grokbot (agent) |
Important
Depends on two things outside this repository.
limine-mkinitcpio-hookrelease that finds kernels without apkgbasemarker.Arch Linux ARM's
linux-aarch64omitsusr/lib/modules/<ver>/pkgbase, andlimine-mkinitcpio-hookreplaces the distribution's90-mkinitcpio-install.hookwith onethat enumerates kernels by that file and silently returns 0 when it is absent. Stock ALARM
generates its initramfs fine; installing Limine turns that into nothing at all, so the
installer completes and writes no boot entries. The fix, a fallback to package ownership
of the module tree, is merged upstream as
Zesko/limine-entry-tool!64
(2026-08-27) but not yet in a tagged release; the newest tag is still 1.37.1, which is
what omarchy-pkgs pins. Once a release ships and
limine-mkinitcpio-hookis bumped there,nothing further is needed here. Verified below with the package built from that commit.
pkgs.omarchy.org, Publish an aarch64 tree at pkgs.omarchy.org omarchy-pkgs#199. Without one thebuild has nowhere to fetch
[omarchy]packages from.Neither is something to work around here.
Adds aarch64 support to the ISO build. Everything is derived from
uname -m; on x86_64 everyselector resolves to the value it has today, and the files x86 reads —
grub.cfg, the pacmanconfigs,
linux-t2.preset— are byte-identical toquattro.Four commits, each a self-contained layer:
builder:configs:boot:installer:builder
One
casesetsISO_ARCH/ISO_NODE_ARCH/ISO_KERNEL. Node needs its own mapping becauseit names builds
linux-x64/linux-arm64rather than byuname;phases_impl.pyderives thesame suffix so the two ends cannot disagree.
Two host-portability fixes that are not architecture-specific:
archisopackage, fall back to the vendored submodule. Not every repositorycarries archiso; Arch Linux ARM has none. Installing from source skips the package's
dependency closure, so
squashfs-tools dosfstools mtools libisoburn erofs-utils arch-install-scripts e2fsprogsare requested explicitly on that path only..pkg.tar.zstand.pkg.tar.xzwhen indexing the offline mirror. Arch shipszstd, Arch Linux ARM still ships xz. Matching only zstd makes
repo-addindex almost nothing,and it fails silently —
repo-addsucceeds, the db exists,pacman -Sysucceeds, and onlythe resolve reports
error: target not found: basefor everything.The package files are enumerated before being handed to
repo-add: an inline glob thatmatches nothing is passed literally, and
repo-addtreats that as a missing file, whichunder
set -ewould have aborted every zstd-only x86_64 build.OMARCHY_ARCH_DROPfilters packages with no aarch64 build (pacman -Sywaborts the wholetransaction on the first missing target). It is applied to all four independently-read
lists — the live environment's
packages.$ISO_ARCH, both shipped Omarchy lists, andarchinstall.packages. Missing any one of them fails late and confusingly; missing the livelist fails at
Failed to install packages to new root.configs
[multilib]is 32-bit x86 libraries and no ARM mirror carries it;[arch-mact2]is an Apple T2repository. Rather than edit the checked-in configs, a filtered copy is staged for aarch64 and
x86_64 keeps reading the originals.
core/extra's explicitServerline points at Omarchy's x86_64-only mirror of Arch. Bothsections already
Includethe mirrorlist, so the line is dropped rather than replaced —substituting another URL would not work, since Arch Linux ARM lays its tree out as
$arch/$reporather than Arch's$repo/os/$arch.plans/aarch64-support.md§8 assumes thatplaceholder adapts automatically; it does not.
boot
arch,bootmodesand the airootfs compression are selected per architecture. ARM has nolegacy BIOS, so aarch64 drops
bios.syslinux.SquashFS compression. Arch Linux ARM builds its kernel without
CONFIG_SQUASHFS_ZSTD(ZLIB, LZ4 and XZ only), so a zstd airootfs builds correctly and then cannot be mounted by the
very kernel on the ISO:
fsconfig() failed: Filesystem uses "zstd" compression. aarch64 usesxz -Xbcj arm; x86_64 keeps zstd, so the measured rationale in the existing comment stands.Worth noting that comment credits the zstd switch with removing an aarch64 blocker — on ALARM
it is the blocker.
grub.cfgis unchanged; it hardcodes the kernel filename, which follows the live kernelpackage, so
build-iso.shsubstitutes it fromISO_KERNELwhen staging (a no-op on x86_64).The live mkinitcpio overrides live in
configs/aarch64/rather thanconfigs/airootfs/, andare installed into the airootfs only on that architecture. They must exist before pacstrap
runs mkinitcpio's pacman hook.
zz-aarch64-live.confis the important one:omarchy_hooks.confdescribes an installed system and sorts afterarchiso.conf, sowithout it the live initramfs has no
archisohook and the ISO panics withFailed to mount '' on real root.The plan says the T2 preset "simply does not ship" on aarch64 and that releng's
linux.presetcovers the stock kernel. That only holds if you boot
linux— on ALARM the kernel islinux-aarch64, so nothing supplies the preset, and the preset is what setsarchiso_config=and thereby bypasses
/etc/mkinitcpio.conf.dentirely. Droppinglinux-t2.presetwithout areplacement looks harmless and is not.
installer
phases_impl.py,context.pyandconfigurator. This is the one to review first. TheArch
liminepackage ships every architecture's binary, soBOOTX64.EFIexists on ARM andthe copy succeeds: the installer writes an x86-64 PE binary to the ESP, registers it with
efibootmgr, andvalidate_boot()then confirmslimine_x64.efiis present, because it is.The install reports success and the machine drops to UEFI setup. It also writes a pacman hook
that re-copies the x86 binary on every
limineupgrade, so it cannot self-heal.detect_kernel()returnslinux; Arch Linux ARM has no barelinuxpackage.target's mirrorlist. All three are Arch x86_64 mirrors laid out as
$repo/os/$arch, so onaarch64 every
pacman -Sywalked through a dozen 404s before reaching the mirror ALARM'sown
pacman-mirrorlistinstalled. aarch64 now passes an empty list so that mirrorlist isleft alone; the x86_64 rendering is byte-identical.
Testing
Built from this branch as pushed, on Arch Linux ARM aarch64 (kernel
7.2.0-2-aarch64-ARCH),natively rather than under QEMU. The only delta from the branch was the
[omarchy]Serverline pointed at a locally built repository, since
pkgs.omarchy.orghas no aarch64 tree; thatrepository carried
limine-mkinitcpio-hookbuilt from upstream master plus thepkgbasefallback described above.
The resulting 3.4 GB ISO boots (GRUB reports
Skipping GRUB module(s) not built for arm64-efi: at_keyboard keylayouts usb usbserial_common usbserial_ftdi usbserial_pl2303 usbserial_usbdebugduring the build), runs the installer to
Installed Omarchy in 2m 2son an encrypted target,and that target boots unattended into the desktop. On the installed system:
The kernel-upgrade path was exercised too: deleting the UKI and running the hook with
usr/lib/initcpio/<ver>on stdin, as pacman does on a kernel upgrade, regenerated itbyte-identical to the original.
A second install from this branch, with omacom/omarchy#8039's
pacman.shin the bundledomarchypackage, checked the package manager on the result: the mirrorlist is ALARM's, andpacman -Sysyncscore,extra,alarmandaurcleanly. The only failure is[omarchy], which 404s until omacom/omarchy-pkgs#199 publishes an aarch64 tree.x86_64 has not been rebuilt. The x86 path is unchanged by inspection — every selector
resolves to its previous literal and the files x86 reads are byte-identical — but that is
inspection, not a build.
Out of scope
Both gaps that used to sit outside this repository are now handled inside it:
at_keyboard,keylayouts,usbandusbserial_*are not built forarm64-efi, sogrub-mkstandaloneaborts. The fix belongs in archiso, so it is carried asbuilder/patches/archiso-grubmodules.patchagainst the vendored copy and applied with--forward, making it a no-op once the submodule is bumped past a release containing it.A post-install check confirms the
mkarchisoactually in use can build for this platform.packages.aarch64— this PR ships its own;mkarchisoreadspackages.$archfrom the profile directory, so no archiso change is needed.pkgs.omarchy.orghas no aarch64 tree (omacom/omarchy-pkgs#199), so an aarch64 buildcurrently needs a locally built repository substituted for
[omarchy]. That is a publishingquestion, so the real URL is left untouched here.
Finally,
configs/efiboot/loader/entries/01-archiso-x86_64-linux.confis dead in this profile —only
uefi.systemd-bootreads it, and neither architecture uses that bootmode.