diff --git a/BUILD.md b/BUILD.md index 59d9a34..15f5f37 100644 --- a/BUILD.md +++ b/BUILD.md @@ -293,6 +293,138 @@ Because of this, to build `ppc64le` artifacts you must run `mockbuild-all.pl` on In short: build `ppc64le` packages on a Power machine. +# 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 +EL10 riscv64 dependency repository (`rh10/riscv64`) is cross-built on an x86_64 host: +mock runs a Rocky Linux 10 riscv64 chroot through user-mode QEMU (`forcearch`), so the +packages are compiled by the riscv64 toolchain of the chroot itself. The mock +configuration for that chroot is shipped in this repository: + +- `mock-configs/rocky-10-riscv64-xcat.cfg` + +It includes the stock `templates/rocky-10.tpl` from mock-core-configs (Rocky 10 BaseOS, +AppStream, CRB and extras for `$basearch` = riscv64) and sets +`root = 'rocky-10-riscv64-xcat'`, `target_arch = 'riscv64'`, +`legal_host_arches = ('x86_64', 'riscv64')` and `forcearch = 'riscv64'`. The stock +`rocky-10-riscv64.cfg` cannot be used from an x86_64 host (it only admits a riscv64 host +and names its chroot `rocky-10-x86_64`). + +## Host prerequisites + +On an x86_64 EL10 host with the baseline tooling from "Prerequisites": + +- `mock` (>= 5) and `mock-core-configs` providing `templates/rocky-10.tpl` and + `rocky-10-x86_64.cfg` (the native, EPEL-free Rocky 10 chroot used for the noarch + packages of the riscv64 build), `podman` (mock pulls the Rocky 10 bootstrap image), + `golang` (goconserver is cross-compiled on the host with `GOARCH=riscv64`). +- A static user-mode QEMU for riscv64 registered in `binfmt_misc` with the `F` (fix + binary) flag. On Fedora this is the `qemu-user-static-riscv` package. EL10 has no such + package: copy `/usr/bin/qemu-riscv64-static` out of a Fedora container (for example + `registry.fedoraproject.org/fedora:44` with `dnf install qemu-user-static-riscv`) to + `/usr/local/bin/qemu-riscv64-static` on the host, then register it: + + ```text + # /etc/binfmt.d/qemu-riscv64-static.conf + :qemu-riscv64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-riscv64-static:FP + ``` + + ```bash + systemctl restart systemd-binfmt + cat /proc/sys/fs/binfmt_misc/qemu-riscv64 # enabled, flags: PF + ``` + +- mock refuses `forcearch` unless `/usr/bin/qemu-riscv64-static` exists (it only checks + for the file; the kernel runs the interpreter registered above). When the binary lives + in `/usr/local/bin`, a symlink is enough: + + ```bash + ln -s /usr/local/bin/qemu-riscv64-static /usr/bin/qemu-riscv64-static + ``` + +Validate the host before building (all as root; mock also accepts members of the `mock` +group): + +```bash +podman run --rm --arch riscv64 quay.io/rockylinux/rockylinux:10 uname -m # riscv64 +install -m 644 mock-configs/rocky-10-riscv64-xcat.cfg /etc/mock/ +mock -r rocky-10-riscv64-xcat --init # ~3-4 min +mock -r rocky-10-riscv64-xcat --chroot -- uname -m # riscv64 +``` + +The per-package `mockbuild.pl` scripts reference the target by name only +(`include('/etc/mock/.cfg')` in their deterministic overlay), so the config must +live in `/etc/mock/` for a build. + +Emulated builds are slow: a chroot init takes 3-4 minutes and a C or XS build 5-30 +minutes instead of seconds, so the riscv64 build of the dependency set takes on the order +of an hour on a large host. Chroots and caches live under `/var/lib/mock` and +`/var/cache/mock` as for any other mock target (about 1 GB per per-package chroot). + +## Building and deploying `rh10/riscv64` + +`mockbuild-all.pl` knows `rocky-10-riscv64-xcat` as a *forcearch target* (see +`%forcearch_targets` in the script): it is selected with `--target` only (the default +rh8/rh9/rh10 run stays the host arch), installs the shipped config into `/etc/mock/` if +missing, and then builds: + +| what | how | +|---|---| +| ipmitool-xcat, conserver-xcat | `mock --rebuild` in the riscv64 chroot (emulated), `--target-arch riscv64` | +| goconserver | cross-compiled on the host (`GOARCH=riscv64`), packaged with `rpmbuild --target riscv64` | +| grub2-xcat (noarch) | built in the native, EPEL-free `rocky-10-x86_64` chroot | +| perl list6 + EPEL gap (`--epel-gap`) | `mockbuild-perl-packages.pl --target-arch riscv64 --noarch-mock-cfg rocky-10-x86_64 --epel-gap`: XS modules in the riscv64 chroot, noarch modules in the native chroot | +| elilo-xcat, syslinux-xcat, xnba-undi | not built (x86 bootloaders) | + +There is no EPEL for riscv64, so the perl deps of xCAT that EL10 otherwise takes from EPEL +are built here as well (`--epel-gap` in `mockbuild-perl-packages.pl`: perl-Crypt-Blowfish, +perl-Crypt-CBC, perl-Crypt-Rijndael, perl-Digest-SHA1, perl-Expect, perl-Mail-Sender, +perl-Net-DNS, perl-Net-IP and the build-only perl-Path-Class), and the noarch deps are +built once, natively, rather than imported from another repo. The required set asserted +after the build is ipmitool-xcat, grub2-xcat, perl-IO-Stty, perl-HTTP-Async and +perl-Net-HTTPS-NB (plus xCAT-genesis-base unless `--skip-genesis`). + +Deliberately not built for riscv64: + +- perl-DB_File: needs libdb, which EL10 dropped (EPEL 10 re-adds it for its own + architectures only, and Rocky Linux 10 riscv64 has no libdb at all). Only the Confluent + client of xCAT-server uses DB_File and xCAT-server only recommends perl-DB_File, so a + riscv64 management node installs without it. +- perl-SOAP-Lite: its Fedora BuildRequires (IO::SessionData, MIME::Lite, XML::Parser::Lite, + Test::XML) are EPEL-only as well, so it can neither be built nor installed without EPEL; + xCAT uses it for HP blade and VirtualBox support only. + +Known differences from the EPEL-fed x86_64 repo: perl-Net-DNS is the 0.80 release of +`perl-Net-DNS/Net-DNS.spec`, built pure-perl (`--noxs`) as noarch, where EPEL 10 ships +1.47 -- its spec BuildRequires perl(Net::LibIDN2), which is EPEL-only too. A newer, +XS-free perl-Net-DNS without that BuildRequires is a follow-up. The riscv64 goconserver +binaries are stripped by the Go linker (`-ldflags "-s -w"`, cross build only) because the +host's brp-strip cannot strip a riscv64 ELF. + +On a host where `/` is small, note that every per-package mock chroot (riscv64 and the +native noarch one) and its bootstrap chroot live under `/var/lib/mock` while it builds +(about 0.5-1 GB each; the bootstrap dirs stay behind after a successful build until +scrubbed), so `--max-parallel` bounds the peak disk usage as well as the CPU load. + +```bash +cd +perl ./mockbuild-all.pl \ + --target rocky-10-riscv64-xcat \ + --output \ + --skip-xcat --skip-genesis --skip-install \ + --max-parallel 8 +``` + +Outputs (as for every target): the build tree under `/mockbuild-all/` and the +deployable repo `/xcat-dep/rh10/riscv64/` (rpms, `repodata/`, `xcat-dep.repo` with +`baseurl=https://xcat.org/files/xcat/repos/yum/devel/xcat-dep/rh10/riscv64`, +`mklocalrepo.sh`, `buildinfo.txt`). Builder failures are tolerated and listed at the end. +The cross-built rpms are smoke-tested without installing them on the host: ipmitool-xcat, +conserver-xcat and the XS perl modules inside the emulated chroot, goconserver by running +its binaries through the binfmt handler. `--skip-install` only skips those checks and the +host installation of the noarch perl rpms (built in the native chroot); pass it when the +build host must stay untouched. + # Validation Commands ```bash diff --git a/conserver/mockbuild.pl b/conserver/mockbuild.pl index 6d175e6..61fca86 100755 --- a/conserver/mockbuild.pl +++ b/conserver/mockbuild.pl @@ -25,6 +25,7 @@ my $version = '8.2.1'; my $work_dir = '/tmp/conserver-mockbuild'; my $mock_cfg = ''; +my $target_arch = ''; my $mock_uniqueext = ''; my $result_dir = "$script_dir/../build-output/list-conserver/conserver"; my $log_dir = "$script_dir/../build-logs/list-conserver/conserver"; @@ -34,6 +35,7 @@ my $build_timestamp; GetOptions( 'work-dir=s' => \$work_dir, 'mock-cfg=s' => \$mock_cfg, + 'target-arch=s' => \$target_arch, 'mock-uniqueext=s' => \$mock_uniqueext, 'result-dir=s' => \$result_dir, 'log-dir=s' => \$log_dir, @@ -63,12 +65,16 @@ if (!$mock_cfg) { my ($rel) = capture('rpm -E %rhel'); $mock_cfg = "${os_id}+epel-${rel}-${arch}"; } +# Arch of the rpms --mock-cfg produces: the host arch unless the config is a forcearch (cross) +# one, e.g. rocky-10-riscv64-xcat built on x86_64 (see BUILD.md "riscv64"). +$target_arch = $arch if $target_arch eq ''; my $uniq = $mock_uniqueext ne '' ? ' --uniqueext ' . sh_quote($mock_uniqueext) : ''; make_path($result_dir, $log_dir); print "package: conserver-xcat\n"; print "version: $version\n"; print "arch: $arch\n"; +print "target-arch:$target_arch\n"; print "mock-cfg: $mock_cfg\n"; print "result-dir: $result_dir\n"; @@ -96,7 +102,7 @@ print "SRPM: $srpm\n"; print "== mock --rebuild ($mock_cfg) ==\n"; my $mock_result = "$work_dir/mock-result"; make_path($mock_result); -run("mock -r " . sh_quote($mock_cfg) . $uniq +run_mock("mock -r " . sh_quote($mock_cfg) . $uniq . " --rebuild " . sh_quote($srpm) . " --resultdir " . sh_quote($mock_result) . " > " . sh_quote("$log_dir/mock-rebuild.log") . " 2>&1"); @@ -104,7 +110,7 @@ run("mock -r " . sh_quote($mock_cfg) . $uniq my @rpms = grep { $_ !~ /\.src\.rpm$/ && $_ !~ /-debug(info|source)-/ } glob("$mock_result/*.rpm"); die "FATAL: no binary RPM produced (see $log_dir/mock-rebuild.log)\n" unless @rpms; -my ($main) = grep { basename($_) =~ /^conserver-xcat-\Q$version\E-.*\.(?:$arch|noarch)\.rpm$/ } @rpms; +my ($main) = grep { basename($_) =~ /^conserver-xcat-\Q$version\E-.*\.(?:$target_arch|noarch)\.rpm$/ } @rpms; die "FATAL: main conserver-xcat RPM not found among: @rpms\n" unless $main; for my $r (@rpms) { @@ -140,8 +146,20 @@ sub capture { chomp $out if defined $out; return $out // ''; } +# mock exits 30 when its package manager failed (chroot init, build deps), which against public +# mirrors is most often a transient download error (stale mirror metadata): retry such a run once. +sub run_mock { + my ($cmd) = @_; + my $rc = system('bash', '-c', $cmd); + if ($rc != -1 && ($rc >> 8) == 30) { + print "mock failed with rc=30 (package manager); retrying once\n"; + $rc = system('bash', '-c', $cmd); + } + die "FATAL: command failed (rc=" . ($rc >> 8) . "): $cmd\n" if $rc != 0; + return 1; +} sub sh_quote { my ($s) = @_; $s =~ s/'/'\\''/g; return "'$s'"; } sub usage { - return "usage: mockbuild.pl --mock-cfg [--result-dir DIR] [--work-dir DIR]\n" + return "usage: mockbuild.pl --mock-cfg [--target-arch ARCH] [--result-dir DIR] [--work-dir DIR]\n" . " [--log-dir DIR] [--mock-uniqueext EXT] [--skip-install]\n"; } diff --git a/goconserver/mockbuild.pl b/goconserver/mockbuild.pl old mode 100755 new mode 100644 index 3b5eb15..5daae09 --- a/goconserver/mockbuild.pl +++ b/goconserver/mockbuild.pl @@ -14,6 +14,7 @@ my $pkg_dir = "$repo_root/goconserver"; my $work_dir = '/tmp/goconserver-mockbuild'; my $mock_cfg = ''; +my $target_arch = ''; my $mock_uniqueext = ''; my $result_dir = "$repo_root/build-output/list5/goconserver"; my $log_dir = "$repo_root/build-logs/list5/goconserver"; @@ -26,6 +27,7 @@ my $build_timestamp; GetOptions( 'work-dir=s' => \$work_dir, 'mock-cfg=s' => \$mock_cfg, + 'target-arch=s' => \$target_arch, 'mock-uniqueext=s' => \$mock_uniqueext, 'result-dir=s' => \$result_dir, 'log-dir=s' => \$log_dir, @@ -50,6 +52,13 @@ if (!$mock_cfg) { my ($rel) = $mock_cfg =~ /-(\d+)-/; $rel //= '10'; +# Arch of the rpm to produce: the host arch unless --mock-cfg is a forcearch (cross) config, +# e.g. rocky-10-riscv64-xcat built on x86_64 (see BUILD.md "riscv64"). goconserver is not built +# in the chroot: go cross-compiles on the host and rpmbuild --target packages the result. +$target_arch = $arch if $target_arch eq ''; +my %goarch = (x86_64 => 'amd64', aarch64 => 'arm64', ppc64le => 'ppc64le', s390x => 's390x', riscv64 => 'riscv64'); +my $cross = $target_arch ne $arch; +die "No GOARCH known for target arch $target_arch\n" if $cross && !exists $goarch{$target_arch}; my $SOURCE_DATE_EPOCH; $SOURCE_DATE_EPOCH = $build_timestamp if defined $build_timestamp; @@ -77,6 +86,7 @@ print "result_dir: $result_dir\n"; print "log_dir: $log_dir\n"; print "mock_cfg: $mock_cfg\n"; print "arch: $arch\n"; +print "target_arch:$target_arch" . ($cross ? " (GOARCH=$goarch{$target_arch}, rpmbuild --target)" : '') . "\n"; print "version: $version\n"; print "go_repo: $go_repo\n"; print "go_ref: $go_ref\n"; @@ -114,6 +124,7 @@ $ENV{GOPATH} = "$work_dir/gopath"; $ENV{GOCACHE} = "$work_dir/gocache"; $ENV{GOMODCACHE} = "$work_dir/gomodcache"; $ENV{CGO_ENABLED} = '0'; +$ENV{GOARCH} = $goarch{$target_arch} if $cross; # The archived github.com/kr/pty sets SysProcAttr.Ctty to the parent-side fd, # which modern Go's os/exec rejects with "Setctty set but Ctty not valid in @@ -129,6 +140,8 @@ my $go_build_dir = "$work_dir/bin"; make_path($go_build_dir); my $ldflags = "-X main.Version=$version"; +# rpm's brp-strip on the host cannot strip a foreign-arch ELF, so let the Go linker do it. +$ldflags .= ' -s -w' if $cross; run("cd " . sh_quote($src_dir) . " && " . "go build -trimpath -buildvcs=false -ldflags " . sh_quote($ldflags) . @@ -187,6 +200,9 @@ run("tar --sort=name --owner=0 --group=0 --mtime=\@$SOURCE_DATE_EPOCH" . " goconserver-$version"); print_step("Create spec and build RPM"); +# rpm refuses 'BuildArch: ' on this host, so a cross build gets its arch from +# rpmbuild --target instead. +my $buildarch_line = $cross ? '' : "BuildArch: $arch"; my $spec_content = <<"SPEC"; Name: goconserver Version: $version @@ -194,7 +210,7 @@ Release: 3.el$rel Summary: Console server written in Go for xCAT License: EPL-1.0 URL: https://github.com/xcat2/goconserver -BuildArch: $arch +$buildarch_line Source0: goconserver-%{version}.tar.gz @@ -239,6 +255,7 @@ run( " --define " . sh_quote("use_source_date_epoch_as_buildtime 1") . " --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") . " --define " . sh_quote("_buildhost xcat-build") . + ($cross ? " --target " . sh_quote($target_arch) : '') . " -ba " . sh_quote($spec_file) . " >" . sh_quote("$log_dir/rpmbuild.log") . " 2>&1" ); @@ -250,7 +267,28 @@ for my $rpm (glob("$rpmbuild_top/RPMS/*/*.rpm"), glob("$rpmbuild_top/SRPMS/*.rpm print "Copied: $dest\n"; } -if (!$skip_install) { +if (!$skip_install && $cross) { + # A cross-built rpm cannot be installed on this host. Unpack it and run the static Go + # binaries through the binfmt_misc handler (qemu-user-static) that the forcearch mock + # builds of the other deps need anyway. + print_step("Smoke test the $target_arch binaries (binfmt)"); + my @built = glob("$rpmbuild_top/RPMS/$target_arch/goconserver-*.rpm"); + die "No $target_arch RPM found\n" if !@built; + my $smoke_root = "$work_dir/smoke-root"; + remove_tree($smoke_root) if -d $smoke_root; + make_path($smoke_root); + run("cd " . sh_quote($smoke_root) . " && rpm2cpio " . sh_quote($built[0]) . " | cpio -idm --quiet" . + " >" . sh_quote("$log_dir/smoke-unpack.log") . " 2>&1"); + for my $bin (qw(goconserver congo)) { + my $path = "$smoke_root/usr/bin/$bin"; + die "Missing $path in the $target_arch rpm\n" if !-x $path; + my $rc = run_rc(sh_quote($path) . " -h >" . sh_quote("$log_dir/smoke-$bin.log") . " 2>&1"); + die "$bin -h failed (rc=$rc): running a $target_arch binary on this $arch host needs the" + . " qemu-user-static binfmt handler (or pass --skip-install)\n" if $rc > 1; + } + print "Smoke tests passed ($target_arch binaries ran through binfmt).\n"; +} +elsif (!$skip_install) { print_step("Install and smoke test"); my @built = glob("$rpmbuild_top/RPMS/$arch/goconserver-*.rpm"); die "No arch RPM found\n" if !@built; @@ -284,6 +322,8 @@ Build goconserver RPM from source. Options: --work-dir PATH Working directory (default: /tmp/goconserver-mockbuild) --mock-cfg NAME Mock config name (auto-detected if omitted) + --target-arch ARCH Arch of the rpm to build (default: uname -m); another arch is + cross-compiled (GOARCH) and packaged with rpmbuild --target --mock-uniqueext STR Mock uniqueext value (for compatibility with mockbuild-all.pl) --result-dir PATH Output directory for RPMs --log-dir PATH Output directory for logs diff --git a/grub2-xcat/debian/changelog b/grub2-xcat/debian/changelog index f0ebc27..2bd314f 100644 --- a/grub2-xcat/debian/changelog +++ b/grub2-xcat/debian/changelog @@ -1,3 +1,10 @@ +grub2-xcat (2.12-2) unstable; urgency=low + + * Ship the EL10 riscv64 grub2 UEFI image as riscv64-efi/grubriscv64.efi and + install it as /tftpboot/boot/grub2/grub2.riscv64 for riscv64 nodes + + -- XCAT Thu, 20 Aug 2026 12:00:00 +0000 + grub2-xcat (2.12-1) unstable; urgency=low * Bump version to satisfy xcat-server dependency (>= 2.02) diff --git a/grub2-xcat/debian/install b/grub2-xcat/debian/install index 5d4ca46..33889a0 100644 --- a/grub2-xcat/debian/install +++ b/grub2-xcat/debian/install @@ -1 +1,2 @@ powerpc-ieee1275/* tftpboot/boot/grub2/powerpc-ieee1275/ +grubriscv64.efi tftpboot/boot/grub2/riscv64-efi/ diff --git a/grub2-xcat/debian/postinst b/grub2-xcat/debian/postinst index f510eca..da555f4 100644 --- a/grub2-xcat/debian/postinst +++ b/grub2-xcat/debian/postinst @@ -22,6 +22,8 @@ case "$1" in configure) rm -f /tftpboot/boot/grub2/grub2.ppc cp /tftpboot/boot/grub2/powerpc-ieee1275/core.elf /tftpboot/boot/grub2/grub2.ppc + rm -f /tftpboot/boot/grub2/grub2.riscv64 + cp /tftpboot/boot/grub2/riscv64-efi/grubriscv64.efi /tftpboot/boot/grub2/grub2.riscv64 ;; abort-upgrade|abort-remove|abort-deconfigure) diff --git a/grub2-xcat/debian/postrm b/grub2-xcat/debian/postrm index 5ec3500..9381339 100644 --- a/grub2-xcat/debian/postrm +++ b/grub2-xcat/debian/postrm @@ -22,6 +22,7 @@ set -e case "$1" in purge|remove) rm /tftpboot/boot/grub2/grub2.ppc + rm -f /tftpboot/boot/grub2/grub2.riscv64 ;; upgrade) ;; diff --git a/grub2-xcat/grub2-xcat.spec b/grub2-xcat/grub2-xcat.spec index 7bda5ea..54bd047 100644 --- a/grub2-xcat/grub2-xcat.spec +++ b/grub2-xcat/grub2-xcat.spec @@ -6,7 +6,7 @@ Name: grub2-xcat Epoch: 1 Version: 1.0 #Release: snap%(date +"%Y%m%d%H%M") -Release: 2 +Release: 3 License: GPLv3+ Group: Applications/System Vendor: IBM Corp. @@ -16,13 +16,18 @@ Prefix: /tftpboot/boot/grub2 BuildRoot: /var/tmp/%{name}-root BuildArch: noarch Source1: grub2-res.tar.gz +# EL10 riscv64 grub2 UEFI image, taken unmodified from the Rocky Linux 10 +# 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 Provides: grub2-xcat Requires:/bin/sh %description -grub2-xcat provides some grub2 resources generated by grub2-mknetdir,including grub2 modules and grub2 image. +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. %define _binaries_in_noarch_packages_terminate_build 0 @@ -53,12 +58,17 @@ cp %{SOURCE1} $RPM_BUILD_ROOT/%{prefix}/ gunzip -f grub2-res.tar.gz 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 %post rm -f %{prefix}/grub2.ppc 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 exit 0 %clean @@ -68,11 +78,13 @@ exit 0 #%{prefix} # one for sles, one for rhel. yes, it's ugly... %{prefix}/powerpc-ieee1275/ +%{prefix}/riscv64-efi/ %defattr(-,root,root) %postun if [ "$1" = "0" ]; then rm %{prefix}/grub2.ppc + rm -f %{prefix}/grub2.riscv64 fi true diff --git a/grub2-xcat/grubriscv64.efi b/grub2-xcat/grubriscv64.efi new file mode 100644 index 0000000..504cbed Binary files /dev/null and b/grub2-xcat/grubriscv64.efi differ diff --git a/grub2-xcat/mockbuild.pl b/grub2-xcat/mockbuild.pl old mode 100755 new mode 100644 index a7848c9..9c978d9 --- a/grub2-xcat/mockbuild.pl +++ b/grub2-xcat/mockbuild.pl @@ -108,6 +108,15 @@ run( " | grep -F 'powerpc-ieee1275/core.elf' >/dev/null" ); +print_step("Verify riscv64 grub2 UEFI image"); +my $riscv_efi = "$pkg_dir/grubriscv64.efi"; +die "Missing required riscv64 grub2 image: $riscv_efi\n" if !-f $riscv_efi; +# Read the PE header ourselves: file(1) only learned the RISC-V PE machine types in 5.38, +# so an older build host (EL8 ships 5.33) would reject a perfectly good image. +my $riscv_efi_type = pe_image_type($riscv_efi); +die "Unexpected riscv64 grub2 image type: $riscv_efi is $riscv_efi_type, expected PE32+ RISC-V 64-bit\n" + if $riscv_efi_type ne 'PE32+ RISC-V 64-bit'; + print_step("Verify spec assets"); for my $asset (@spec_assets) { my $path = "$pkg_dir/$asset"; @@ -143,7 +152,7 @@ print "Prep dry run passed. Applied patches: $patch_count\n"; print_step("Build SRPM with mock"); my $srpm_out = "$work_dir/srpm"; make_path($srpm_out); -run( +run_mock( "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " --buildsrpm --spec " . sh_quote($spec_file) . " --sources " . sh_quote($pkg_dir) . @@ -161,7 +170,7 @@ print "SRPM: $srpm\n"; print_step("Rebuild RPM with mock"); my $rpm_out = "$work_dir/rpm"; make_path($rpm_out); -run( +run_mock( "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " --rebuild " . sh_quote($srpm) . " --resultdir " . sh_quote($rpm_out) . @@ -198,6 +207,10 @@ run( "rpm -qpl " . sh_quote($main_rpm) . " | grep -Fx /tftpboot/boot/grub2/powerpc-ieee1275/core.elf >/dev/null" ); +run( + "rpm -qpl " . sh_quote($main_rpm) . + " | grep -Fx /tftpboot/boot/grub2/riscv64-efi/grubriscv64.efi >/dev/null" +); print "Verified RPM name/arch/payload: $main_rpm\n"; print_step("Copy artifacts and logs"); @@ -241,6 +254,22 @@ if (!$skip_install) { die "Smoke check failed: rpm -qf returned $rc_qf\n" if $rc_qf != 0; die "Smoke check failed: core.elf and grub2.ppc differ (cmp rc=$rc_cmp)\n" if $rc_cmp != 0; + my $riscv_image = '/tftpboot/boot/grub2/riscv64-efi/grubriscv64.efi'; + my $grub2riscv = '/tftpboot/boot/grub2/grub2.riscv64'; + die "Missing installed riscv64 grub2 image: $riscv_image\n" if !-f $riscv_image; + die "Missing installed post script output: $grub2riscv\n" if !-f $grub2riscv; + # The installed image must be the verified source image byte for byte, and %post must have + # copied it to grub2.riscv64. + my $rc_cmp_riscv_src = run_capture_rc("cmp -s " . sh_quote($riscv_efi) . " $riscv_image", + "$log_dir/smoke-cmp-riscv64-source.log"); + my $rc_cmp_riscv = run_capture_rc("cmp -s $riscv_image $grub2riscv", "$log_dir/smoke-cmp-riscv64.log"); + die "Smoke check failed: installed grubriscv64.efi differs from the source image (cmp rc=$rc_cmp_riscv_src)\n" + if $rc_cmp_riscv_src != 0; + die "Smoke check failed: grubriscv64.efi and grub2.riscv64 differ (cmp rc=$rc_cmp_riscv)\n" if $rc_cmp_riscv != 0; + my $riscv_type = pe_image_type($grub2riscv); + die "riscv64 grub2 image type check failed: $grub2riscv is $riscv_type\n" + if $riscv_type ne 'PE32+ RISC-V 64-bit'; + my $core_out = slurp($file_core_log); my $qf_out = slurp($qf_log); @@ -257,6 +286,10 @@ if (!$skip_install) { print {$sfh} "rc_file_ppc=$rc_file_ppc\n"; print {$sfh} "rc_qf=$rc_qf\n"; print {$sfh} "rc_cmp=$rc_cmp\n"; + print {$sfh} "grub2riscv64=$grub2riscv\n"; + print {$sfh} "rc_cmp_riscv64_source=$rc_cmp_riscv_src\n"; + print {$sfh} "type_riscv64=$riscv_type\n"; + print {$sfh} "rc_cmp_riscv64=$rc_cmp_riscv\n"; close $sfh; } @@ -351,6 +384,22 @@ sub capture { return $out; } +# mock exits 30 when its package manager failed (chroot init, build deps), which against public +# mirrors is most often a transient download error (stale mirror metadata): retry such a run once. +sub run_mock { + my ($cmd) = @_; + print "+ $cmd\n"; + my $rc = system($cmd); + if ($rc != -1 && ($rc >> 8) == 30) { + print "mock failed with rc=30 (package manager); retrying once\n"; + $rc = system($cmd); + } + if ($rc != 0) { + my $exit = $rc == -1 ? 255 : ($rc >> 8); + die "Command failed (rc=$exit): $cmd\n"; + } +} + sub run_capture_rc { my ($cmd, $log_file) = @_; my $full = "$cmd > " . sh_quote($log_file) . " 2>&1"; @@ -359,6 +408,26 @@ sub run_capture_rc { return $rc == -1 ? 255 : ($rc >> 8); } +# Image type of a PE file read from its headers, "PE32+ RISC-V 64-bit" for the grub2 UEFI +# image riscv64 firmware loads (COFF machine 0x5064, optional header magic 0x20b); anything +# else comes back as a short description for the error message. +sub pe_image_type { + my ($path) = @_; + open my $fh, '<:raw', $path or die "Cannot read $path: $!\n"; + my $buf = ''; + return 'not an MZ/PE file' if read($fh, $buf, 2) != 2 || $buf ne 'MZ'; + return 'truncated PE file' if !seek($fh, 0x3c, 0) || read($fh, $buf, 4) != 4; + my $pe_off = unpack('V', $buf); + return 'truncated PE file' if !seek($fh, $pe_off, 0) || read($fh, $buf, 26) != 26; + close $fh; + my ($sig, $machine, $magic) = unpack('a4 v x18 v', $buf); + return 'not a PE file' if $sig ne "PE\0\0"; + my %machine_name = (0x5064 => 'RISC-V 64-bit', 0x5032 => 'RISC-V 32-bit', + 0x8664 => 'x86-64', 0xaa64 => 'Aarch64', 0x014c => 'Intel 80386'); + my $format = $magic == 0x20b ? 'PE32+' : $magic == 0x10b ? 'PE32' : sprintf('PE (magic 0x%x)', $magic); + return "$format " . ($machine_name{$machine} // sprintf('machine 0x%04x', $machine)); +} + sub slurp { my ($path) = @_; open my $fh, '<', $path or die "Cannot read $path: $!\n"; diff --git a/grub2-xcat/readme b/grub2-xcat/readme index b364973..0674598 100644 --- a/grub2-xcat/readme +++ b/grub2-xcat/readme @@ -16,3 +16,21 @@ run the following cmd on a RHEL7-PPC64 node: 2.Please update the %version or %release when any modification is made for the files + + +#riscv64: +riscv64 nodes boot through UEFI firmware and grub2 only. The file +grubriscv64.efi (Source2) is the unmodified grub2 UEFI image from the +Rocky Linux 10 riscv64 BaseOS tree (the copy used for installation media +and network boot, embedded prefix /EFI/BOOT): + + path: BaseOS/riscv64/os/EFI/BOOT/grubriscv64.efi (Rocky Linux 10.2) + built from: grub2-2.12-46.el10_2.rocky.0.1.src.rpm (GPL-3.0-or-later), + the same build as grub2-efi-riscv64-2.12-46.el10_2.rocky.0.1 + sha256: 40baf4e65d20f73e6a5ec4f882d8a50450eaaf8b6688acf871824824ef0bad54 + +It is installed as /tftpboot/boot/grub2/riscv64-efi/grubriscv64.efi and +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. diff --git a/ipmitool/mockbuild.pl b/ipmitool/mockbuild.pl old mode 100755 new mode 100644 index 3afcb26..9a5bba8 --- a/ipmitool/mockbuild.pl +++ b/ipmitool/mockbuild.pl @@ -17,6 +17,7 @@ my $source_url = 'https://github.com/ipmitool/ipmitool/archive/refs/tags/IPMITOO my $source_file = ''; my $work_dir = '/tmp/ipmitool-xcat-mockbuild'; my $mock_cfg = ''; +my $target_arch = ''; my $mock_uniqueext = ''; my $result_dir = "$repo_root/build-output/list3/ipmitool-xcat"; my $log_dir = "$repo_root/build-logs/list3/ipmitool-xcat"; @@ -28,6 +29,7 @@ GetOptions( 'source-file=s' => \$source_file, 'work-dir=s' => \$work_dir, 'mock-cfg=s' => \$mock_cfg, + 'target-arch=s' => \$target_arch, 'mock-uniqueext=s' => \$mock_uniqueext, 'result-dir=s' => \$result_dir, 'log-dir=s' => \$log_dir, @@ -55,6 +57,9 @@ if (!$mock_cfg) { my $os_id = capture(q{bash -lc 'source /etc/os-release; echo $ID'}); $mock_cfg = resolve_mock_cfg($os_id, '10', $arch); } +# Arch of the rpms --mock-cfg produces: the host arch unless the config is a forcearch (cross) +# one, e.g. rocky-10-riscv64-xcat built on x86_64 (see BUILD.md "riscv64"). +$target_arch = $arch if $target_arch eq ''; my $mock_uniqueext_opt = $mock_uniqueext ne '' ? ' --uniqueext ' . sh_quote($mock_uniqueext) : ''; @@ -79,6 +84,7 @@ print "work_dir: $work_dir\n"; print "result_dir: $result_dir\n"; print "log_dir: $log_dir\n"; print "mock_cfg: $mock_cfg\n"; +print "target_arch:$target_arch\n"; print "mock_uniqueext: " . ($mock_uniqueext ne '' ? $mock_uniqueext : '(none)') . "\n"; print "source_url: $source_url\n"; print "source_file:$source_file\n"; @@ -132,7 +138,7 @@ print "Patch application check passed. Applied patches: $patch_count\n"; print_step("Build SRPM with mock"); my $srpm_out = "$work_dir/srpm"; make_path($srpm_out); -run( +run_mock( "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " --buildsrpm --spec " . sh_quote($spec_file) . " --sources " . sh_quote($pkg_dir) . @@ -150,7 +156,7 @@ print "SRPM: $srpm\n"; print_step("Rebuild RPM with mock"); my $rpm_out = "$work_dir/rpm"; make_path($rpm_out); -run( +run_mock( "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " --rebuild " . sh_quote($srpm) . " --define " . sh_quote("use_source_date_epoch_as_buildtime 1") . @@ -159,7 +165,7 @@ run( " --resultdir " . sh_quote($rpm_out) ); -my @arch_rpms = sort glob("$rpm_out/*.${arch}.rpm"); +my @arch_rpms = sort glob("$rpm_out/*.${target_arch}.rpm"); die "No architecture RPMs generated in $rpm_out\n" if !@arch_rpms; my $main_rpm = ''; @@ -176,7 +182,7 @@ print_step("Verify generated RPM"); my $rpm_name = capture("rpm -qp --qf '%{NAME}' " . sh_quote($main_rpm)); my $rpm_arch = capture("rpm -qp --qf '%{ARCH}' " . sh_quote($main_rpm)); die "Unexpected RPM name: $rpm_name\n" if $rpm_name ne 'ipmitool-xcat'; -die "Unexpected RPM arch: $rpm_arch (expected $arch)\n" if $rpm_arch ne $arch; +die "Unexpected RPM arch: $rpm_arch (expected $target_arch)\n" if $rpm_arch ne $target_arch; run( "rpm -qpl " . sh_quote($main_rpm) . " | grep -Fx /opt/xcat/bin/ipmitool-xcat >/dev/null" @@ -195,7 +201,28 @@ for my $log (qw(build.log root.log state.log hw_info.log installed_pkgs.log)) { or die "Failed to copy $src to $log_dir: $!\n"; } -if (!$skip_install) { +if (!$skip_install && $target_arch ne $arch) { + # A cross-built rpm cannot be installed on this host: install it into the (emulated) build + # chroot instead and run the binary there. + print_step("Install RPM into the chroot and run smoke tests"); + run_mock("mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " --install " . sh_quote($main_rpm) + . " > " . sh_quote("$log_dir/smoke-chroot-install.log") . " 2>&1"); + my $bin = '/opt/xcat/bin/ipmitool-xcat'; + my $version_log = "$log_dir/smoke-version.log"; + my $rc_version = run_capture_rc( + "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " -q --chroot -- " . sh_quote("$bin -V"), + $version_log); + die "Smoke check failed: -V in the chroot returned $rc_version\n" if $rc_version != 0; + my $version_out = slurp($version_log); + die "Version output missing expected version string\n" + if $version_out !~ /ipmitool-xcat version \Q$version\E/i; + my $summary = "$log_dir/smoke-summary.txt"; + open my $sfh, '>', $summary or die "Cannot write $summary: $!\n"; + print {$sfh} "binary=$bin (in chroot $mock_cfg)\n"; + print {$sfh} "rc_version=$rc_version\n"; + close $sfh; +} +elsif (!$skip_install) { print_step("Install RPM and run smoke tests"); run("dnf -y install " . sh_quote($main_rpm)); @@ -262,6 +289,8 @@ Usage: $0 [options] --source-file FILE Source filename stored in ipmitool/ (default: inferred from spec version) --work-dir PATH Temporary work dir (default: $work_dir) --mock-cfg NAME Mock config (default: +epel-10-) + --target-arch ARCH Arch of the rpms --mock-cfg produces (default: uname -m); a forcearch + config such as rocky-10-riscv64-xcat needs it --mock-uniqueext TXT Optional mock --uniqueext suffix to isolate concurrent builds --result-dir PATH Output RPM/SRPM directory (default: $result_dir) --log-dir PATH Log directory (default: $log_dir) @@ -374,6 +403,22 @@ sub capture { return $out; } +# mock exits 30 when its package manager failed (chroot init, build deps), which against public +# mirrors is most often a transient download error (stale mirror metadata): retry such a run once. +sub run_mock { + my ($cmd) = @_; + print "+ $cmd\n"; + my $rc = system($cmd); + if ($rc != -1 && ($rc >> 8) == 30) { + print "mock failed with rc=30 (package manager); retrying once\n"; + $rc = system($cmd); + } + if ($rc != 0) { + my $exit = $rc == -1 ? 255 : ($rc >> 8); + die "Command failed (rc=$exit): $cmd\n"; + } +} + sub run_capture_rc { my ($cmd, $log_file) = @_; my $full = "$cmd > " . sh_quote($log_file) . " 2>&1"; diff --git a/mock-configs/rocky-10-riscv64-xcat.cfg b/mock-configs/rocky-10-riscv64-xcat.cfg new file mode 100644 index 0000000..686ea67 --- /dev/null +++ b/mock-configs/rocky-10-riscv64-xcat.cfg @@ -0,0 +1,14 @@ +# Rocky Linux 10 riscv64 chroot for the xCAT dependency build, cross-built on an x86_64 host +# through qemu-user-static (binfmt_misc). mock-core-configs ships rocky-10-riscv64.cfg, but it +# only admits a riscv64 build host and names its chroot after the x86_64 one, so it cannot be +# used from the x86_64 hosts that produce the xcat-dep repos; this config includes the same +# template and adds forcearch. There is no EPEL for riscv64, so nothing EPEL-only is reachable +# from this chroot: mockbuild-all.pl builds the EPEL-only perl deps of xCAT for this target. +# See BUILD.md ("riscv64") for the host prerequisites and how mockbuild-all.pl uses it. +include('templates/rocky-10.tpl') + +config_opts['root'] = 'rocky-10-riscv64-xcat' +config_opts['description'] = 'Rocky Linux 10 riscv64 (xCAT dependency build, forcearch)' +config_opts['target_arch'] = 'riscv64' +config_opts['legal_host_arches'] = ('x86_64', 'riscv64') +config_opts['forcearch'] = 'riscv64' diff --git a/mockbuild-all.pl b/mockbuild-all.pl old mode 100755 new mode 100644 index 331577f..d6dd92b --- a/mockbuild-all.pl +++ b/mockbuild-all.pl @@ -150,7 +150,11 @@ acquire_repository_lock($repo_dep, $force_unlock) $xcat_src = resolve_xcat_source($xcat_src, $repo_root); -my $arch = capture_command('uname', '-m'); +my $host_arch = capture_command('uname', '-m'); +# Arch of the target being built: the host arch, except for the forcearch targets below, which +# cross-build another arch on this host. Set per target in build_one_target; the deploy and +# the repo metadata take the arch from the target profile instead of this variable. +my $arch = $host_arch; my %os = read_os_release('/etc/os-release'); my $os_id = $os{ID} // ''; my $version_id = $os{VERSION_ID} // ''; @@ -188,10 +192,28 @@ if ($genesis_release ne '') { # An explicit --target builds just that target; otherwise build the current host # arch across rh8/rh9/rh10 into a deployable per-EL xcat-dep repo. This script builds -# ONLY the host arch (uname -m) -- the other arch is produced on its own build host. +# ONLY the host arch (uname -m) -- the other arch is produced on its own build host -- +# except for the forcearch targets (%forcearch_targets, --target only), which are +# cross-built here through qemu-user-static. my @build_targets = $target ? ($target) - : map { resolve_mock_cfg($os_id, $_, $arch) } (8, 9, 10); + : map { resolve_mock_cfg($os_id, $_, $host_arch) } (8, 9, 10); + +# What a target builds. The mock-core-configs targets (+epel--) build every +# dep natively on the host arch. The forcearch targets shipped in mock-configs/ cross-build +# another arch that has no EPEL: the x86-only bootloaders are not built for it, the EPEL-only +# perl deps of xCAT are (mockbuild-perl-packages.pl --epel-gap), and the noarch deps are built +# in the native, EPEL-free chroot of the same release (the rpms are identical for every arch +# and an emulated build is an order of magnitude slower). See BUILD.md ("riscv64"). +my %forcearch_targets = ( + 'rocky-10-riscv64-xcat' => { + rel => 10, + arch => 'riscv64', + noarch_cfg => "rocky-10-$host_arch", + dep_builders => [qw(grub2-xcat ipmitool-xcat goconserver conserver-xcat)], + required => [qw(ipmitool-xcat grub2-xcat perl-IO-Stty perl-HTTP-Async perl-Net-HTTPS-NB)], + }, +); # NOTE: no dhcp- packages are built here. DHCP backend selection is an install-time # rich dep in xCAT.spec (kea if system-release>=10 else /usr/sbin/dhcpd), so there is @@ -255,8 +277,9 @@ sub build_one_target { # different targets (e.g. alma+epel-8 vs -9) share build-output/ and # cross-contaminate. Fold the target into run_id so each target gets its own tree. $run_id = "$target-$run_id" unless index($run_id, $target) >= 0; - my ($rel) = $target =~ /epel-(\d+)-/; - die "Could not parse EL release from target '$target'\n" unless defined $rel; + my $profile = target_profile($target); + my $rel = $profile->{rel}; + $arch = $profile->{arch}; my $run_root = "$output_root/$run_id"; my $build_root = "$run_root/build-results"; @@ -269,16 +292,18 @@ my $srpm_tarball = "$output_root/mockbuild-all-$target-$run_id-srpm.tar.gz"; # All dep builders run natively on every arch. xnba-undi and grub2-xcat are noarch packagings of # committed artifacts (an x86 UNDI ROM / the grub2 resource tarball) with no arch-specific build -# step, so ppc builds them the same as x86 -- no cross-arch import. +# step, so ppc builds them the same as x86 -- no cross-arch import. A forcearch target builds +# only the builders its profile lists; the noarch ones run in the profile's native chroot. my @dep_builders = ( - { name => 'elilo-xcat', script => "$repo_root/elilo/mockbuild.pl" }, - { name => 'grub2-xcat', script => "$repo_root/grub2-xcat/mockbuild.pl" }, + { name => 'elilo-xcat', script => "$repo_root/elilo/mockbuild.pl", noarch => 1 }, + { name => 'grub2-xcat', script => "$repo_root/grub2-xcat/mockbuild.pl", noarch => 1 }, { name => 'ipmitool-xcat', script => "$repo_root/ipmitool/mockbuild.pl" }, { name => 'syslinux-xcat', script => "$repo_root/syslinux/mockbuild.pl" }, { name => 'goconserver', script => "$repo_root/goconserver/mockbuild.pl" }, { name => 'conserver-xcat', script => "$repo_root/conserver/mockbuild.pl" }, - { name => 'xnba-undi', script => "$repo_root/xnba/mockbuild.pl" }, + { name => 'xnba-undi', script => "$repo_root/xnba/mockbuild.pl", noarch => 1 }, ); +my %profile_builds = map { $_ => 1 } @{ $profile->{dep_builders} }; my $perl_builder = "$repo_root/mockbuild-perl-packages.pl"; @@ -287,6 +312,7 @@ die "Missing xCAT build script: $xcat_src/buildrpms.pl\n" my @active_dep_builders; for my $b (@dep_builders) { + next if !$profile_builds{$b->{name}}; if (-f $b->{script}) { push @active_dep_builders, $b; next; @@ -320,6 +346,10 @@ print "xcat_source: $xcat_src\n"; print "output_root: $output_root\n"; print "run_root: $run_root\n"; print "arch: $arch\n"; +print "host_arch: $host_arch\n"; +print "forcearch: $profile->{forcearch}\n"; +print "noarch_cfg: $profile->{noarch_cfg}\n"; +print "epel: $profile->{epel}\n"; print "os_id: $os_id\n"; print "version_id: $version_id\n"; print "rel: $rel\n"; @@ -343,12 +373,19 @@ print "srpm_tarball: $srpm_tarball\n"; my @collect_roots; +install_mock_cfg($target); + if ($scrub_all_chroots) { run_step( step => "Scrub all chroots for target $target", cmd => "mock -r " . shell_quote($target) . " --scrub=all", log => "$log_root/scrub-all-chroots.log", ); + run_step( + step => "Scrub all chroots for noarch config $profile->{noarch_cfg}", + cmd => "mock -r " . shell_quote($profile->{noarch_cfg}) . " --scrub=all", + log => "$log_root/scrub-all-chroots-noarch.log", + ) if $profile->{noarch_cfg} ne $target; } if (!$skip_build) { @@ -364,7 +401,8 @@ if (!$skip_build) { my $step_uniqueext = build_mock_uniqueext($run_id, ++$build_step_seq, $name); my $cmd = join(' ', 'perl', shell_quote($script), - '--mock-cfg', shell_quote($target), + '--mock-cfg', shell_quote($builder->{noarch} ? $profile->{noarch_cfg} : $target), + ($profile->{forcearch} && !$builder->{noarch} ? ('--target-arch', shell_quote($arch)) : ()), '--mock-uniqueext', shell_quote($step_uniqueext), '--result-dir', shell_quote($step_result), '--log-dir', shell_quote($step_log), @@ -393,6 +431,10 @@ if (!$skip_build) { my $cmd = join(' ', 'perl', shell_quote($perl_builder), '--mock-cfg', shell_quote($target), + ($profile->{forcearch} + ? ('--target-arch', shell_quote($arch), '--noarch-mock-cfg', shell_quote($profile->{noarch_cfg})) + : ()), + ($profile->{epel} ? () : ('--epel-gap')), '--mock-uniqueext', shell_quote($perl_uniqueext), '--result-dir', shell_quote($perl_result), '--log-dir', shell_quote($perl_log), @@ -602,7 +644,7 @@ if (!$dry_run) { print {$sfh} "run_root=$run_root\n"; print {$sfh} "repo_dir=$repo_dir\n"; print {$sfh} "target=$target\n"; - print {$sfh} "arch=$arch\n"; + print {$sfh} "arch=$profile->{arch}\n"; print {$sfh} "os_id=$os_id\n"; print {$sfh} "version_id=$version_id\n"; print {$sfh} "rel=$rel\n"; @@ -631,7 +673,55 @@ print "Summary: $summary_file\n" if !$dry_run; print "Tarball: $tarball\n" if !$skip_tarball; print "SRPM Tarball: $srpm_tarball\n" if !$skip_tarball; - return { repo_dir => $repo_dir, rel => $rel }; + return { repo_dir => $repo_dir, rel => $rel, profile => $profile }; +} + +# The build profile of a target: EL release, arch of the rpms, where its noarch deps are built, +# which dep builders run and which rpms the deployed repo must contain. +sub target_profile { + my ($target) = @_; + if (my $fa = $forcearch_targets{$target}) { + return { + %{$fa}, + forcearch => 1, + epel => 0, + }; + } + my ($rel) = $target =~ /epel-(\d+)-/; + die "Could not parse EL release from target '$target'\n" unless defined $rel; + return { + rel => $rel, + arch => $host_arch, + noarch_cfg => $target, + forcearch => 0, + epel => 1, + dep_builders => [qw(elilo-xcat grub2-xcat ipmitool-xcat syslinux-xcat goconserver conserver-xcat xnba-undi)], + # xCAT Requires all of these on every arch, and every one of them builds natively on + # every arch (the noarch deps -- grub2-xcat, xnba-undi -- just repackage committed + # artifacts), so a self-sufficient per-arch build produces the whole set. + required => [qw(ipmitool-xcat syslinux-xcat grub2-xcat xnba-undi + perl-IO-Stty perl-HTTP-Async perl-Net-HTTPS-NB)], + }; +} + +# The forcearch targets are shipped in mock-configs/; mock, and the include('/etc/mock/.cfg') +# overlays of the per-package builders, need them in /etc/mock. Install a missing one; never +# overwrite one the host already has. +sub install_mock_cfg { + my ($cfg) = @_; + my $src = "$repo_root/mock-configs/$cfg.cfg"; + return if !-f $src; + my $dst = "/etc/mock/$cfg.cfg"; + if (-f $dst) { + die "$dst differs from $src: the build would not use the configuration shipped in this" + . " tree. Remove or update the host copy (it is never overwritten here) and rerun.\n" + if system("cmp -s " . shell_quote($src) . ' ' . shell_quote($dst)) != 0; + return; + } + print "Installing mock config $src -> $dst\n"; + return if $dry_run; + copy($src, $dst) or die "Failed to install $src -> $dst: $!\n"; + chmod 0644, $dst; } # Assemble the built per-target repo into the deployable, signed per-EL layout @@ -639,9 +729,10 @@ print "SRPM Tarball: $srpm_tarball\n" if !$skip_tarball; # xcat-dep.repo / mklocalrepo.sh / buildinfo.txt (ready to push to xcat.org). sub deploy_target { my ($tgt, $info) = @_; - my $rel = $info->{rel}; - my $src = $info->{repo_dir}; - my $dest = "$repo_dep/rh$rel/$arch"; + my $rel = $info->{rel}; + my $src = $info->{repo_dir}; + my $tarch = $info->{profile}{arch}; + my $dest = "$repo_dep/rh$rel/$tarch"; print_step("Deploy $tgt -> $dest"); return if $dry_run; make_path($dest); @@ -651,11 +742,11 @@ sub deploy_target { publish_file($rpm, $destination); } remove_genesis_packages($dest, 0) if $genesis_release; - assert_required_deps($dest); + assert_required_deps($dest, $info->{profile}{required}); sign_and_index_repo($dest); - write_dep_repo_metadata($dest, $rel); + write_dep_repo_metadata($dest, $rel, $tarch); my $n = scalar(grep { !/\.src\.rpm$/ } bsd_glob("$dest/*.rpm")); - print "Deployed rh$rel/$arch: $n rpms\n"; + print "Deployed rh$rel/$tarch: $n rpms\n"; } sub publish_genesis_common_repo { @@ -757,14 +848,14 @@ sub sign_and_index_repo { } sub write_dep_repo_metadata { - my ($dir, $rel) = @_; - my $baseurl = "https://xcat.org/files/xcat/repos/yum/devel/xcat-dep/rh$rel/$arch"; + my ($dir, $rel, $tarch) = @_; + my $baseurl = "https://xcat.org/files/xcat/repos/yum/devel/xcat-dep/rh$rel/$tarch"; my $gpgcheck = $gpg_sign ? 1 : 0; my $gpgkey_line = $gpg_sign ? "gpgkey=$baseurl/repodata/repomd.xml.key" : "# gpgkey="; open my $r, '>', "$dir/xcat-dep.repo" or die "Cannot write $dir/xcat-dep.repo: $!\n"; print {$r} <<"EOF"; [xcat-dep] -name=xCAT 2 dependencies (rh$rel $arch) +name=xCAT 2 dependencies (rh$rel $tarch) baseurl=$baseurl enabled=1 gpgcheck=$gpgcheck @@ -773,7 +864,7 @@ EOF close $r; write_local_repo_helper($dir); - write_buildinfo($dir, "rh$rel/$arch"); + write_buildinfo($dir, "rh$rel/$tarch"); } sub write_common_repo_metadata { @@ -866,8 +957,10 @@ Options: --gpg-sign Sign RPMs and repomd.xml in every published repository --gpg-key-name NAME GPG key name (default: "xCAT Signing Key") --gpg-home PATH GNUPGHOME for signing (default: system keyring) - --target NAME Build only this target (+epel--); default is - the host arch across rh8, rh9 and rh10 + --target NAME Build only this target (+epel--, or a forcearch + config from mock-configs/ such as rocky-10-riscv64-xcat, which + cross-builds that arch on this host); default is the host arch + across rh8, rh9 and rh10 --nproc N Parallel jobs for buildrpms.pl (default: 1) --parallel-builds N Max concurrent top-level build steps within one EL target (default: auto) --parallel-targets N Concurrent EL targets (rh8/rh9/rh10). 0/auto = all at once, 1 = serial, @@ -892,7 +985,7 @@ Options: Notes: - Run this script as root on the build host. - - ARCH is derived from: uname -m + - ARCH is derived from: uname -m (or from the forcearch target) - Top-level parallel queue includes xcat-dep mockbuild.pl steps, perl builder, and ../xcat-core/buildrpms.pl. - Child mockbuild scripts are invoked with per-step mock --uniqueext values @@ -1045,16 +1138,12 @@ sub have_rpm { return scalar(@m) > 0; } -# assert_required_deps: the per-EL dep repo is unusable without these, so a MISSING one is -# fatal even though individual builder failures are tolerated above. genesis-base is required -# unless --skip-genesis. +# assert_required_deps: the per-EL dep repo is unusable without these (the target profile's +# required set), so a MISSING one is fatal even though individual builder failures are +# tolerated above. genesis-base is required unless --skip-genesis. sub assert_required_deps { - my ($dir) = @_; - # xCAT Requires all of these on every arch, and every one of them builds natively on every - # arch (the noarch deps -- grub2-xcat, xnba-undi -- just repackage committed artifacts), so - # a self-sufficient per-arch build produces the whole set with no cross-arch import. - my @req = qw(ipmitool-xcat syslinux-xcat grub2-xcat xnba-undi - perl-IO-Stty perl-HTTP-Async perl-Net-HTTPS-NB); + my ($dir, $required) = @_; + my @req = @{$required}; push @req, 'xCAT-genesis-base' unless $skip_genesis; my @missing = grep { !have_rpm($dir, $_) } @req; die "FATAL: required deps missing from $dir: @missing\n" if @missing; diff --git a/mockbuild-perl-packages.pl b/mockbuild-perl-packages.pl old mode 100755 new mode 100644 index 9408b40..2869aa0 --- a/mockbuild-perl-packages.pl +++ b/mockbuild-perl-packages.pl @@ -12,10 +12,13 @@ use Parallel::ForkManager; my $repo_root = abs_path(dirname(__FILE__)); my $work_dir = '/tmp/perl-list6-mockbuild'; my $mock_cfg = ''; +my $noarch_mock_cfg = ''; +my $target_arch = ''; my $mock_uniqueext = ''; my $result_dir = ''; my $log_dir = ''; my $packages_csv = ''; +my $epel_gap = 0; my $jobs = 0; my $skip_install = 0; my $allow_erasing = 0; @@ -24,10 +27,13 @@ my $build_timestamp; GetOptions( 'work-dir=s' => \$work_dir, 'mock-cfg=s' => \$mock_cfg, + 'noarch-mock-cfg=s' => \$noarch_mock_cfg, + 'target-arch=s' => \$target_arch, 'mock-uniqueext=s' => \$mock_uniqueext, 'result-dir=s' => \$result_dir, 'log-dir=s' => \$log_dir, 'packages=s' => \$packages_csv, + 'epel-gap!' => \$epel_gap, 'jobs=i' => \$jobs, 'skip-install!' => \$skip_install, 'allow-erasing!' => \$allow_erasing, @@ -45,6 +51,12 @@ if (!$mock_cfg) { my $os_id = capture(q{bash -lc 'source /etc/os-release; echo $ID'}); $mock_cfg = resolve_mock_cfg($os_id, $arch); } +# Arch of the rpms --mock-cfg produces: the host arch unless the config is a forcearch (cross) +# one, e.g. rocky-10-riscv64-xcat built on x86_64 (see BUILD.md "riscv64"). The noarch packages +# may be built in a native chroot of the same release instead of the emulated one (their rpms +# are identical for every arch and emulated builds are slow). +$target_arch = $arch if $target_arch eq ''; +$noarch_mock_cfg = $mock_cfg if $noarch_mock_cfg eq ''; my $mock_uniqueext_opt = $mock_uniqueext ne '' ? ' --uniqueext ' . sh_quote($mock_uniqueext) : ''; @@ -63,13 +75,44 @@ $SOURCE_DATE_EPOCH = time() unless $SOURCE_DATE_EPOCH =~ /^\d+$/; $ENV{SOURCE_DATE_EPOCH} = $SOURCE_DATE_EPOCH; if (!$result_dir) { - $result_dir = "$repo_root/build-output/list6/perl/$arch"; + $result_dir = "$repo_root/build-output/list6/perl/$target_arch"; } if (!$log_dir) { - $log_dir = "$repo_root/build-logs/list6/perl/$arch"; + $log_dir = "$repo_root/build-logs/list6/perl/$target_arch"; } my %meta = ( + 'perl-Crypt-Blowfish' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Crypt-Blowfish", + srpm_globs => [ + "$repo_root/perl-Crypt-Blowfish/perl-Crypt-Blowfish-2.14-25.el10_0.src.rpm", + "$repo_root/perl-Crypt-Blowfish/perl-Crypt-Blowfish-*.src.rpm", + ], + rpm_name => 'perl-Crypt-Blowfish', + rpm_arch => 'native', + module => 'Crypt::Blowfish', + needs => ['perl-Crypt-CBC'], # optional tests (BuildRequires) + }, + 'perl-Crypt-CBC' => { + mode => 'spec', + pkg_dir => "$repo_root/perl-Crypt-CBC", + spec => "$repo_root/perl-Crypt-CBC/perl-Crypt-CBC.spec", + rpm_name => 'perl-Crypt-CBC', + rpm_arch => 'noarch', + module => 'Crypt::CBC', + }, + 'perl-Crypt-Rijndael' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Crypt-Rijndael", + srpm_globs => [ + "$repo_root/perl-Crypt-Rijndael/perl-Crypt-Rijndael-1.13-10.fc29.src.rpm", + "$repo_root/perl-Crypt-Rijndael/perl-Crypt-Rijndael-*.src.rpm", + ], + rpm_name => 'perl-Crypt-Rijndael', + rpm_arch => 'native', + module => 'Crypt::Rijndael', + }, 'perl-Crypt-SSLeay' => { mode => 'spec', pkg_dir => "$repo_root/perl-Crypt-SSLeay", @@ -77,6 +120,29 @@ my %meta = ( rpm_name => 'perl-Crypt-SSLeay', rpm_arch => 'native', module => 'Crypt::SSLeay', + needs => ['perl-Path-Class'], # Makefile.PL (configure_requires), EPEL-only on EL + }, + 'perl-Digest-SHA1' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Digest-SHA1", + srpm_globs => [ + "$repo_root/perl-Digest-SHA1/perl-Digest-SHA1-2.13-23.fc28.src.rpm", + "$repo_root/perl-Digest-SHA1/perl-Digest-SHA1-*.src.rpm", + ], + rpm_name => 'perl-Digest-SHA1', + rpm_arch => 'native', + module => 'Digest::SHA1', + }, + 'perl-Expect' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Expect", + srpm_globs => [ + "$repo_root/perl-Expect/perl-Expect-1.35-6.fc29.src.rpm", + "$repo_root/perl-Expect/perl-Expect-*.src.rpm", + ], + rpm_name => 'perl-Expect', + rpm_arch => 'noarch', + module => 'Expect', }, 'perl-HTML-Form' => { mode => 'srpm', @@ -108,6 +174,25 @@ my %meta = ( rpm_arch => 'noarch', module => 'IO::Stty', }, + 'perl-Mail-Sender' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Mail-Sender", + srpm_globs => [ + "$repo_root/perl-Mail-Sender/perl-Mail-Sender-0.903-7.fc29.src.rpm", + "$repo_root/perl-Mail-Sender/perl-Mail-Sender-*.src.rpm", + ], + rpm_name => 'perl-Mail-Sender', + rpm_arch => 'noarch', + module => 'Mail::Sender', + }, + 'perl-Net-DNS' => { + mode => 'spec', + pkg_dir => "$repo_root/perl-Net-DNS", + spec => "$repo_root/perl-Net-DNS/Net-DNS.spec", + rpm_name => 'perl-Net-DNS', + rpm_arch => 'noarch', + module => 'Net::DNS', + }, 'perl-Net-HTTPS-NB' => { mode => 'spec', pkg_dir => "$repo_root/perl-Net-HTTPS-NB", @@ -116,6 +201,17 @@ my %meta = ( rpm_arch => 'noarch', module => 'Net::HTTPS::NB', }, + 'perl-Net-IP' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Net-IP", + srpm_globs => [ + "$repo_root/perl-Net-IP/perl-Net-IP-1.26-30.el10_0.src.rpm", + "$repo_root/perl-Net-IP/perl-Net-IP-*.src.rpm", + ], + rpm_name => 'perl-Net-IP', + rpm_arch => 'noarch', + module => 'Net::IP', + }, 'perl-Net-Telnet' => { mode => 'srpm', pkg_dir => "$repo_root/perl-Net-Telnet", @@ -127,6 +223,28 @@ my %meta = ( rpm_arch => 'noarch', module => 'Net::Telnet', }, + 'perl-Path-Class' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-Path-Class", + srpm_globs => [ + "$repo_root/perl-Path-Class/perl-Path-Class-0.37-24.el10_0.src.rpm", + "$repo_root/perl-Path-Class/perl-Path-Class-*.src.rpm", + ], + rpm_name => 'perl-Path-Class', + rpm_arch => 'noarch', + module => 'Path::Class', + }, + 'perl-SOAP-Lite' => { + mode => 'srpm', + pkg_dir => "$repo_root/perl-SOAP-Lite", + srpm_globs => [ + "$repo_root/perl-SOAP-Lite/perl-SOAP-Lite-1.27-3.fc29.src.rpm", + "$repo_root/perl-SOAP-Lite/perl-SOAP-Lite-*.src.rpm", + ], + rpm_name => 'perl-SOAP-Lite', + rpm_arch => 'noarch', + module => 'SOAP::Lite', + }, 'perl-Sys-Virt' => { mode => 'spec', pkg_dir => "$repo_root/perl-Sys-Virt", @@ -137,6 +255,7 @@ my %meta = ( }, ); +# xcat-dep's own perl deps of xCAT, built for every EL and arch ("list6"). my @default_order = qw( perl-Crypt-SSLeay perl-HTML-Form @@ -147,7 +266,25 @@ my @default_order = qw( perl-Sys-Virt ); +# The perl deps of xCAT that EL takes from EPEL. Built only where there is no EPEL (riscv64, +# --epel-gap); the x86_64/ppc64le repos keep getting them from EPEL. perl-Path-Class is a +# build dep of perl-Crypt-SSLeay only. Not here although in the table: perl-SOAP-Lite (its +# fc29 BuildRequires IO::SessionData, MIME::Lite, XML::Parser::Lite, Test::XML are EPEL-only +# too, so it cannot be built or installed without EPEL; xCAT uses it for HP blades only). +my @epel_gap_order = qw( + perl-Crypt-Blowfish + perl-Crypt-CBC + perl-Crypt-Rijndael + perl-Digest-SHA1 + perl-Expect + perl-Mail-Sender + perl-Net-DNS + perl-Net-IP + perl-Path-Class +); + my @packages = @default_order; +push @packages, @epel_gap_order if $epel_gap; if ($packages_csv ne '') { @packages = grep { $_ ne '' } map { s/^\s+|\s+$//gr } split /,/, $packages_csv; } @@ -178,8 +315,11 @@ print "work_dir: $work_dir\n"; print "result_dir: $result_dir\n"; print "log_dir: $log_dir\n"; print "arch: $arch\n"; +print "target_arch: $target_arch\n"; print "mock_cfg: $mock_cfg\n"; +print "noarch_mock_cfg: $noarch_mock_cfg\n"; print "mock_uniqueext: " . ($mock_uniqueext ne '' ? $mock_uniqueext : '(none)') . "\n"; +print "epel_gap: $epel_gap\n"; print "packages: " . join(', ', @packages) . "\n"; print "jobs: $jobs\n"; print "skip_install:$skip_install\n"; @@ -187,6 +327,8 @@ print "allow_erasing:$allow_erasing\n"; print_step("Mock config check"); run("mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt . " --print-root-path >/dev/null"); +run("mock -r " . sh_quote($noarch_mock_cfg) . $mock_uniqueext_opt . " --print-root-path >/dev/null") + if $noarch_mock_cfg ne $mock_cfg; my @failed; my @passed; @@ -204,28 +346,36 @@ $pm->run_on_finish( } ); -for my $idx (0 .. $#packages) { - my $pkg = $packages[$idx]; - my $cfg = $meta{$pkg}; - my $pkg_uniqueext = package_uniqueext($mock_uniqueext, $idx + 1, $pkg); +# A package that 'needs' others (see %meta) is built after them, with their rpms installed into +# its chroot, so the waves run one after the other; the packages of a wave build in parallel. +my %selected = map { $_ => 1 } @packages; +my $idx = 0; +for my $wave (build_waves(\@packages)) { + for my $pkg (@{$wave}) { + my $cfg = $meta{$pkg}; + my $pkg_uniqueext = package_uniqueext($mock_uniqueext, ++$idx, $pkg); + my @needs = grep { $selected{$_} } @{ $cfg->{needs} // [] }; - my $pid = $pm->start($pkg); - next if $pid; - my $ok = build_package( - pkg => $pkg, - cfg => $cfg, - work_dir => $work_dir, - result_dir => $result_dir, - log_dir => $log_dir, - mock_cfg => $mock_cfg, - mock_uniqueext => $pkg_uniqueext, - arch => $arch, - skip_install => $skip_install, - allow_erasing => $allow_erasing, - ); - $pm->finish($ok ? 0 : 1); + my $pid = $pm->start($pkg); + next if $pid; + my $ok = build_package( + pkg => $pkg, + cfg => $cfg, + work_dir => $work_dir, + result_dir => $result_dir, + log_dir => $log_dir, + mock_cfg => ($cfg->{rpm_arch} eq 'noarch' ? $noarch_mock_cfg : $mock_cfg), + mock_uniqueext => $pkg_uniqueext, + arch => $target_arch, + host_arch => $arch, + needs => \@needs, + skip_install => $skip_install, + allow_erasing => $allow_erasing, + ); + $pm->finish($ok ? 0 : 1); + } + $pm->wait_all_children; } -$pm->wait_all_children; for my $pkg (@packages) { my $status_file = "$log_dir/$pkg/status.txt"; @@ -252,10 +402,12 @@ for my $pkg (@packages) { open my $sfh, '>', "$log_dir/build-summary.txt" or die "Cannot write $log_dir/build-summary.txt: $!\n"; print {$sfh} "mock_cfg=$mock_cfg\n"; +print {$sfh} "noarch_mock_cfg=$noarch_mock_cfg\n" if $noarch_mock_cfg ne $mock_cfg; print {$sfh} "mock_uniqueext=$mock_uniqueext\n" if $mock_uniqueext ne ''; -print {$sfh} "arch=$arch\n"; +print {$sfh} "arch=$target_arch\n"; print {$sfh} "result_dir=$result_dir\n"; print {$sfh} "log_dir=$log_dir\n"; +print {$sfh} "epel_gap=$epel_gap\n"; print {$sfh} "packages=" . join(',', @packages) . "\n"; print {$sfh} "passed=" . join(',', @passed) . "\n"; print {$sfh} "failed=" . join(',', @failed) . "\n"; @@ -280,6 +432,8 @@ sub build_package { my $mock_cfg = $args{mock_cfg}; my $mock_uniqueext = $args{mock_uniqueext}; my $arch = $args{arch}; + my $host_arch = $args{host_arch} // $arch; + my $needs = $args{needs} // []; my $skip_install = $args{skip_install}; my $allow_erasing = $args{allow_erasing}; @@ -304,7 +458,9 @@ sub build_package { my $mock_uniqueext_opt = ' --uniqueext ' . sh_quote($mock_uniqueext); print_step("Build $pkg"); + print "mock_cfg: $mock_cfg\n"; print "mock_uniqueext: $mock_uniqueext\n"; + print "needs: " . (@{$needs} ? join(', ', @{$needs}) : '(none)') . "\n"; my $summary = ''; my $ok = 0; @@ -358,7 +514,7 @@ sub build_package { my $srpm_result = "$pkg_run_dir/srpm"; make_path($srpm_result); - run( + run_mock( "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . " --buildsrpm --spec " . sh_quote($spec) . " --sources " . sh_quote($source_dir) . @@ -373,9 +529,19 @@ sub build_package { $srpm_path = $srpms[-1]; } - run( + # The rpms of the packages this one needs (built in an earlier wave) go into the chroot + # on top of the build requirements the chroot resolves itself. + my $additional_opt = ''; + for my $need (@{$needs}) { + my @need_rpms = grep { !/\.src\.rpm$/ && !/-debug(?:info|source)-/ } + sort glob("$result_dir/$need/*.rpm"); + die "Needed package $need left no rpms in $result_dir/$need (build failed?)\n" if !@need_rpms; + $additional_opt .= " --additional-package " . sh_quote($_) for @need_rpms; + } + + run_mock( "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . - " --rebuild " . sh_quote($srpm_path) . + " --rebuild " . sh_quote($srpm_path) . $additional_opt . " --define " . sh_quote("use_source_date_epoch_as_buildtime 1") . " --define " . sh_quote("clamp_mtime_to_source_date_epoch 1") . " --define " . sh_quote("_buildhost xcat-build") . @@ -425,7 +591,22 @@ sub build_package { } } - if (!$skip_install) { + if (!$skip_install && $cfg->{rpm_arch} eq 'native' && $arch ne $host_arch) { + # A cross-built XS module cannot be loaded on this host: install the rpm into the + # (emulated) build chroot and import the module there. + my $module = $cfg->{module}; + run_mock( + "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . + " --install " . sh_quote($main_rpm) . + " > " . sh_quote("$pkg_log/smoke-chroot-install.log") . " 2>&1" + ); + my $rc_mod = run_capture_rc( + "mock -r " . sh_quote($det_mock_cfg) . $mock_uniqueext_opt . + " -q --chroot -- perl -M$module -e 1", + "$pkg_log/smoke-perl-module.log"); + die "Perl module import failed for $pkg ($module) in the $arch chroot, rc=$rc_mod\n" if $rc_mod != 0; + } + elsif (!$skip_install) { my $install_cmd = "dnf -y install "; $install_cmd .= "--allowerasing " if $allow_erasing; run($install_cmd . sh_quote($main_rpm)); @@ -455,6 +636,28 @@ sub build_package { return $ok; } +# Order the selected packages in waves: a package comes after the selected packages it 'needs' +# (installed into its chroot, see %meta). Needs outside the selection are ignored: the chroot +# then has to provide the module itself (e.g. from EPEL). +sub build_waves { + my ($pkgs) = @_; + my %selected = map { $_ => 1 } @{$pkgs}; + my %done; + my @waves; + my @left = @{$pkgs}; + while (@left) { + my @ready = grep { + my $p = $_; + !grep { $selected{$_} && !$done{$_} } @{ $meta{$p}{needs} // [] }; + } @left; + die "Circular 'needs' among packages: @left\n" if !@ready; + push @waves, \@ready; + $done{$_} = 1 for @ready; + @left = grep { !$done{$_} } @left; + } + return @waves; +} + sub package_uniqueext { my ($base, $index, $pkg) = @_; my $tag = lc $pkg; @@ -472,11 +675,18 @@ sub usage { Usage: $0 [options] --work-dir PATH Temporary work dir (default: $work_dir) --mock-cfg NAME Mock config (default: +epel-10-) + --noarch-mock-cfg NAME Mock config for the noarch packages (default: --mock-cfg); with a + forcearch --mock-cfg, a native config of the same release builds them + without emulation + --target-arch ARCH Arch of the rpms --mock-cfg produces (default: uname -m); a forcearch + config such as rocky-10-riscv64-xcat needs it --mock-uniqueext TXT Optional mock --uniqueext suffix to isolate concurrent builds --jobs N Number of parallel package workers (default: selected package count) --result-dir PATH Output directory (default: build-output/list6/perl/) --log-dir PATH Log directory (default: build-logs/list6/perl/) --packages LIST Comma-separated subset of packages to build + --epel-gap Also build the perl deps of xCAT that EL takes from EPEL (for an arch + without EPEL, e.g. riscv64) --build-timestamp EPOCH Unix epoch for SOURCE_DATE_EPOCH (deterministic builds) --skip-install Skip dnf install + perl module import checks --allow-erasing Allow dnf to erase conflicting packages during install smoke tests @@ -574,6 +784,22 @@ sub capture { return $out; } +# mock exits 30 when its package manager failed (chroot init, build deps), which against public +# mirrors is most often a transient download error (stale mirror metadata): retry such a run once. +sub run_mock { + my ($cmd) = @_; + print "+ $cmd\n"; + my $rc = system($cmd); + if ($rc != -1 && ($rc >> 8) == 30) { + print "mock failed with rc=30 (package manager); retrying once\n"; + $rc = system($cmd); + } + if ($rc != 0) { + my $exit = $rc == -1 ? 255 : ($rc >> 8); + die "Command failed (rc=$exit): $cmd\n"; + } +} + sub run_capture_rc { my ($cmd, $log_file) = @_; my $full = "$cmd > " . sh_quote($log_file) . " 2>&1"; diff --git a/perl-Crypt-Blowfish/Build-notes b/perl-Crypt-Blowfish/Build-notes index dbecba8..7167871 100644 --- a/perl-Crypt-Blowfish/Build-notes +++ b/perl-Crypt-Blowfish/Build-notes @@ -2,3 +2,7 @@ 1. Copy Crypt-Blowfish-2.14.tar.gz to /usr/src/packages/SOURCES/. 2. Copy perl-Crypt-Blowfish.spec to /usr/src/packages/SPECS/ 3. Run "rpmbuild -ba /usr/src/packages/SPECS/perl-Crypt-Blowfish.spec" which creates /usr/src/packages/RPMS/x86_64/perl-Crypt-Blowfish-2.14-5.1.x86_64.rpm + +perl-Crypt-Blowfish.spec above is a SUSE spec (perl-macros). For RHEL 10 (EPEL-only there), run +"rpmbuild --rebuild perl-Crypt-Blowfish-2.14-25.el10_0.src.rpm" (the EPEL 10 source rpm); its +optional tests need perl(Crypt::CBC) at build time. diff --git a/perl-Crypt-Blowfish/perl-Crypt-Blowfish-2.14-25.el10_0.src.rpm b/perl-Crypt-Blowfish/perl-Crypt-Blowfish-2.14-25.el10_0.src.rpm new file mode 100644 index 0000000..3d5bb24 Binary files /dev/null and b/perl-Crypt-Blowfish/perl-Crypt-Blowfish-2.14-25.el10_0.src.rpm differ diff --git a/perl-Crypt-CBC/Build-notes b/perl-Crypt-CBC/Build-notes index 765218e..43108a5 100644 --- a/perl-Crypt-CBC/Build-notes +++ b/perl-Crypt-CBC/Build-notes @@ -5,3 +5,8 @@ 3. Run "rpmbuild -ba /usr/src/packages/SPECS/perl-Crypt-CBC.spec" which creates /usr/src/packages/RPMS/noarch/perl-Crypt-CBC-2.33-3.7.noarch.rpm For RHEL 8, run "rpmbuild --rebuild perl-Crypt-CBC-2.33-20.fc29.src.rpm". + +perl-Crypt-CBC.spec is now the Fedora spec of perl-Crypt-CBC-2.33-20.fc29.src.rpm with the +BuildRequires an EL10 buildroot needs (make, perl-interpreter); the SUSE spec it replaces is in +the git history. For RHEL 10 (EPEL-only there), run "rpmbuild -ba perl-Crypt-CBC.spec" with +Crypt-CBC-2.33.tar.gz in SOURCES. diff --git a/perl-Crypt-CBC/perl-Crypt-CBC.spec b/perl-Crypt-CBC/perl-Crypt-CBC.spec index 260cf56..5e962ec 100644 --- a/perl-Crypt-CBC/perl-Crypt-CBC.spec +++ b/perl-Crypt-CBC/perl-Crypt-CBC.spec @@ -1,172 +1,212 @@ -# -# spec file for package perl-Crypt-CBC -# -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. -# -# All modifications and additions to the file contributed by third parties -# remain the property of their copyright owners, unless otherwise agreed -# upon. The license for this file, and modifications and additions to the -# file, is the same license as for the pristine package itself (unless the -# license for the pristine package is not an Open Source License, in which -# case the license is the MIT License). An "Open Source License" is a -# license that conforms to the Open Source Definition (Version 1.9) -# published by the Open Source Initiative. - -# Please submit bugfixes or comments via http://bugs.opensuse.org/ -# - - -Name: perl-Crypt-CBC -Version: 2.33 -Release: 5.26 -%define cpan_name Crypt-CBC -Summary: Encrypt Data with Cipher Block Chaining Mode -License: GPL-1.0+ or Artistic-1.0 -Group: Development/Libraries/Perl -Url: http://search.cpan.org/dist/Crypt-CBC/ -Source: http://www.cpan.org/authors/id/L/LD/LDS/%{cpan_name}-%{version}.tar.gz -BuildArch: noarch -BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: perl -BuildRequires: perl-macros -#BuildRequires: perl(Crypt::CBC) -#BuildRequires: perl(Crypt::IDEA) -%{perl_requires} +Summary: Encrypt Data with Cipher Block Chaining Mode +Name: perl-Crypt-CBC +Version: 2.33 +Release: 21%{?dist} +# Upstream confirms that they're under the same license as perl. +# Wording in CBC.pm is less than clear, but still. +License: GPL+ or Artistic +Group: Development/Libraries +URL: https://metacpan.org/release/Crypt-CBC +Source0: https://cpan.metacpan.org/authors/id/L/LD/LDS/Crypt-CBC-%{version}.tar.gz +BuildArch: noarch +Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) +# EL >= 8 buildroots have neither perl nor make by default +BuildRequires: make +BuildRequires: perl-interpreter +BuildRequires: perl-generators +BuildRequires: perl(bytes) +BuildRequires: perl(constant) +BuildRequires: perl(Digest::MD5) >= 2.00 +BuildRequires: perl(ExtUtils::MakeMaker) +# Modules used for test suite, skipped when bootstrapping as +# some of these modules use Crypt::CBC themselves +# Crypt::CAST5 not yet packaged in Fedora +# Crypt::IDEA is unavailable due to patents +%if 0%{!?perl_bootstrap:1} +BuildRequires: perl(Crypt::DES) +%if ! (0%{?rhel} >= 7) +BuildRequires: perl(Crypt::Blowfish) +BuildRequires: perl(Crypt::Blowfish_PP) +BuildRequires: perl(Crypt::Rijndael) +%endif +%endif %description -This module is a Perl-only implementation of the cryptographic cipher block -chaining mode (CBC). In combination with a block cipher such as DES or -IDEA, you can encrypt and decrypt messages of arbitrarily long length. The -encrypted messages are compatible with the encryption format used by the -*OpenSSL* package. - -To use this module, you will first create a Crypt::CBC cipher object with -new(). At the time of cipher creation, you specify an encryption key to use -and, optionally, a block encryption algorithm. You will then call the -start() method to initialize the encryption or decryption process, crypt() -to encrypt or decrypt one or more blocks of data, and lastly finish(), to -pad and encrypt the final block. For your convenience, you can call the -encrypt() and decrypt() methods to operate on a whole data value at once. +This is Crypt::CBC, a Perl-only implementation of the cryptographic +cipher block chaining mode (CBC). In combination with a block cipher +such as Crypt::DES or Crypt::IDEA, you can encrypt and decrypt +messages of arbitrarily long length. The encrypted messages are +compatible with the encryption format used by SSLeay. %prep -%setup -q -n %{cpan_name}-%{version} +%setup -q -n Crypt-CBC-%{version} +chmod 644 eg/*.pl %build %{__perl} Makefile.PL INSTALLDIRS=vendor -%{__make} %{?_smp_mflags} - -%check -%{__make} test +make %install -%perl_make_install -%perl_process_packlist -%perl_gen_filelist +rm -rf $RPM_BUILD_ROOT +make pure_install DESTDIR=$RPM_BUILD_ROOT +find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';' +%{_fixperms} $RPM_BUILD_ROOT -%files -f %{name}.files -%defattr(-,root,root,755) -%doc Changes Crypt-CBC-2.16-vulnerability.txt README +%check +make test + +%files +%doc Changes README eg/ +%{perl_vendorlib}/Crypt/ +%{_mandir}/man3/*.3* %changelog -* Tue Aug 6 2013 coolo@suse.com -- updated to 2.33 - - Fix minor RT bugs 83175 and 86455. -* Mon Jun 3 2013 coolo@suse.com -- updated to 2.32 - - Fixes "Taint checks are turned on and your key is tainted" error when autogenerating salt and IV. - - Fixes to regular expressions to avoid rare failures to - correctly strip padding in decoded messages. - - Add padding type = "none". - - Both fixes contributed by Bas van Sisseren. -* Fri Nov 18 2011 coolo@suse.com -- use original .tar.gz -* Fri Aug 26 2011 chris@computersalat.de -- remove Author from desc -- added bcond_with opt - o test optional pkgs via local build (osc build --with opt) -- fix deps for CentOS -- some spec cleanup -* Wed Dec 8 2010 coolo@novell.com -- avoid even more requires to avoid even more cycles -* Tue Nov 30 2010 coolo@novell.com -- remove extra requires to avoid cycle -* Wed Nov 24 2010 chris@computersalat.de -- recreated by cpanspec 1.78 - o fix deps -- noarch pkg -* Sun Jan 10 2010 jengelh@medozas.de -- enable parallel build -* Fri Feb 27 2009 anicka@suse.cz -- update to 2.30 - * setting $cipher correctly -* Thu Jun 19 2008 anicka@suse.cz +* Thu Aug 20 2026 xCAT build - 2.33-21 +- Fedora spec from perl-Crypt-CBC-2.33-20.fc29.src.rpm, with BuildRequires make + and perl-interpreter so it builds in an EL10 buildroot + +* Fri Jul 13 2018 Fedora Release Engineering - 2.33-20 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Sat Jun 30 2018 Jitka Plesnikova - 2.33-19 +- Perl 5.28 re-rebuild of bootstrapped packages + +* Wed Jun 27 2018 Jitka Plesnikova - 2.33-18 +- Perl 5.28 rebuild + +* Thu Feb 08 2018 Fedora Release Engineering - 2.33-17 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 2.33-16 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jun 07 2017 Jitka Plesnikova - 2.33-15 +- Perl 5.26 re-rebuild of bootstrapped packages + +* Sun Jun 04 2017 Jitka Plesnikova - 2.33-14 +- Perl 5.26 rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 2.33-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed May 18 2016 Jitka Plesnikova - 2.33-12 +- Perl 5.24 re-rebuild of bootstrapped packages + +* Sun May 15 2016 Jitka Plesnikova - 2.33-11 +- Perl 5.24 rebuild + +* Thu Feb 04 2016 Fedora Release Engineering - 2.33-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jun 18 2015 Fedora Release Engineering - 2.33-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed Jun 10 2015 Jitka Plesnikova - 2.33-8 +- Perl 5.22 re-rebuild of bootstrapped packages + +* Wed Jun 03 2015 Jitka Plesnikova - 2.33-7 +- Perl 5.22 rebuild + +* Sun Sep 07 2014 Jitka Plesnikova - 2.33-6 +- Perl 5.20 re-rebuild of bootstrapped packages + +* Wed Aug 27 2014 Jitka Plesnikova - 2.33-5 +- Perl 5.20 rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 2.33-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Wed Aug 14 2013 Jitka Plesnikova - 2.33-3 +- Perl 5.18 re-rebuild of bootstrapped packages + +* Sat Aug 03 2013 Fedora Release Engineering - 2.33-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Tue Jul 30 2013 Paul Howarth - 2.33-1 +- Update to 2.33 + - Fixes to regular expressions to avoid rare failures to correctly strip + padding in decoded messages + - Add padding type = "none" + - Fix "Taint checks are turned on and your key is tainted" error when + autogenerating salt and IV + - Fix minor bugs CPAN RT#83175 and CPAN RT#86455 +- Don't need to remove empty directories from the buildroot +- Drop %%defattr, redundant since rpm 4.4 +- Use %%{_fixperms} macro rather than our own chmod incantation +- Use DESTDIR rather than PERL_INSTALL_ROOT + +* Thu Jul 18 2013 Petr Pisar - 2.29-16 +- Perl 5.18 rebuild + +* Thu Feb 14 2013 Fedora Release Engineering - 2.29-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Jul 20 2012 Fedora Release Engineering - 2.29-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 10 2012 Petr Pisar - 2.29-13 +- Perl 5.16 re-rebuild of bootstrapped packages + +* Mon Jun 11 2012 Petr Pisar - 2.29-12 +- Perl 5.16 rebuild + +* Mon Jun 11 2012 Marcela Mašláňová - 2.29-11 +- Do not build-require Crypt::Blowfish, Crypt::Blowfish_PP, and Crypt::Rijndael + on RHEL >= 7 +- Resolves: rhbz#822812 + +* Sat Apr 21 2012 Paul Howarth - 2.29-10 +- BR: perl(bytes), perl(constant), perl(Digest::MD5) - required by module +- BR: perl(Crypt::Blowfish), perl(Crypt::Blowfish_PP), perl(Crypt::DES), + perl(Crypt::Rijndael) for improved test coverage, except when bootstrapping + +* Fri Jan 13 2012 Fedora Release Engineering - 2.29-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Fri Jun 17 2011 Marcela Mašláňová - 2.29-8 +- Perl mass rebuild + +* Tue Feb 08 2011 Fedora Release Engineering - 2.29-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Dec 15 2010 Marcela Maslanova - 2.29-6 +- Rebuild to fix problems with vendorarch/lib (#661697) + +* Fri Apr 30 2010 Marcela Maslanova - 2.29-5 +- Mass rebuild with perl-5.12.0 + +* Fri Dec 4 2009 Stepan Kasal - 2.29-4 +- rebuild against perl 5.10.1 + +* Sat Jul 25 2009 Fedora Release Engineering - 2.29-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Feb 26 2009 Fedora Release Engineering - 2.29-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Jul 11 2008 Tom "spot" Callawau - 2.29-1 - update to 2.29 - * Fixed errors that occurred when encrypting/decrypting utf8 - strings in Perl's more recent than 5.8.8. -* Wed Apr 2 2008 anicka@suse.cz -- update to 2.28 - - Fixed bug in onesandzeroes test that causes it to fail - with Rijndael module is not installed. - - When taint mode is turned on and user is using a tainted key, - explicitly check tainting of key in order to avoid "cryptic" - failure messages from some crypt modules. - - Fixed onezeropadding test, which was not reporting - its test count properly. - - Fixed failure of oneandzeroes padding when plaintext size is - an even multiple of blocksize. - - Added new "rijndael_compat" padding method, which is compatible - with the oneandzeroes padding method used by Crypt::Rijndael in - CBC mode. -* Mon Oct 8 2007 anicka@suse.cz -- update to 2.24 - * Fixed failure to run under taint checks with Crypt::Rijndael - or Crypt::OpenSSL::AES (and maybe other Crypt modules). - * Added checks for other implementations of CBC which add no - standard padding at all when cipher text is an even multiple - of the block size. -* Tue Dec 12 2006 anicka@suse.cz -- update to 2.22 - * Fixed bug in which plaintext encrypted with the - - literal_key option could not be decrypted using a new - object created with the same -literal_key. - * Added documentation confirming that -literal_key must be - accompanied by a -header of 'none' and a manually specificied IV. -* Thu Oct 19 2006 anicka@suse.cz -- update to 2.21 - * Fixed bug in which new() failed to work when first option is - - literal_key. - * Added ability to pass a preinitialized Crypt::* block cipher - object instead of the class name. -* Thu Sep 14 2006 anicka@suse.cz -- update to 2.19 - * Renamed Crypt::CBC-2.16-vulnerability.txt so that - package installs correctly under Cygwin -* Fri Jul 14 2006 anicka@suse.cz -- update to 2.18 - * added lots of documentation - * fixed using 8 byte IVs when generating the old-style RandomIV - style header for the Rijndael algorithm. - * versions 2.17 and higher will not decrypt messages - encrypted with versions 2.16 and lower unless you pass - an optional value 'randomiv' to the new() call -* Wed Apr 5 2006 schubi@suse.de -- Bug 153627 - VUL-0: perl-Crypt-CBC: ciphertext weakness when using certain block algorithms -* Wed Jan 25 2006 mls@suse.de -- converted neededforbuild to BuildRequires -* Mon Jul 11 2005 schubi@suse.de -- update to 2.14 -* Fri Apr 15 2005 schubi@suse.de -- update to 2.12 -* Sun Jan 11 2004 adrian@suse.de -- build as user -* Fri Aug 22 2003 mjancar@suse.cz -- require the perl version we build with -* Fri Jul 18 2003 choeger@suse.de -- use install_vendor and new %%perl_process_packlist macro -* Tue Jun 17 2003 choeger@suse.de -- updated filelist -- update to version 2.08 -* Mon May 19 2003 choeger#@suse.de -- remove installed (but unpackaged) file perllocal.pod -* Wed Aug 14 2002 choeger@suse.de -- new package, version 2.07 + +* Mon Mar 3 2008 Tom "spot" Callaway - 2.22-3 +- work around buildsystem burp + +* Fri Feb 8 2008 Tom "spot" Callaway - 2.22-2 +- rebuild for new perl + +* Mon Oct 15 2007 Tom "spot" Callaway - 2.22-1.1 +- add BR: perl(ExtUtils::MakeMaker) + +* Wed Feb 07 2007 Andreas Thienemann - 2.22-1 +- Upgrade to 2.22 + +* Fri Sep 08 2006 Andreas Thienemann - 2.19-1 +- Upgrade to 2.19 + +* Fri Feb 24 2006 Andreas Thienemann - 2.17-1 +- Upgrade to 2.17 + +* Thu Jul 14 2005 Andreas Thienemann - 2.14-2 +- Remove execute permissions from example files + +* Thu Jul 14 2005 Andreas Thienemann - 2.14-1 +- Initial package diff --git a/perl-Net-DNS/Net-DNS.spec b/perl-Net-DNS/Net-DNS.spec index 68864ba..56d184e 100644 --- a/perl-Net-DNS/Net-DNS.spec +++ b/perl-Net-DNS/Net-DNS.spec @@ -14,17 +14,29 @@ name: perl-Net-DNS summary: Net-DNS - Perl DNS resolver module version: 0.80 -release: 1 +release: 2 vendor: Olaf Kolkman packager: Arix International license: Artistic group: Applications/CPAN url: http://www.cpan.org buildroot: %{_tmppath}/%{name}-%{version}-%(id -u -n) -buildarch: x86_64 +buildarch: noarch prefix: %(echo %{_prefix}) source: Net-DNS-0.80.tar.gz +# cpan2rpm specs carry no BuildRequires; an EL10 buildroot has neither perl nor make, and +# perl-generators is what makes rpm compute the perl(...) Requires. +BuildRequires: make +BuildRequires: perl-interpreter +BuildRequires: perl-generators +BuildRequires: perl(ExtUtils::MakeMaker) +BuildRequires: perl(Digest::HMAC) +BuildRequires: perl(Digest::MD5) +BuildRequires: perl(Digest::SHA) +BuildRequires: perl(MIME::Base64) +BuildRequires: perl(Test::More) + %description Net::DNS is a collection of Perl modules that act as a Domain Name System (DNS) resolver. It allows the programmer to perform DNS queries that are @@ -49,7 +61,8 @@ grep -rsl '^#!.*perl' . | grep -v '.bak$' |xargs --no-run-if-empty \ %__perl -MExtUtils::MakeMaker -e 'MY->fixin(@ARGV)' CFLAGS="$RPM_OPT_FLAGS" -%{__perl} Makefile.PL `%{__perl} -MExtUtils::MakeMaker -e ' print qq|PREFIX=%{buildroot}%{_prefix}| if \$ExtUtils::MakeMaker::VERSION =~ /5\.9[1-6]|6\.0[0-5]/ '` +# --noxs: pure-perl Net::DNS (no compiled dn_expand), so one noarch rpm serves every arch +%{__perl} Makefile.PL --noxs `%{__perl} -MExtUtils::MakeMaker -e ' print qq|PREFIX=%{buildroot}%{_prefix}| if \$ExtUtils::MakeMaker::VERSION =~ /5\.9[1-6]|6\.0[0-5]/ '` %{__make} %if %maketest %{__make} test @@ -126,5 +139,10 @@ find %{buildroot}%{_prefix} \ %defattr(-,root,root) %changelog +* Thu Aug 20 2026 xCAT build - 0.80-2 +- Build the pure-perl module (--noxs) as noarch instead of an XS x86_64 rpm. +- BuildRequires for an EL10 buildroot (make, perl-interpreter, perl-generators, + MakeMaker, Digest::HMAC/MD5/SHA, MIME::Base64, Test::More). + * Tue Oct 28 2014 root@slesmn - Initial build. \ No newline at end of file diff --git a/perl-Net-IP/Build-notes b/perl-Net-IP/Build-notes new file mode 100644 index 0000000..cfd50ad --- /dev/null +++ b/perl-Net-IP/Build-notes @@ -0,0 +1,4 @@ +perl-Net-IP (Net::IP, used by xCAT::NetworkUtils) is EPEL-only on EL10. The source rpm is +the EPEL 10 one (Fedora spec, Net-IP 1.26, noarch). + +For RHEL 10, run "rpmbuild --rebuild perl-Net-IP-1.26-30.el10_0.src.rpm". diff --git a/perl-Net-IP/perl-Net-IP-1.26-30.el10_0.src.rpm b/perl-Net-IP/perl-Net-IP-1.26-30.el10_0.src.rpm new file mode 100644 index 0000000..169753e Binary files /dev/null and b/perl-Net-IP/perl-Net-IP-1.26-30.el10_0.src.rpm differ diff --git a/perl-Path-Class/Build-notes b/perl-Path-Class/Build-notes new file mode 100644 index 0000000..7210eb7 --- /dev/null +++ b/perl-Path-Class/Build-notes @@ -0,0 +1,6 @@ +perl-Path-Class (Path::Class) is only a build dependency: Crypt-SSLeay's Makefile.PL uses it +(configure_requires), and EL10 has it in EPEL only. The source rpm is the EPEL 10 one (Fedora +spec, Path-Class 0.37, noarch). mockbuild-perl-packages.pl builds it where there is no EPEL +(--epel-gap) and installs it into the perl-Crypt-SSLeay build chroot. + +For RHEL 10, run "rpmbuild --rebuild perl-Path-Class-0.37-24.el10_0.src.rpm". diff --git a/perl-Path-Class/perl-Path-Class-0.37-24.el10_0.src.rpm b/perl-Path-Class/perl-Path-Class-0.37-24.el10_0.src.rpm new file mode 100644 index 0000000..f674071 Binary files /dev/null and b/perl-Path-Class/perl-Path-Class-0.37-24.el10_0.src.rpm differ