2
0
mirror of https://github.com/xcat2/xcat-dep.git synced 2026-10-18 01:30:32 +00:00

Merge remote-tracking branch 'up/master' into mm/fix/goconserver-goamd64-v1

This commit is contained in:
Daniel Hilst
2026-10-07 10:57:14 -03:00
8 changed files with 292 additions and 14 deletions
+8
View File
@@ -387,6 +387,14 @@ Because of this, to build `ppc64le` artifacts you must run `mockbuild-all.pl` on
In short: build `ppc64le` packages on a Power machine.
`aarch64` works the same way, natively on an aarch64 host against EPEL, for EL10 only: the
manifest has an `[alma+epel-10-aarch64]` section and no EL8/EL9 one, so pass
`--target alma+epel-10-aarch64` (a run without `--target` also tries rh8 and rh9 and stops at the
missing section). The x86 boot loaders are built there like on ppc64le: `elilo-xcat` ships its
tracked prebuilt EFI payload and `syslinux-xcat` installs the prebuilt bootloader blobs of the
release tarball, so the noarch rpms carry the same payload as the ppc64le build. aarch64 is not
part of the `--finalize-xcat-dep` cross-arch genesis copy.
# riscv64 (EL10): cross-building on an x86_64 host
There is no riscv64 build host in the xCAT build farm and no EPEL for riscv64, so the
+8 -5
View File
@@ -20,11 +20,11 @@ Patch2: elilo-big-bzimage-limit.patch
Patch3: elilo-gnu-efi-strncpy-conflict.patch
Source4: elilo-xcat-3.14-6.noarch.rpm
# Ship the tracked prebuilt EFI payload (SOURCE4) instead of compiling on targets where the
# gnu-efi toolchain layout does not support elilo's build: ppc64le (no x86 EFI toolchain) and
# EL8 (gnu-efi-devel places elf_x86_64_efi.lds under a path elilo's Makefile does not find).
# gnu-efi toolchain layout does not support elilo's build: ppc64le and aarch64 (no x86 EFI
# toolchain) and EL8 (gnu-efi-devel places elf_x86_64_efi.lds under a path elilo's Makefile does not find).
# elilo-x64.efi is a noarch artifact, so the prebuilt is byte-identical to the compiled one.
# Use the tracked prebuilt on ppc (no x86 EFI toolchain) and on EL8 (gnu-efi lds path gap).
# Three SEPARATE %if blocks, each a single simple compare -- NOT one `A || B` expression (the
# Use the tracked prebuilt on ppc and aarch64 (no x86 EFI toolchain) and on EL8 (gnu-efi lds path gap).
# SEPARATE %if blocks, each a single simple compare -- NOT one `A || B` expression (the
# older rpm in the EL8/EL9 mock chroot mis-evaluates `||`), and NOT %ifarch (during `rpmbuild -bs`
# the srpm's BuildRequires are frozen against %{_host_cpu}, not the target). Crucially, alma ppc
# chroots report %{_host_cpu}=powerpc64le while rocky reports ppc64le, so BOTH must be matched --
@@ -35,6 +35,9 @@ Source4: elilo-xcat-3.14-6.noarch.rpm
%if "%{_host_cpu}" == "powerpc64le"
%global use_prebuilt 1
%endif
%if "%{_host_cpu}" == "aarch64"
%global use_prebuilt 1
%endif
%if 0%{?rhel} == 8
%global use_prebuilt 1
%endif
@@ -68,7 +71,7 @@ sed -i 's|^EFILIB[[:space:]]*=.*|EFILIB = /usr/lib64|' Make.defaults
sed -i 's|^EFICRT0[[:space:]]*=.*|EFICRT0 = /usr/lib|' Make.defaults
%endif
%if 0%{?use_prebuilt}
# Reuse the prebuilt EFI payload from the tracked noarch package (ppc64le / EL8).
# Reuse the prebuilt EFI payload from the tracked noarch package (ppc64le / aarch64 / EL8).
mkdir -p prebuilt
rpm2cpio %{SOURCE4} | (cd prebuilt && cpio -idm --quiet)
test -f prebuilt/tftpboot/xcat/elilo-x64.efi
+35 -2
View File
@@ -6,7 +6,7 @@ Name: grub2-xcat
Epoch: 1
Version: 1.0
#Release: snap%(date +"%Y%m%d%H%M")
Release: 3
Release: 4
License: GPLv3+
Group: Applications/System
Vendor: IBM Corp.
@@ -20,6 +20,16 @@ Source1: grub2-res.tar.gz
# BaseOS riscv64 tree (EFI/BOOT/grubriscv64.efi, built from
# grub2-2.12-46.el10_2.rocky.0.1.src.rpm, GPL-3.0-or-later); see readme.
Source2: grubriscv64.efi
# aarch64 nodes boot through UEFI and grub2 like riscv64, but the distro grubaa64.efi
# carries the distro prefix (/EFI/<vendor>) and never finds the boot/grub2/grub.cfg-*
# that nodeset writes. The aarch64 image is therefore generated here with grub2-mkimage
# and the /boot/grub2 prefix grub2.ppc uses. grub2-efi-aa64-modules is noarch, so the
# image builds on every EL build host. The openEuler x86_64 repositories carry no
# grub2-efi-aa64-modules and openEuler has no aarch64 target, so it ships without the image.
%if ! 0%{?openEuler}
BuildRequires: grub2-tools
BuildRequires: grub2-efi-aa64-modules
%endif
Provides: grub2-xcat
Requires:/bin/sh
@@ -27,7 +37,8 @@ Requires:/bin/sh
%description
grub2-xcat provides some grub2 resources generated by grub2-mknetdir,including grub2 modules and grub2 image,
and the EL grub2 UEFI image for riscv64 nodes, which boot through UEFI and grub2 only.
and the EL grub2 UEFI image for riscv64 nodes and an xCAT-prefixed grub2 UEFI image for
aarch64 nodes, which boot through UEFI and grub2 only.
%define _binaries_in_noarch_packages_terminate_build 0
%if 0%{?openEuler}
@@ -46,6 +57,15 @@ and the EL grub2 UEFI image for riscv64 nodes, which boot through UEFI and grub2
#%endif
%build
%if ! 0%{?openEuler}
# The aarch64 network loader: net search finds the boot/grub2/grub.cfg-<HEXIP> that
# nodeset links. efi_uga is left out: it is x86 only, and grub2-mkimage aborts on it
# for arm64-efi.
grub2-mkimage -O arm64-efi -p /boot/grub2 -o %{_builddir}/grubaa64.efi \
tftp efinet net http normal linux configfile search search_fs_file search_fs_uuid \
search_label echo test cat ls boot reboot halt help fat ext2 xfs part_gpt part_msdos \
gzio all_video video efi_gop font gettext terminal terminfo loadenv read sleep
%endif
%pre
@@ -63,6 +83,10 @@ tar -xf grub2-res.tar
%endif
mkdir -p $RPM_BUILD_ROOT/%{prefix}/riscv64-efi
install -m 0644 %{SOURCE2} $RPM_BUILD_ROOT/%{prefix}/riscv64-efi/grubriscv64.efi
%if ! 0%{?openEuler}
mkdir -p $RPM_BUILD_ROOT/%{prefix}/aarch64-efi
install -m 0644 %{_builddir}/grubaa64.efi $RPM_BUILD_ROOT/%{prefix}/aarch64-efi/grubaa64.efi
%endif
@@ -72,6 +96,11 @@ cp %{prefix}/powerpc-ieee1275/core.elf %{prefix}/grub2.ppc
# riscv64 firmware loads boot/grub2/grub2.riscv64 (DHCP client architecture 27)
rm -f %{prefix}/grub2.riscv64
cp %{prefix}/riscv64-efi/grubriscv64.efi %{prefix}/grub2.riscv64
# aarch64 firmware loads boot/grub2/grub2.aarch64 (DHCP client architecture 11)
rm -f %{prefix}/grub2.aarch64
if [ -f %{prefix}/aarch64-efi/grubaa64.efi ]; then
cp %{prefix}/aarch64-efi/grubaa64.efi %{prefix}/grub2.aarch64
fi
exit 0
%clean
@@ -82,6 +111,9 @@ exit 0
# one for sles, one for rhel. yes, it's ugly...
%{prefix}/powerpc-ieee1275/
%{prefix}/riscv64-efi/
%if ! 0%{?openEuler}
%{prefix}/aarch64-efi/
%endif
%defattr(-,root,root)
%postun
@@ -89,5 +121,6 @@ exit 0
if [ "$1" = "0" ]; then
rm %{prefix}/grub2.ppc
rm -f %{prefix}/grub2.riscv64
rm -f %{prefix}/grub2.aarch64
fi
true
+19 -1
View File
@@ -41,7 +41,7 @@ die "Mode regenerate-from-el10-srcrpm is not supported in this script yet; use r
make_path($recompile_dir) if !-d $recompile_dir;
for my $bin (qw(mock rpmbuild rpm dnf file bash tar grep cmp)) {
for my $bin (qw(mock rpmbuild rpm rpm2cpio cpio dnf file bash tar grep cmp)) {
run("command -v " . sh_quote($bin) . " >/dev/null 2>&1");
}
@@ -208,6 +208,24 @@ run(
"rpm -qpl " . sh_quote($main_rpm) .
" | grep -Fx /tftpboot/boot/grub2/riscv64-efi/grubriscv64.efi >/dev/null"
);
# The aarch64 image is generated in %build (grub2-mkimage -O arm64-efi); openEuler ships without it.
if ($mock_cfg !~ /^openeuler-/) {
run(
"rpm -qpl " . sh_quote($main_rpm) .
" | grep -Fx /tftpboot/boot/grub2/aarch64-efi/grubaa64.efi >/dev/null"
);
my $extract_dir = "$work_dir/payload";
remove_tree($extract_dir) if -d $extract_dir;
make_path($extract_dir);
run(
"cd " . sh_quote($extract_dir) . " && rpm2cpio " . sh_quote($main_rpm) .
" | cpio -idm --quiet ./tftpboot/boot/grub2/aarch64-efi/grubaa64.efi"
);
my $aa64_efi = "$extract_dir/tftpboot/boot/grub2/aarch64-efi/grubaa64.efi";
my $aa64_efi_type = pe_image_type($aa64_efi);
die "Unexpected aarch64 grub2 image type: $aa64_efi is $aa64_efi_type, expected PE32+ Aarch64\n"
if $aa64_efi_type ne 'PE32+ Aarch64';
}
print "Verified RPM name/arch/payload: $main_rpm\n";
print_step("Copy artifacts and logs");
+17
View File
@@ -34,3 +34,20 @@ copied to /tftpboot/boot/grub2/grub2.riscv64 by the package scripts, which
is the boot file xCAT hands to DHCP client architecture 27 (0x001b). To
refresh it, take EFI/BOOT/grubriscv64.efi from the BaseOS tree of the EL10
release you target and record the release, source rpm and sha256 here.
#aarch64:
aarch64 nodes boot through UEFI firmware and grub2 only, like riscv64, but
the distro grubaa64.efi cannot be shipped as is: its embedded prefix points
at the distro's /EFI/<vendor> directory, so it never finds the
boot/grub2/grub.cfg-<HEXIP> that nodeset writes. The image is therefore
generated in %build with
grub2-mkimage -O arm64-efi -p /boot/grub2 -o grubaa64.efi <modules>
(BuildRequires grub2-tools and the noarch grub2-efi-aa64-modules), the same
/boot/grub2 prefix the grub2.ppc core image uses. efi_uga is not in the
module list: it is x86 only and grub2-mkimage aborts on it for arm64-efi.
It is installed as /tftpboot/boot/grub2/aarch64-efi/grubaa64.efi and
copied to /tftpboot/boot/grub2/grub2.aarch64 by %post, which is the boot
file xCAT hands to DHCP client architecture 11 (0x000b). The openEuler
build carries no grub2-efi-aa64-modules and ships without the image.
+29
View File
@@ -187,6 +187,35 @@ perl-Net-Telnet=3.04
perl-Sys-Virt=11.10.0
xCAT-genesis-base=>= 2:2.18.0
# alma+epel-10-aarch64 is a native EPEL target like x86_64 and ppc64le, built on an aarch64 host
# (not a forcearch cross-build like riscv64), so it lists what [alma+epel-10-x86_64] lists. The
# x86 boot loaders (elilo-xcat, ipxe-xcat, syslinux-xcat, xnba-undi) are noarch and are listed like
# on ppc64le: an aarch64 management node serves the x86 nodes of a mixed cluster. aarch64 nodes
# themselves boot UEFI and grub2, from the grub2.aarch64 image grub2-xcat generates.
[alma+epel-10-aarch64]
conserver-xcat=8.2.1
elilo-xcat=3.14
goconserver=>= 0.3.3-snap202011021058
grub2-xcat=1.0
ipmitool-xcat=>= 1.8.18-4
ipxe-xcat=2.0.0
syslinux-xcat=>= 6.03-1
xnba-undi=>= 1.21.1-1
perl-Crypt-CBC=2.33
perl-Crypt-Rijndael=1.13
perl-Crypt-SSLeay=0.72
perl-Digest-SHA1=2.13
perl-Expect=1.35
perl-HTML-Form=6.07
perl-HTTP-Async=>= 0.30-3
perl-IO-Stty=>= 0.04-5
perl-IO-Tty=1.20
perl-Net-DNS=1.57
perl-Net-HTTPS-NB=>= 0.14-3
perl-Net-Telnet=3.04
perl-Sys-Virt=11.10.0
xCAT-genesis-base=>= 2:2.18.0
# rocky-10-riscv64-xcat is the forcearch (cross-built) EL10 riscv64 target. It differs from the
# EPEL-fed EL10 sections above in one way (see BUILD.md, "riscv64"): riscv64 has no EPEL, so it
# also builds perl-Crypt-Blowfish, perl-Mail-Sender, perl-Net-IP and perl-Path-Class. A management
+6 -6
View File
@@ -16,7 +16,7 @@ License: GPL
Group: System/Boot
Source0: https://www.kernel.org/pub/linux/utils/boot/syslinux/%{name}-%{VERSION}.tar.xz
Patch0: syslinux-6.03-multibootif.patch
ExclusiveArch: i386 i486 i586 i686 athlon pentium4 x86_64 ppc64le
ExclusiveArch: i386 i486 i586 i686 athlon pentium4 x86_64 ppc64le aarch64
Packager: H. Peter Anvin <hpa@zytor.com>
Buildroot: %{_tmppath}/%{name}-%{VERSION}-root
Autoreq: 0
@@ -30,7 +30,7 @@ BuildRequires: libuuid-devel
# a system bootloader, and may be necessary for system recovery.
%define _sbindir /sbin
%ifnarch ppc64le
%ifnarch ppc64le aarch64
%package devel
Summary: Development environment for SYSLINUX add-on modules
Group: Development/Libraries
@@ -43,7 +43,7 @@ filesystems, Linux ext2/ext3 filesystems (EXTLINUX), PXE network boots
(PXELINUX), or ISO 9660 CD-ROMs (ISOLINUX). It also includes a tool,
MEMDISK, which loads legacy operating systems from these media.
%ifnarch ppc64le
%ifnarch ppc64le aarch64
%description devel
The SYSLINUX boot loader contains an API, called COM32, for writing
sophisticated add-on modules. This package contains the libraries
@@ -88,7 +88,7 @@ make CC='%{my_cc}' PYTHON=python3 installer
%install
rm -rf %{buildroot}
%ifarch ppc64le
%ifarch ppc64le aarch64
make CC='%{my_cc}' PYTHON=python3 install \
INSTALLROOT=%{buildroot} BINDIR=%{_bindir} SBINDIR=%{_sbindir} \
LIBDIR=%{_libdir} DATADIR=%{_datadir} \
@@ -126,14 +126,14 @@ rm -rf %{buildroot}
%{_datadir}/syslinux/*.bin
%{_datadir}/syslinux/*.0
%{_datadir}/syslinux/memdisk
%ifnarch ppc64le
%ifnarch ppc64le aarch64
%{_datadir}/syslinux/dosutil/*
%endif
%{_datadir}/syslinux/diag/*
%{_datadir}/syslinux/efi32
%{_datadir}/syslinux/efi64
%ifnarch ppc64le
%ifnarch ppc64le aarch64
%files devel
%{_datadir}/syslinux/com32
%endif
+170
View File
@@ -0,0 +1,170 @@
#!/usr/bin/env perl
# The EL10 aarch64 target: its manifest cell, the x86 boot loaders it builds natively like ppc64le,
# and the grub2.aarch64 network loader grub2-xcat generates for aarch64 nodes.
#
# alma+epel-10-aarch64 is a native EPEL target, so it must ship what the EL10 x86_64 cell ships: a
# service node perl package missing there would leave `dnf install xCATsn` unresolvable on aarch64
# only. aarch64 nodes boot through UEFI and grub2, and xCAT hands them boot/grub2/grub2.aarch64.
# The distro grubaa64.efi cannot be that file (its prefix is the distro's /EFI/<vendor>), so the
# spec generates one with grub2-mkimage and the /boot/grub2 prefix; efi_uga must stay out of the
# module list, because it is x86 only and grub2-mkimage aborts on it for arm64-efi.
use strict;
use warnings;
use File::Temp qw(tempdir);
use FindBin qw($RealBin);
use Test::More;
use lib $RealBin, "$RealBin/..";
use MockBuildUtils qw(read_manifest);
my $root = "$RealBin/..";
my $target = 'alma+epel-10-aarch64';
sub slurp {
my ($path) = @_;
open(my $fh, '<', $path) or die "read $path: $!";
local $/;
return scalar <$fh>;
}
# The body of one spec section (%build, %install, %post, ...), up to the next section.
sub section {
my ($spec, $name) = @_;
my ($body) = $spec =~ /^%\Q$name\E[ \t]*\n(.*?)(?=^%(?:prep|build|install|check|clean|files|pre|post|preun|postun|changelog|description|package)\b|\z)/ms;
return $body // '';
}
# The grub2-mkimage invocation of a spec text, joined across its continuation lines.
sub mkimage_command {
my ($text) = @_;
my ($cmd) = $text =~ /^(grub2-mkimage\b(?:[^\n]*\\\n)*[^\n]*)$/m;
return unless defined $cmd;
$cmd =~ s/\\\n/ /g;
return $cmd;
}
# rpmspec -P of a spec under extra macro definitions, or undef when rpmspec is unavailable.
my $have_rpmspec = system('command -v rpmspec >/dev/null 2>&1') == 0;
sub parsed_spec {
my ($spec, %define) = @_;
return unless $have_rpmspec;
my @args = map { ('--define', "$_ $define{$_}") } sort keys %define;
# rpmspec warns about the specs' old %patchN and macros in comments; keep that out of TAP.
open(my $save, '>&', \*STDERR) or die "dup STDERR: $!";
open(STDERR, '>', '/dev/null') or die "mute STDERR: $!";
my $out;
if (open(my $fh, '-|', 'rpmspec', '-P', @args, $spec)) {
local $/;
$out = <$fh>;
$out = undef unless close($fh);
}
open(STDERR, '>&', $save) or die "restore STDERR: $!";
return $out;
}
# ---- the manifest cell ---------------------------------------------------------------------------
{
my %m = read_manifest("$root/packages-manifest.conf");
my $cell = $m{$target};
ok($cell, "the manifest has a [$target] section") or $cell = {};
# A native EPEL target: the same packages at the same pins as EL10 x86_64, the service node
# perl set (perl-Crypt-CBC ... perl-Net-DNS) and xCAT-genesis-base included.
is_deeply($cell, $m{'alma+epel-10-x86_64'},
"[$target] lists what [alma+epel-10-x86_64] lists, at the same pins");
# The x86 boot loaders are noarch and an aarch64 management node serves the x86 nodes of a mixed
# cluster, as a ppc64le one does.
for my $boot (qw(elilo-xcat grub2-xcat ipxe-xcat syslinux-xcat xnba-undi)) {
is($cell->{$boot}, $m{'alma+epel-10-ppc64le'}{$boot},
"$boot pinned in [$target] as in the EL10 ppc64le target");
}
}
# ---- grub2-xcat: generate, ship and install grub2.aarch64 --------------------------------------
my $grub_spec_file = "$root/grub2-xcat/grub2-xcat.spec";
my $grub_spec = slurp($grub_spec_file);
{
like($grub_spec, qr/^BuildRequires:\s*grub2-tools\s*$/m, 'grub2-xcat BuildRequires grub2-tools');
like($grub_spec, qr/^BuildRequires:\s*grub2-efi-aa64-modules\s*$/m,
'grub2-xcat BuildRequires the noarch arm64-efi grub modules');
my $cmd = mkimage_command(section($grub_spec, 'build'));
ok(defined $cmd, '%build runs grub2-mkimage') or $cmd = '';
like($cmd, qr/(?:^|\s)-O\s+arm64-efi(?:\s|$)/, '... for the arm64-efi platform');
like($cmd, qr/(?:^|\s)-p\s+\/boot\/grub2(?:\s|$)/, '... with the /boot/grub2 prefix grub2.ppc uses');
like($cmd, qr/(?:^|\s)-o\s+\S*grubaa64\.efi(?:\s|$)/, '... into grubaa64.efi');
my @modules = split ' ', ($cmd =~ /grubaa64\.efi\s+(.*)$/)[0] // '';
for my $mod (qw(tftp efinet net http normal linux configfile search)) {
ok((grep { $_ eq $mod } @modules), "... with the $mod module");
}
ok(!(grep { $_ eq 'efi_uga' } @modules), '... and without efi_uga (x86 only)');
like(section($grub_spec, 'install'),
qr{^install -m 0644 \S*grubaa64\.efi \$RPM_BUILD_ROOT/%\{prefix\}/aarch64-efi/grubaa64\.efi$}m,
'%install ships it as aarch64-efi/grubaa64.efi');
like(section($grub_spec, 'files'), qr{^%\{prefix\}/aarch64-efi/$}m, '%files owns aarch64-efi/');
like(section($grub_spec, 'post'),
qr{^\s*cp\s+%\{prefix\}/aarch64-efi/grubaa64\.efi %\{prefix\}/grub2\.aarch64$}m,
'%post installs it as grub2.aarch64');
like(section($grub_spec, 'postun'), qr{^\s*rm -f %\{prefix\}/grub2\.aarch64$}m,
'%postun removes grub2.aarch64');
SKIP: {
skip 'rpmspec not available', 4 unless $have_rpmspec;
my $el = parsed_spec($grub_spec_file, rhel => 10);
ok(defined $el, 'rpmspec parses grub2-xcat.spec for EL10') or $el = '';
like($el, qr/^BuildRequires:\s*grub2-efi-aa64-modules\s*$/m, '... and EL keeps the aarch64 image');
# openEuler's x86_64 repositories carry no grub2-efi-aa64-modules: there the image is
# neither required nor shipped, and %post must not copy a file that is not there.
my $oe = parsed_spec($grub_spec_file, openEuler => 1);
ok(defined $oe && $oe !~ /grub2-efi-aa64-modules|grub2-mkimage|aarch64-efi\/$/m,
'openEuler builds without the aarch64 image');
like($oe // '', qr{if \[ -f /tftpboot/boot/grub2/aarch64-efi/grubaa64\.efi \]},
'... and its %post copies grub2.aarch64 only when the image exists');
}
# Run the spec's own command where the arm64-efi modules are installed: a module the grub
# build does not carry, or efi_uga, makes grub2-mkimage fail.
SKIP: {
my $moddir = '/usr/lib/grub/arm64-efi';
skip 'grub2-mkimage or the arm64-efi grub modules are not installed', 4
unless -d $moddir && system('command -v grub2-mkimage >/dev/null 2>&1') == 0;
skip 'no grub2-mkimage command in the spec', 4 if $cmd eq '';
my $tmp = tempdir(CLEANUP => 1);
my $run = $cmd;
$run =~ s/(?<=\s-o\s)\S+/$tmp\/grubaa64.efi/;
is(system("$run >/dev/null 2>&1"), 0, "the spec's grub2-mkimage command succeeds");
my $image = '';
if (open(my $fh, '<:raw', "$tmp/grubaa64.efi")) { local $/; $image = <$fh> // ''; }
my $pe = length($image) > 0x40 ? unpack('V', substr($image, 0x3c, 4)) : 0;
is(length($image) > $pe + 6 ? unpack('v', substr($image, $pe + 4, 2)) : 0, 0xaa64,
'... and writes an AArch64 PE image');
like($image, qr{/boot/grub2\0}, '... whose embedded prefix is /boot/grub2');
isnt(system("$run efi_uga >/dev/null 2>&1"), 0, 'adding efi_uga makes the command fail');
}
}
# ---- the x86 boot loaders build natively on aarch64, as on ppc64le -----------------------------
{
my $syslinux = slurp("$root/syslinux/syslinux-xcat.spec");
my ($exclusive) = $syslinux =~ /^ExclusiveArch:\s*(.*?)\s*$/m;
my %arches = map { $_ => 1 } split ' ', $exclusive // '';
ok($arches{aarch64} && $arches{ppc64le}, 'syslinux ExclusiveArch admits aarch64 beside ppc64le');
my @ppc_only = $syslinux =~ /^%ifn?arch ppc64le\s*$/mg;
is_deeply(\@ppc_only, [], 'every ppc64le arch conditional of syslinux covers aarch64 as well');
my $elilo_file = "$root/elilo/elilo-xcat.spec";
SKIP: {
skip 'rpmspec not available', 2 unless $have_rpmspec;
my $aa64 = parsed_spec($elilo_file, _host_cpu => 'aarch64', rhel => 10) // '';
unlike($aa64, qr/^BuildRequires:\s*gnu-efi/m,
'elilo on aarch64 needs no gnu-efi (it ships the tracked prebuilt EFI payload)');
my $x86 = parsed_spec($elilo_file, _host_cpu => 'x86_64', rhel => 10) // '';
like($x86, qr/^BuildRequires:\s*gnu-efi/m, '... while EL10 x86_64 still compiles it');
}
}
done_testing;