Xlibre build script updated.
This commit is contained in:
Executable
+325
@@ -0,0 +1,325 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repoUrl="https://github.com/X11Libre/pkgbuilds-arch-based.git"
|
||||
rootfsUrl="http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz"
|
||||
|
||||
aarch64Packages=(
|
||||
xlibre-xserver
|
||||
xlibre-input-libinput
|
||||
xlibre-video-fbdev
|
||||
xlibre-video-amdgpu
|
||||
xlibre-video-ati
|
||||
xlibre-video-nouveau
|
||||
)
|
||||
|
||||
outputDir=$(pwd -P)
|
||||
workDir=""
|
||||
chrootDir=""
|
||||
binfmtMounted=false
|
||||
binfmtRegistered=false
|
||||
|
||||
log() {
|
||||
printf '%s %s\n' "$*" "$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
}
|
||||
|
||||
die() {
|
||||
printf 'Error: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
local exitStatus=$?
|
||||
local cleanupFailed=false
|
||||
local mountTarget
|
||||
local chrootMounts=()
|
||||
|
||||
trap - EXIT INT TERM
|
||||
|
||||
if [[ -n "$workDir" && -d "$workDir" ]]; then
|
||||
log "Removing temporary chroot"
|
||||
if [[ -n "$chrootDir" ]]; then
|
||||
mapfile -t chrootMounts < <(
|
||||
findmnt -rn -o TARGET |
|
||||
awk -v root="$chrootDir" '$0 == root || index($0, root "/") == 1' |
|
||||
sort -r
|
||||
)
|
||||
fi
|
||||
for mountTarget in "${chrootMounts[@]}"; do
|
||||
if ! mountpoint -q "$mountTarget"; then
|
||||
continue
|
||||
fi
|
||||
if ! umount --recursive "$mountTarget"; then
|
||||
printf 'Warning: normal chroot unmount failed; detaching it lazily\n' >&2
|
||||
umount --recursive --lazy "$mountTarget" || cleanupFailed=true
|
||||
fi
|
||||
done
|
||||
rm -rf --one-file-system "$workDir" || cleanupFailed=true
|
||||
if [[ -e "$workDir" ]]; then
|
||||
printf 'Error: failed to remove temporary chroot: %s\n' "$workDir" >&2
|
||||
cleanupFailed=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$binfmtRegistered" == true && -e /proc/sys/fs/binfmt_misc/qemu-aarch64 ]]; then
|
||||
printf '%s' -1 > /proc/sys/fs/binfmt_misc/qemu-aarch64 || cleanupFailed=true
|
||||
fi
|
||||
|
||||
if [[ "$binfmtMounted" == true ]]; then
|
||||
umount /proc/sys/fs/binfmt_misc || cleanupFailed=true
|
||||
fi
|
||||
|
||||
if [[ "$cleanupFailed" == true && "$exitStatus" -eq 0 ]]; then
|
||||
exitStatus=1
|
||||
fi
|
||||
|
||||
exit "$exitStatus"
|
||||
}
|
||||
|
||||
require_commands() {
|
||||
local commandName
|
||||
local missingCommands=()
|
||||
|
||||
for commandName in arch-chroot awk bsdtar chown cp curl date findmnt grep install mkdir mktemp mount mountpoint rm sort tr umount; do
|
||||
if ! command -v "$commandName" >/dev/null 2>&1; then
|
||||
missingCommands+=("$commandName")
|
||||
fi
|
||||
done
|
||||
|
||||
if ((${#missingCommands[@]})); then
|
||||
die "Missing required commands: ${missingCommands[*]}"
|
||||
fi
|
||||
|
||||
[[ -x /usr/bin/qemu-aarch64-static ]] || die "/usr/bin/qemu-aarch64-static is required"
|
||||
[[ -r /usr/lib/binfmt.d/qemu-aarch64-static.conf ]] || die "The qemu-user-static-binfmt package is required"
|
||||
}
|
||||
|
||||
configure_binfmt() {
|
||||
if ! mountpoint -q /proc/sys/fs/binfmt_misc; then
|
||||
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
|
||||
binfmtMounted=true
|
||||
fi
|
||||
|
||||
if [[ ! -e /proc/sys/fs/binfmt_misc/qemu-aarch64 ]]; then
|
||||
tr -d '\n' < /usr/lib/binfmt.d/qemu-aarch64-static.conf > /proc/sys/fs/binfmt_misc/register
|
||||
binfmtRegistered=true
|
||||
fi
|
||||
|
||||
grep -qx 'enabled' /proc/sys/fs/binfmt_misc/qemu-aarch64 || die "aarch64 binfmt registration is not enabled"
|
||||
}
|
||||
|
||||
create_build_script() {
|
||||
local buildScript=$1
|
||||
|
||||
install -m 0755 /dev/stdin "$buildScript" <<'CHROOT_SCRIPT'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repoUrl=$1
|
||||
shift
|
||||
packages=("$@")
|
||||
repoDir=/build/pkgbuilds
|
||||
|
||||
log() {
|
||||
printf '%s %s\n' "$*" "$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
local packageDir=$1
|
||||
local dependency
|
||||
local outputPackage
|
||||
local srcInfo
|
||||
local dependencies=()
|
||||
local filteredDependencies=()
|
||||
local missingDependencies=()
|
||||
local outputPackages=()
|
||||
local -A internalPackages=()
|
||||
|
||||
# $1 is expanded by the nested builder shell, not this root shell.
|
||||
# shellcheck disable=SC2016
|
||||
srcInfo=$(runuser -u builder -- bash -c \
|
||||
'cd "$1" && makepkg --printsrcinfo' _ "$packageDir")
|
||||
|
||||
mapfile -t outputPackages < <(
|
||||
printf '%s\n' "$srcInfo" |
|
||||
awk -F ' = ' '/^[[:space:]]*pkgname = / { print $2 }'
|
||||
)
|
||||
for outputPackage in "${outputPackages[@]}"; do
|
||||
internalPackages["$outputPackage"]=1
|
||||
done
|
||||
|
||||
mapfile -t dependencies < <(
|
||||
printf '%s\n' "$srcInfo" |
|
||||
awk -F ' = ' '
|
||||
/^[[:space:]]*(depends|makedepends|checkdepends)(_aarch64)? = / {
|
||||
dependency=$2
|
||||
sub(/[<>=].*/, "", dependency)
|
||||
print dependency
|
||||
}
|
||||
' |
|
||||
sort -u
|
||||
)
|
||||
for dependency in "${dependencies[@]}"; do
|
||||
if [[ -z ${internalPackages[$dependency]+present} ]]; then
|
||||
filteredDependencies+=("$dependency")
|
||||
fi
|
||||
done
|
||||
((${#filteredDependencies[@]})) || return 0
|
||||
|
||||
mapfile -t missingDependencies < <(pacman -T "${filteredDependencies[@]}" || true)
|
||||
((${#missingDependencies[@]})) || return 0
|
||||
|
||||
log "Installing dependencies for ${packageDir##*/}"
|
||||
pacman -S --asdeps --needed --noconfirm "${missingDependencies[@]}"
|
||||
}
|
||||
|
||||
remove_installed_packages() {
|
||||
local packageName
|
||||
local installedPackages=()
|
||||
|
||||
for packageName in "$@"; do
|
||||
if pacman -Q "$packageName" >/dev/null 2>&1; then
|
||||
installedPackages+=("$packageName")
|
||||
fi
|
||||
done
|
||||
((${#installedPackages[@]})) || return 0
|
||||
|
||||
log "Removing conflicting packages: ${installedPackages[*]}"
|
||||
pacman -Rdd --noconfirm "${installedPackages[@]}"
|
||||
}
|
||||
|
||||
build_package() {
|
||||
local packageName=$1
|
||||
local installAfterBuild=${2:-false}
|
||||
local packageDir="$repoDir/$packageName"
|
||||
local builtPackages=()
|
||||
|
||||
[[ -f "$packageDir/PKGBUILD" ]] || {
|
||||
printf 'Missing PKGBUILD for %s\n' "$packageName" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
log "Building $packageName"
|
||||
install_dependencies "$packageDir"
|
||||
# $1 is expanded by the nested builder shell, not this root shell.
|
||||
# shellcheck disable=SC2016
|
||||
runuser -u builder -- bash -c \
|
||||
'cd "$1" && makepkg --noconfirm --clean --cleanbuild' _ "$packageDir"
|
||||
|
||||
mapfile -d '' builtPackages < <(
|
||||
find "$packageDir" -maxdepth 1 -type f -name '*.pkg.tar.*' ! -name '*.sig' -print0
|
||||
)
|
||||
((${#builtPackages[@]})) || {
|
||||
printf 'No package artifacts were produced for %s\n' "$packageName" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
if [[ "$installAfterBuild" == true ]]; then
|
||||
case "$packageName" in
|
||||
xlibre-input-libinput)
|
||||
remove_installed_packages xf86-input-libinput
|
||||
;;
|
||||
xlibre-xserver)
|
||||
remove_installed_packages \
|
||||
xorg-server \
|
||||
xorg-server-common \
|
||||
xorg-server-devel \
|
||||
xorg-server-xephyr \
|
||||
xorg-server-xnest \
|
||||
xorg-server-xvfb \
|
||||
glamor-egl \
|
||||
xf86-video-modesetting
|
||||
;;
|
||||
esac
|
||||
log "Installing $packageName for subsequent builds"
|
||||
pacman -U --noconfirm "${builtPackages[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
log "Initializing Arch Linux ARM"
|
||||
# Pacman's Landlock sandbox is unavailable through qemu-user emulation.
|
||||
sed -i \
|
||||
-e '/^[[:space:]]*DisableSandbox[[:space:]]*$/d' \
|
||||
-e '/^\[options\][[:space:]]*$/a DisableSandbox' \
|
||||
/etc/pacman.conf
|
||||
pacman-key --init
|
||||
pacman-key --populate archlinuxarm
|
||||
pacman -Syu --noconfirm
|
||||
pacman -S --needed --noconfirm base-devel git
|
||||
|
||||
useradd --create-home --shell /bin/bash builder
|
||||
install -d -o builder -g builder /build
|
||||
|
||||
log "Cloning XLibre PKGBUILDs"
|
||||
runuser -u builder -- git clone --depth 1 "$repoUrl" "$repoDir"
|
||||
|
||||
# The input driver must first be built against the stock xorg-server-devel.
|
||||
build_package xlibre-input-libinput true
|
||||
|
||||
# Installing all server split packages replaces the stock Xorg server/devel
|
||||
# packages and provides the ABI dependencies needed by the video drivers.
|
||||
build_package xlibre-xserver true
|
||||
|
||||
for packageName in "${packages[@]}"; do
|
||||
case "$packageName" in
|
||||
xlibre-input-libinput|xlibre-xserver)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
build_package "$packageName"
|
||||
done
|
||||
|
||||
install -d /output
|
||||
find "$repoDir" -type f -name '*.pkg.tar.*' ! -name '*.sig' -exec cp -t /output -- {} +
|
||||
log "All requested aarch64 packages built"
|
||||
CHROOT_SCRIPT
|
||||
}
|
||||
|
||||
main() {
|
||||
local rootfsArchive
|
||||
local packageFile
|
||||
local copiedPackageCount=0
|
||||
|
||||
((EUID == 0)) || die "Run this script as root: sudo $0"
|
||||
require_commands
|
||||
trap cleanup EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
configure_binfmt
|
||||
|
||||
workDir=$(mktemp -d /tmp/xlibre-aarch64.XXXXXX)
|
||||
chrootDir="$workDir/root"
|
||||
rootfsArchive="$workDir/ArchLinuxARM-aarch64-latest.tar.gz"
|
||||
mkdir -p "$chrootDir"
|
||||
|
||||
log "Downloading a fresh Arch Linux ARM aarch64 root filesystem"
|
||||
curl --fail --location --retry 3 --output "$rootfsArchive" "$rootfsUrl"
|
||||
|
||||
log "Creating aarch64 chroot"
|
||||
bsdtar -xpf "$rootfsArchive" -C "$chrootDir"
|
||||
install -m 0755 /usr/bin/qemu-aarch64-static "$chrootDir/usr/bin/qemu-aarch64-static"
|
||||
cp --remove-destination /etc/resolv.conf "$chrootDir/etc/resolv.conf"
|
||||
create_build_script "$chrootDir/root/build-xlibre"
|
||||
|
||||
# arch-chroot expects the chroot root to be a mountpoint.
|
||||
mount --bind "$chrootDir" "$chrootDir"
|
||||
|
||||
log "Starting aarch64 package build"
|
||||
arch-chroot "$chrootDir" /root/build-xlibre "$repoUrl" "${aarch64Packages[@]}"
|
||||
|
||||
shopt -s nullglob
|
||||
for packageFile in "$chrootDir"/output/*.pkg.tar.*; do
|
||||
[[ ${packageFile##*/} == *-aarch64.pkg.tar.* ]] || die "Unexpected non-aarch64 artifact: ${packageFile##*/}"
|
||||
install -m 0644 "$packageFile" "$outputDir/"
|
||||
((copiedPackageCount += 1))
|
||||
if [[ -n ${SUDO_UID:-} && -n ${SUDO_GID:-} ]]; then
|
||||
chown "$SUDO_UID:$SUDO_GID" "$outputDir/${packageFile##*/}"
|
||||
fi
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
((copiedPackageCount > 0)) || die "No package artifacts were copied to $outputDir"
|
||||
log "Copied $copiedPackageCount completed packages to $outputDir"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
startDir="$(pwd)"
|
||||
buildDir="${startDir}/xlibre-build"
|
||||
|
||||
packageList=(
|
||||
xlibre-input-libinput
|
||||
xlibre-xserver
|
||||
xlibre-video-amdgpu
|
||||
xlibre-video-ati
|
||||
xlibre-video-fbdev
|
||||
xlibre-video-intel
|
||||
xlibre-video-nouveau
|
||||
xlibre-video-vesa
|
||||
xlibre-video-dummy-with-vt
|
||||
)
|
||||
|
||||
mkdir -p "${buildDir}"
|
||||
|
||||
for i in "${packageList[@]}" ; do
|
||||
yay -Ga "$i"
|
||||
pushd "$i"
|
||||
makepkg -Acrsf
|
||||
cp -v ./*.pkg.tar.* "${buildDir}/"
|
||||
popd
|
||||
done
|
||||
Reference in New Issue
Block a user