230 lines
6.7 KiB
Bash
Executable file
230 lines
6.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
#
|
|
# Singe 3
|
|
# Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public Licens
|
|
# as published by the Free Software Foundation; either version 3
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
# 02110-1301, USA.
|
|
#
|
|
|
|
# Builds Singe and every vendored library for one platform, or all of them. The work is done
|
|
# by the CMake superbuild (cmake/Superbuild.cmake, one preset per platform in
|
|
# CMakePresets.json); this script installs the host packages and calls it:
|
|
#
|
|
# ./build-all.sh every supported platform
|
|
# ./build-all.sh linux x86_64 one platform
|
|
#
|
|
# Anything cmake --build accepts can follow the platform, so a single library can be redone:
|
|
#
|
|
# ./build-all.sh linux x86_64 --target rebuild-ffmpeg
|
|
|
|
G_BUILDDIR=.builddir
|
|
G_INSTALL="$(dirname "$0")/INSTALL"
|
|
|
|
# The one copy of the host package list. Everything else that names these packages derives from it.
|
|
# Grouped by what wants them, because the SDL3 half is long and a bare list gives no clue why a
|
|
# package is here: SDL3 compiles a backend whenever it finds the headers, so a package missing from
|
|
# this list does not fail the build, it quietly drops a backend from the binary.
|
|
G_HOSTPACKAGES=(
|
|
# Toolchain
|
|
build-essential
|
|
cmake
|
|
git-lfs
|
|
pkg-config
|
|
perl
|
|
nasm
|
|
llvm
|
|
autoconf
|
|
automake
|
|
libtool
|
|
# dav1d, the AV1 decoder, is the one vendored library whose own build system is Meson
|
|
meson
|
|
ninja-build
|
|
# Content the build generates: embedded images, the menu video, the LuaSec table, the manual
|
|
imagemagick
|
|
ffmpeg
|
|
lua5.4
|
|
asciidoctor
|
|
ruby-asciidoctor-pdf
|
|
# Video decode and display
|
|
libva-dev
|
|
libvdpau-dev
|
|
libdrm-dev
|
|
libgl-dev
|
|
libegl-dev
|
|
libgles-dev
|
|
libgbm-dev
|
|
# SDL3 audio backends
|
|
libasound2-dev
|
|
libpulse-dev
|
|
libpipewire-0.3-dev
|
|
libjack-jackd2-dev
|
|
libsndio-dev
|
|
# SDL3 device hotplug, desktop integration and input methods
|
|
libudev-dev
|
|
libdbus-1-dev
|
|
libibus-1.0-dev
|
|
libxkbcommon-dev
|
|
# SDL3 X11 video backend and the extensions it uses
|
|
libx11-dev
|
|
libxext-dev
|
|
libxfixes-dev
|
|
libxi-dev
|
|
libxcursor-dev
|
|
libxrandr-dev
|
|
libxss-dev
|
|
libxtst-dev
|
|
# SDL3 Wayland video backend
|
|
libwayland-dev
|
|
wayland-protocols
|
|
libdecor-0-dev
|
|
)
|
|
|
|
G_INSTALLLEAD="Host packages (what build-all.sh installs):"
|
|
G_INSTALLWIDTH=72
|
|
|
|
|
|
function buildAll() {
|
|
local OS=$1
|
|
local ARCH=$2
|
|
shift 2
|
|
|
|
# Every platform builds with the zig the build fetches itself; the Pi preset also fetches its
|
|
# platform packages and macOS needs the Apple SDK tarball (see INSTALL).
|
|
# "macos universal" builds both macOS presets and joins them with llvm-lipo.
|
|
if [[ "${OS}" == "macos" && "${ARCH}" == "universal" ]]; then
|
|
buildAll macos aarch64 "$@"
|
|
buildAll macos x86_64 "$@"
|
|
cmake -P cmake/zig/macosUniversal.cmake
|
|
return
|
|
fi
|
|
|
|
cmake --preset ${OS}-${ARCH}
|
|
cmake --build --preset ${OS}-${ARCH} "$@"
|
|
}
|
|
|
|
|
|
# assets/ holds the artwork, the font and the menu video in Git LFS. A clone made without git-lfs
|
|
# leaves pointer stubs -- a hundred and thirty bytes of text where a video should be -- and the
|
|
# resource generators embed them without complaining, so the failure only shows up at run time as a
|
|
# menu with no background. One sentinel is enough to tell the two apart.
|
|
function checkoutHydrated() {
|
|
local SENTINEL="$(dirname "$0")/assets/menuBackground.mkv"
|
|
|
|
# A sentinel that is not there at all is not a hydrated checkout either, and saying so beats
|
|
# passing quietly because the path was wrong.
|
|
[[ -f "${SENTINEL}" ]] || return 1
|
|
! head -c 64 "${SENTINEL}" | grep -q "git-lfs.github.com/spec"
|
|
}
|
|
|
|
|
|
# The package list as INSTALL wants to read it: one sentence, wrapped, ending in a full stop.
|
|
function installParagraph() {
|
|
local LINE="${G_INSTALLLEAD}"
|
|
local SEP=" "
|
|
local WORD
|
|
|
|
for WORD in "${G_HOSTPACKAGES[@]}"; do
|
|
if (( ${#LINE} + ${#SEP} + ${#WORD} > G_INSTALLWIDTH )); then
|
|
printf '%s\n' "${LINE}"
|
|
LINE="${WORD}"
|
|
else
|
|
LINE="${LINE}${SEP}${WORD}"
|
|
fi
|
|
SEP=" "
|
|
done
|
|
printf '%s.\n' "${LINE}"
|
|
}
|
|
|
|
|
|
# What INSTALL says today: from the lead line to the first line that ends the sentence.
|
|
function installCurrent() {
|
|
awk -v lead="${G_INSTALLLEAD}" '
|
|
index($0, lead) == 1 { found = 1 }
|
|
found { print; if (/\.$/) exit }
|
|
' "${G_INSTALL}"
|
|
}
|
|
|
|
|
|
function installMatches() {
|
|
# A checkout without INSTALL is not worth nagging about; there is nothing to disagree with.
|
|
[[ ! -f "${G_INSTALL}" ]] || [[ "$(installParagraph)" == "$(installCurrent)" ]]
|
|
}
|
|
|
|
|
|
# Writes the paragraph back into INSTALL, replacing whatever sentence is there now.
|
|
function installSync() {
|
|
local TEMP
|
|
|
|
TEMP=$(mktemp)
|
|
awk -v lead="${G_INSTALLLEAD}" -v replacement="$(installParagraph)" '
|
|
index($0, lead) == 1 && !done {
|
|
print replacement
|
|
skip = 1
|
|
}
|
|
skip { if (/\.$/) { skip = 0; done = 1 } next }
|
|
{ print }
|
|
' "${G_INSTALL}" > "${TEMP}"
|
|
mv "${TEMP}" "${G_INSTALL}"
|
|
}
|
|
|
|
|
|
# -e = stop script on errors
|
|
# -u = stop script on undefined variable
|
|
# -o pipefail = stop pipeline if any step fails
|
|
set -euo pipefail
|
|
|
|
case "${1:-}" in
|
|
--packages)
|
|
printf '%s\n' "${G_HOSTPACKAGES[@]}"
|
|
exit 0
|
|
;;
|
|
--sync-install)
|
|
installSync
|
|
echo "INSTALL rewritten from build-all.sh."
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
mkdir -p ${G_BUILDDIR}
|
|
|
|
|
|
# Host packages the build needs on a Debian based system. INSTALL prints the same list for a
|
|
# reader who has not run anything yet, so it is written from this one: --sync-install rewrites
|
|
# that paragraph and every build checks it, which is why there is no second list to keep in step.
|
|
if ! installMatches; then
|
|
echo "warning: INSTALL's host package list no longer matches this script."
|
|
echo " Run ./build-all.sh --sync-install to write it from here."
|
|
fi
|
|
sudo apt-get install -y "${G_HOSTPACKAGES[@]}"
|
|
|
|
|
|
if ! checkoutHydrated; then
|
|
echo "error: assets/ holds git-lfs pointer files, not the real artwork, font and video."
|
|
echo " The build would embed those stubs and produce a broken binary."
|
|
echo " Fix the checkout with: git lfs install && git lfs pull"
|
|
exit 1
|
|
fi
|
|
|
|
|
|
if [[ $# -ge 2 ]]; then
|
|
buildAll "$@" 2>&1 | tee ${G_BUILDDIR}/$1-$2.log
|
|
else
|
|
buildAll linux x86_64 2>&1 | tee ${G_BUILDDIR}/linux-x86_64.log
|
|
buildAll macos universal 2>&1 | tee ${G_BUILDDIR}/macos-universal.log
|
|
buildAll linux aarch64 2>&1 | tee ${G_BUILDDIR}/linux-aarch64.log
|
|
buildAll windows x86_64 2>&1 | tee ${G_BUILDDIR}/windows-x86_64.log
|
|
fi
|