2021-11-08 22:46:53 -03:00
#!/bin/sh
#
2023-01-06 15:36:05 -05:00
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
2021-11-08 22:46:53 -03:00
#
2023-01-06 15:36:05 -05:00
# This file is part of the 86Box distribution.
2021-11-08 22:46:53 -03:00
#
2023-01-06 15:36:05 -05:00
# Jenkins build script.
2021-11-08 22:46:53 -03:00
#
#
2023-01-06 15:36:05 -05:00
# Authors: RichardG, <richardg867@gmail.com>
2021-11-08 22:46:53 -03:00
#
2023-01-15 16:01:22 -03:00
# Copyright 2021-2023 RichardG.
2021-11-08 22:46:53 -03:00
#
#
# While this script was made for our Jenkins infrastructure, you can run it
# to produce Jenkins-like builds on your local machine by following these notes:
#
# - Run build.sh without parameters to see its usage
2022-04-26 00:39:10 -03:00
# - Any boolean CMake definitions (-D ...=ON/OFF) must be ON or OFF to ensure correct behavior
2021-11-08 22:46:53 -03:00
# - For Windows (MSYS MinGW) builds:
# - Packaging requires 7-Zip on Program Files
# - Packaging the Ghostscript DLL requires 32-bit and/or 64-bit Ghostscript on Program Files
2023-07-11 10:06:23 -03:00
# - Packaging the XAudio2 DLL for FAudio requires it to be at /home/86Box/dll32/xaudio2*.dll
# and/or /home/86Box/dll64/xaudio2*.dll (for 32-bit and 64-bit builds respectively)
2021-11-08 22:46:53 -03:00
# - For Linux builds:
# - Only Debian and derivatives are supported
2022-04-06 15:28:23 -03:00
# - dpkg and apt-get are called through sudo to manage dependencies; make sure those
# are configured as NOPASSWD in /etc/sudoers if you're doing unattended builds
2021-11-08 22:46:53 -03:00
# - For macOS builds:
2022-04-06 15:28:23 -03:00
# - A standard MacPorts installation is required, with the following macports.conf settings:
2022-04-06 18:21:25 -03:00
# buildfromsource always
# build_arch x86_64 (or arm64)
# universal_archs (blank)
# ui_interactive no
2022-08-31 15:10:42 -03:00
# macosx_deployment_target 10.13 (for x86_64, 10.14 for Qt Vulkan, or 11.0 for arm64)
2022-05-01 16:10:47 -03:00
# - For universal building on Apple Silicon hardware, install native MacPorts on the default
# /opt/local and Intel MacPorts on /opt/intel, then tell build.sh to build for "x86_64+arm64"
2022-08-31 15:10:42 -03:00
# - Qt Vulkan support through MoltenVK requires 10.14 while we target 10.13. We deal with that
# (at least for now) by abusing the x86_64h universal slice to branch Haswell and newer Macs
# into a Vulkan-enabled but 10.14+ binary, with older ones opting for a 10.13-compatible,
# non-Vulkan binary. With this approach, the only machines that miss out on Vulkan despite
# supporting Metal are Ivy Bridge ones as well as GPU-upgraded Mac Pros. For building that
# Vulkan binary, install another Intel MacPorts on /opt/x86_64h, then use the "x86_64h"
# architecture when invoking build.sh (either standalone or as part of an universal build)
# - port and sed are called through sudo to manage dependencies; make sure those are configured
2022-04-06 15:28:23 -03:00
# as NOPASSWD in /etc/sudoers if you're doing unattended builds
2021-11-08 22:46:53 -03:00
#
2021-11-17 14:43:48 -03:00
# Define common functions.
2022-03-12 16:42:45 -03:00
alias is_windows = '[ -n "$MSYSTEM" ]'
2021-11-08 22:46:53 -03:00
alias is_mac = 'uname -s | grep -q Darwin'
2021-11-13 01:53:00 -03:00
make_tar( ) {
2021-11-13 02:37:47 -03:00
# Install dependencies.
if ! which tar xz > /dev/null 2>& 1
then
2022-07-15 23:04:36 -03:00
if which apt-get > /dev/null 2>& 1
then
sudo apt-get update
DEBIAN_FRONTEND = noninteractive sudo apt-get install -y tar xz-utils
sudo apt-get clean
elif which port > /dev/null 2>& 1
then
2022-07-15 23:17:07 -03:00
sudo port selfupdate
2022-07-15 23:04:36 -03:00
sudo port install gnutar xz
fi
2021-11-13 02:37:47 -03:00
fi
2022-07-15 23:17:07 -03:00
# Use MacPorts gnutar (if installed) on macOS.
2022-07-15 23:04:36 -03:00
local tar_cmd = tar
2022-07-15 23:12:27 -03:00
which gnutar > /dev/null 2>& 1 && local tar_cmd = gnutar
2021-11-13 02:37:47 -03:00
2021-11-13 01:53:00 -03:00
# Determine the best supported compression type.
local compression_flag =
local compression_ext =
if which xz > /dev/null 2>& 1
then
local compression_flag = -J
local compression_ext = .xz
elif which bzip2 > /dev/null 2>& 1
then
local compression_flag = -j
local compression_ext = .bz2
elif which gzip > /dev/null 2>& 1
then
local compression_flag = -z
local compression_ext = .gz
fi
# Make tar verbose if requested.
2022-03-12 16:42:45 -03:00
[ -n " $VERBOSE " ] && local compression_flag = " $compression_flag -v "
2021-11-13 01:53:00 -03:00
# tar is notorious for having many diverging implementations. For instance,
# the flags we use to strip UID/GID metadata can be --owner/group (GNU),
# --uid/gid (bsdtar) or even none at all (MSYS2 bsdtar). Account for such
# flag differences by checking if they're mentioned on the help text.
local ownership_flags =
2022-07-15 23:04:36 -03:00
local tar_help = $( " $tar_cmd " --help 2>& 1)
2021-11-13 01:53:00 -03:00
if echo $tar_help | grep -q -- --owner
then
local ownership_flags = "--owner=0 --group=0"
elif echo $tar_help | grep -q -- --uid
then
local ownership_flags = "--uid 0 --gid 0"
fi
# Run tar.
2022-07-15 23:04:36 -03:00
" $tar_cmd " -c $compression_flag -f " $1 $compression_ext " $ownership_flags *
2021-11-13 01:53:00 -03:00
return $?
}
2022-07-24 13:31:58 -03:00
cache_dir = " $HOME /86box-build-cache "
[ ! -d " $cache_dir " ] && mkdir -p " $cache_dir "
check_buildtag( ) {
[ -z " $BUILD_TAG " -o " $BUILD_TAG " != " $( cat " $cache_dir /buildtag. $1 " 2> /dev/null) " ]
return $?
}
save_buildtag( ) {
local contents = " $BUILD_TAG "
[ -n " $2 " ] && local contents = " $2 "
echo " $contents " > " $cache_dir /buildtag. $1 "
return $?
}
2021-11-17 14:43:48 -03:00
# Set common variables.
project = 86Box
cwd = $( pwd )
# Parse arguments.
package_name =
arch =
tarball_name =
2022-05-01 16:10:47 -03:00
skip_archive = 0
2022-10-25 14:27:32 -03:00
dep_report = 0
2021-11-28 13:57:58 -03:00
strip = 0
2021-11-17 15:09:21 -03:00
cmake_flags =
2021-11-17 14:43:48 -03:00
while [ $# -gt 0 ]
do
case $1 in
-b)
shift
package_name = " $1 "
shift
arch = " $1 "
shift
; ;
2022-05-01 16:10:47 -03:00
-n)
shift
skip_archive = 1
; ;
2022-10-25 14:27:32 -03:00
-p)
shift
2023-06-16 23:36:50 -03:00
# Check for lddtree and install it if required.
which lddtree > /dev/null || DEBIAN_FRONTEND = noninteractive sudo apt-get -y install pax-utils
# Default to main binary.
binary = " $1 "
[ -z " $binary " ] && binary = " archive_tmp/usr/local/bin/ $project "
# Run lddtree with AppImage lib directories included in the search path.
LD_LIBRARY_PATH = $( find " $( pwd ) /archive_tmp " -type d -name lib -o -name lib64 | while read dir; do find " $dir " -type d; done | tr '\n' ':' ) \
lddtree " $binary "
exit $?
2022-10-25 14:27:32 -03:00
; ;
2021-11-17 14:43:48 -03:00
-s)
shift
tarball_name = " $1 "
shift
; ;
2021-11-28 13:57:58 -03:00
-t)
shift
strip = 1
; ;
2021-11-17 14:43:48 -03:00
*)
2022-10-25 14:27:32 -03:00
# Consume remaining arguments as CMake flags.
while [ $# -gt 0 ]
do
if echo $1 | grep -q " "
then
cmake_flag = " \" $1 \" "
else
cmake_flag = " $1 "
fi
if [ -z " $cmake_flags " ]
then
cmake_flags = " $cmake_flag "
else
cmake_flags = " $cmake_flags $cmake_flag "
fi
shift
done
2021-11-17 14:43:48 -03:00
; ;
esac
done
cmake_flags_extra =
# Check if mandatory arguments were specified.
2022-03-12 16:42:45 -03:00
if [ -z " $package_name " -a -z " $tarball_name " ] || [ -n " $package_name " -a -z " $arch " ]
2021-11-17 14:43:48 -03:00
then
2021-11-28 13:57:58 -03:00
echo '[!] Usage: build.sh -b {package_name} {architecture} [-t] [cmake_flags...]'
2021-11-17 14:43:48 -03:00
echo ' build.sh -s {source_tarball_name}'
2023-06-16 23:36:50 -03:00
echo 'Dep. tree: build.sh -p [archive_tmp/path/to/binary]'
2021-11-17 14:43:48 -03:00
exit 100
fi
2021-11-18 19:22:19 -03:00
# Switch to the repository root directory.
cd " $( dirname " $0 " ) /.. "
2021-11-17 14:43:48 -03:00
# Make source tarball if requested.
2022-03-12 16:42:45 -03:00
if [ -n " $tarball_name " ]
2021-11-17 14:43:48 -03:00
then
echo [ -] Making source tarball [ $tarball_name ]
# Clean local tree of gitignored files.
git clean -dfX
2021-11-18 19:22:19 -03:00
# Recreate working directory if it was removed by git clean.
2021-11-17 18:45:20 -03:00
[ ! -d " $cwd " ] && mkdir -p " $cwd "
2021-11-17 14:43:48 -03:00
# Save current HEAD commit to VERSION.
git log --stat -1 > VERSION || rm -f VERSION
# Archive source.
2021-11-18 19:22:19 -03:00
make_tar " $cwd / $tarball_name .tar "
2021-11-17 14:43:48 -03:00
status = $?
# Check if the archival succeeded.
if [ $status -ne 0 ]
2021-11-08 22:46:53 -03:00
then
2021-11-17 14:43:48 -03:00
echo [ !] Tarball creation failed with status [ $status ]
exit 1
else
echo [ -] Source tarball [ $tarball_name ] created successfully
[ -z " $package_name " ] && exit 0
2021-11-08 22:46:53 -03:00
fi
2021-11-17 14:43:48 -03:00
fi
2021-11-08 22:46:53 -03:00
2021-11-17 14:43:48 -03:00
echo [ -] Building [ $package_name ] for [ $arch ] with flags [ $cmake_flags ]
2021-11-08 22:46:53 -03:00
2022-02-11 14:06:07 -03:00
# Determine CMake toolchain file for this architecture.
2022-04-06 15:28:23 -03:00
toolchain_prefix = flags-gcc
is_mac && toolchain_prefix = llvm-macos
2022-02-11 14:06:07 -03:00
case $arch in
2022-04-06 15:28:23 -03:00
32 | x86) toolchain = " $toolchain_prefix -i686 " ; ;
2022-09-05 16:34:58 -03:00
64 | x86_64*) toolchain = " $toolchain_prefix -x86_64 " ; ;
2022-04-06 15:28:23 -03:00
ARM32 | arm32) toolchain = " $toolchain_prefix -armv7 " ; ;
ARM64 | arm64) toolchain = " $toolchain_prefix -aarch64 " ; ;
*) toolchain = " $toolchain_prefix - $arch " ; ;
2022-02-11 14:06:07 -03:00
esac
2022-04-06 15:28:23 -03:00
[ ! -e " cmake/ $toolchain .cmake " ] && toolchain = flags-gcc
2022-07-26 20:55:58 -03:00
toolchain_file = " cmake/ $toolchain .cmake "
2023-06-30 17:53:28 -03:00
toolchain_file_libs =
2022-02-11 14:06:07 -03:00
2021-11-17 14:43:48 -03:00
# Perform platform-specific setup.
2021-11-28 13:57:58 -03:00
strip_binary = strip
2021-11-17 14:43:48 -03:00
if is_windows
then
# Switch into the correct MSYSTEM if required.
msys = MINGW$arch
[ ! -d " / $msys " ] && msys = CLANG$arch
if [ -d " / $msys " ]
2021-11-08 22:46:53 -03:00
then
2021-11-17 14:43:48 -03:00
if [ " $MSYSTEM " != " $msys " ]
2021-11-08 22:46:53 -03:00
then
2021-11-17 14:43:48 -03:00
# Call build with the correct MSYSTEM.
echo [ -] Switching to MSYSTEM [ $msys ]
cd " $cwd "
2022-05-01 21:31:27 -03:00
args =
[ $strip -ne 0 ] && args = " -t $args "
2022-05-01 21:32:30 -03:00
[ $skip_archive -ne 0 ] && args = " -n $args "
2022-05-01 21:31:27 -03:00
CHERE_INVOKING = yes MSYSTEM = " $msys " bash -lc 'exec "' " $0 " '" -b "' " $package_name " '" "' " $arch " '" ' " $args " " $cmake_flags "
2021-11-17 14:43:48 -03:00
exit $?
2021-11-08 22:46:53 -03:00
fi
else
2021-11-17 14:43:48 -03:00
echo [ !] No MSYSTEM for architecture [ $arch ]
exit 2
fi
echo [ -] Using MSYSTEM [ $MSYSTEM ]
2022-02-11 14:06:07 -03:00
2022-07-24 00:18:26 -03:00
# Install dependencies only if we're in a new build and/or architecture.
2022-07-24 13:31:58 -03:00
if check_buildtag " $MSYSTEM "
2022-07-24 00:18:26 -03:00
then
2022-07-24 13:31:58 -03:00
# Update databases and keyring only if we're in a new build.
if check_buildtag pacmansync
then
# Update keyring as well, since the package signing keys sometimes change.
echo [ -] Updating package databases and keyring
2023-02-07 13:12:34 -03:00
pacman -Sy --needed --noconfirm msys2-keyring
2022-07-24 13:31:58 -03:00
# Save build tag to skip pacman sync/keyring later.
save_buildtag pacmansync
else
echo [ -] Not updating package databases and keyring again
fi
2022-03-12 16:42:45 -03:00
2023-02-07 13:12:34 -03:00
# Establish general dependencies.
pkgs = "git"
2022-03-12 16:42:45 -03:00
2023-02-07 13:12:34 -03:00
# Gather installed architecture-specific packages for updating.
# This prevents outdated shared libraries, unmet dependencies
# and potentially other issues caused by the fact pacman doesn't
# update a package's dependencies unless explicitly told to.
pkgs = " $pkgs $( pacman -Quq | grep -E " ^ $MINGW_PACKAGE_PREFIX - " ) "
2022-07-24 00:18:26 -03:00
2023-02-07 13:12:34 -03:00
# Establish architecture-specific dependencies.
while read pkg rest
do
pkgs = " $pkgs $MINGW_PACKAGE_PREFIX - $( echo " $pkg " | tr -d '\r' ) " # CR removal required
done < .ci/dependencies_msys.txt
2022-03-12 16:42:45 -03:00
2023-02-07 13:12:34 -03:00
# Install or update dependencies.
2022-07-24 00:18:26 -03:00
echo [ -] Installing dependencies through pacman
2023-02-07 13:12:34 -03:00
if ! pacman -S --needed --noconfirm $pkgs
2022-03-12 16:42:45 -03:00
then
# Install packages individually if installing them all together failed.
2022-03-16 14:36:57 -03:00
for pkg in $pkgs
2022-03-12 16:42:45 -03:00
do
2023-02-07 13:12:34 -03:00
pacman -S --needed --noconfirm " $pkg "
2022-03-12 16:42:45 -03:00
done
fi
2023-06-16 23:36:50 -03:00
2023-04-08 20:30:07 -03:00
# Clean pacman cache when running under Jenkins to save disk space.
[ " $CI " = "true" ] && rm -rf /var/cache/pacman/pkg
2022-03-12 16:42:45 -03:00
2022-07-24 00:18:26 -03:00
# Save build tag to skip this later. Doing it here (once everything is
# in place) is important to avoid potential issues with retried builds.
2022-07-24 13:31:58 -03:00
save_buildtag " $MSYSTEM "
2022-07-24 00:18:26 -03:00
else
echo [ -] Not installing dependencies again
2022-03-12 16:42:45 -03:00
fi
2021-11-17 14:43:48 -03:00
elif is_mac
then
# macOS lacks nproc, but sysctl can do the same job.
alias nproc = 'sysctl -n hw.logicalcpu'
2022-04-06 15:28:23 -03:00
2022-07-24 00:18:26 -03:00
# Handle universal building.
2022-05-01 16:10:47 -03:00
if echo " $arch " | grep -q '+'
then
# Create temporary directory for merging app bundles.
rm -rf archive_tmp_universal
mkdir archive_tmp_universal
# Build for each architecture.
merge_src =
for arch_universal in $( echo " $arch " | tr '+' ' ' )
do
# Run build for the architecture.
2022-05-01 21:31:27 -03:00
args =
[ $strip -ne 0 ] && args = " -t $args "
2022-08-31 15:10:42 -03:00
zsh -lc 'exec "' " $0 " '" -n -b "universal slice" "' " $arch_universal " '" ' " $args " " $cmake_flags " ' ' " $cmake_flags_extra "
2022-05-01 16:10:47 -03:00
status = $?
if [ $status -eq 0 ]
then
# Move app bundle to the temporary directory.
app_bundle_name = " archive_tmp/ $( ls archive_tmp | grep '.app$' ) "
mv " $app_bundle_name " " archive_tmp_universal/ $arch_universal .app "
status = $?
# Merge app bundles.
if [ -z " $merge_src " ]
then
# This is the first bundle, nothing to merge with.
merge_src = " $arch_universal "
else
# Merge previous bundle with this one.
merge_dest = " $merge_src + $arch_universal "
echo [ -] Merging app bundles [ $merge_src ] and [ $arch_universal ] into [ $merge_dest ]
# Merge directory structures.
2022-07-24 13:31:58 -03:00
( cd " archive_tmp_universal/ $merge_src .app " && find . -type d && cd " ../../archive_tmp_universal/ $arch_universal .app " && find . -type d && cd ../..) | sort > " $cache_dir /universal_listing.txt "
cat " $cache_dir /universal_listing.txt " | uniq | while IFS = read line
2022-05-01 16:10:47 -03:00
do
2022-05-01 22:25:50 -03:00
echo " > Directory: $line "
2022-05-01 16:10:47 -03:00
mkdir -p " archive_tmp_universal/ $merge_dest .app/ $line "
done
# Create merged file listing.
2022-07-24 13:31:58 -03:00
( cd " archive_tmp_universal/ $merge_src .app " && find . -type f && cd " ../../archive_tmp_universal/ $arch_universal .app " && find . -type f && cd ../..) | sort > " $cache_dir /universal_listing.txt "
2022-05-01 16:10:47 -03:00
2022-05-01 22:48:17 -03:00
# Copy files that only exist on one bundle.
2022-07-24 13:31:58 -03:00
cat " $cache_dir /universal_listing.txt " | uniq -u | while IFS = read line
2022-05-01 16:10:47 -03:00
do
if [ -e " archive_tmp_universal/ $merge_src .app/ $line " ]
then
file_src = " $merge_src "
else
file_src = " $arch_universal "
fi
2022-05-01 22:25:50 -03:00
echo " > Only on [ $file_src ]: $line "
2022-05-01 16:10:47 -03:00
cp -p " archive_tmp_universal/ $file_src .app/ $line " " archive_tmp_universal/ $merge_dest .app/ $line "
done
2022-05-01 22:48:17 -03:00
# Copy or lipo files that exist on both bundles.
2022-07-24 13:31:58 -03:00
cat " $cache_dir /universal_listing.txt " | uniq -d | while IFS = read line
2022-05-01 16:10:47 -03:00
do
if cmp -s " archive_tmp_universal/ $merge_src .app/ $line " " archive_tmp_universal/ $arch_universal .app/ $line "
then
2022-05-01 22:25:50 -03:00
echo " > Identical: $line "
2022-05-01 16:10:47 -03:00
cp -p " archive_tmp_universal/ $merge_src .app/ $line " " archive_tmp_universal/ $merge_dest .app/ $line "
elif lipo -create -output " archive_tmp_universal/ $merge_dest .app/ $line " " archive_tmp_universal/ $merge_src .app/ $line " " archive_tmp_universal/ $arch_universal .app/ $line " 2> /dev/null
then
2022-05-01 22:25:50 -03:00
echo " > Merged: $line "
2022-05-01 16:10:47 -03:00
else
2022-05-01 22:25:50 -03:00
echo " > Copied from [ $merge_src ]: $line "
2022-05-01 16:10:47 -03:00
cp -p " archive_tmp_universal/ $merge_src .app/ $line " " archive_tmp_universal/ $merge_dest .app/ $line "
fi
done
# Merge symlinks.
2022-07-24 13:31:58 -03:00
( cd " archive_tmp_universal/ $merge_src .app " && find . -type l && cd " ../../archive_tmp_universal/ $arch_universal .app " && find . -type l && cd ../..) | sort > " $cache_dir /universal_listing.txt "
cat " $cache_dir /universal_listing.txt " | uniq | while IFS = read line
2022-05-01 16:10:47 -03:00
do
2022-05-01 22:48:17 -03:00
# Get symlink destinations.
other_link_dest =
2022-05-01 16:10:47 -03:00
if [ -e " archive_tmp_universal/ $merge_src .app/ $line " ]
then
file_src = " $merge_src "
2022-05-01 22:48:17 -03:00
other_link_path = " archive_tmp_universal/ $arch_universal .app/ $line "
if [ -L " $other_link_path " ]
then
other_link_dest = " $( readlink " $other_link_path " ) "
elif [ -e " $other_link_path " ]
then
other_link_dest = '[not a symlink]'
fi
2022-05-01 16:10:47 -03:00
else
file_src = " $arch_universal "
fi
link_dest = " $( readlink " archive_tmp_universal/ $file_src .app/ $line " ) "
2022-05-01 22:48:17 -03:00
# Warn if destinations differ.
if [ -n " $other_link_dest " -a " $link_dest " != " $other_link_dest " ]
then
echo " > Symlink: $line => WARNING: different targets "
echo " >> Using: [ $merge_src ] $link_dest "
echo " >> Other: [ $arch_universal ] $other_link_dest "
else
echo " > Symlink: $line => $link_dest "
fi
2022-05-01 16:10:47 -03:00
ln -s " $link_dest " " archive_tmp_universal/ $merge_dest .app/ $line "
done
# Merge a subsequent bundle with this one.
merge_src = " $merge_dest "
fi
fi
if [ $status -ne 0 ]
then
echo [ !] Aborting universal build: [ $arch_universal ] failed with status [ $status ]
exit $status
fi
done
# Rename final app bundle.
rm -rf archive_tmp
mkdir archive_tmp
mv " archive_tmp_universal/ $merge_src .app " " $app_bundle_name "
# Sign final app bundle.
2022-05-01 22:25:50 -03:00
arch -" $( uname -m) " codesign --force --deep -s - " $app_bundle_name "
2022-05-01 16:10:47 -03:00
# Create zip.
2022-05-01 22:25:50 -03:00
echo [ -] Creating artifact archive
2022-05-01 16:10:47 -03:00
cd archive_tmp
2022-05-02 22:01:41 -03:00
zip --symlinks -r " $cwd / $package_name .zip " .
2022-05-01 16:10:47 -03:00
status = $?
# Check if the archival succeeded.
if [ $status -ne 0 ]
then
echo [ !] Artifact archive creation failed with status [ $status ]
exit 7
fi
# All good.
echo [ -] Universal build of [ $package_name ] for [ $arch ] with flags [ $cmake_flags ] successful
exit 0
fi
# Switch into the correct architecture if required.
case $arch in
2022-10-25 19:21:00 -03:00
x86_64*) arch_mac = "i386" ; arch_cmd = "x86_64" ; ;
*) arch_mac = " $arch " ; arch_cmd = " $arch " ; ;
2022-05-01 16:10:47 -03:00
esac
if [ " $( arch) " != " $arch " -a " $( arch) " != " $arch_mac " ]
then
# Call build with the correct architecture.
echo [ -] Switching to architecture [ $arch ]
cd " $cwd "
2022-05-01 21:31:27 -03:00
args =
[ $strip -ne 0 ] && args = " -t $args "
2022-05-01 21:32:30 -03:00
[ $skip_archive -ne 0 ] && args = " -n $args "
2022-10-25 19:21:00 -03:00
arch -" $arch_cmd " zsh -lc 'exec "' " $0 " '" -b "' " $package_name " '" "' " $arch " '" ' " $args " " $cmake_flags "
2022-05-01 16:10:47 -03:00
exit $?
fi
echo [ -] Using architecture [ $( arch) ]
2022-04-07 15:48:07 -03:00
# Locate the MacPorts prefix.
macports = "/opt/local"
[ -e " /opt/ $arch /bin/port " ] && macports = " /opt/ $arch "
[ " $arch " = "x86_64" -a -e "/opt/intel/bin/port" ] && macports = "/opt/intel"
2022-06-27 15:03:30 -03:00
export PATH = " $macports /bin: $macports /sbin: $macports /libexec/qt5/bin: $PATH "
2022-04-07 15:48:07 -03:00
2022-08-31 15:10:42 -03:00
# Enable MoltenVK on x86_64h and arm64, but not on x86_64.
# The rationale behind that is explained on the big comment up top.
moltenvk = 0
if [ " $arch " != "x86_64" ]
then
moltenvk = 1
cmake_flags_extra = " $cmake_flags_extra -D MOLTENVK=ON -D \"MOLTENVK_INCLUDE_DIR= $macports \" "
fi
# Install dependencies only if we're in a new build and/or MacPorts prefix.
if check_buildtag " $( basename " $macports " ) "
2022-07-24 00:18:26 -03:00
then
# Install dependencies.
echo [ -] Installing dependencies through MacPorts
sudo " $macports /bin/port " selfupdate
2022-08-31 15:10:42 -03:00
if [ $moltenvk -ne 0 ]
then
# Patch Qt to enable Vulkan support where supported.
qt5_portfile = " $macports /var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/aqua/qt5/Portfile "
sudo sed -i -e 's/-no-feature-vulkan/-feature-vulkan/g' " $qt5_portfile "
sudo sed -i -e 's/configure.env-append MAKE=/configure.env-append VULKAN_SDK=${prefix} MAKE=/g' " $qt5_portfile "
fi
2022-10-25 19:21:00 -03:00
while :
do
# Attempt to install dependencies.
sudo " $macports /bin/port " install $( cat .ci/dependencies_macports.txt) 2>& 1 | tee macports.log
# Stop if no port version activation errors were found.
2022-10-25 21:22:36 -03:00
stuck_dep = $( grep " cannot be built while another version of " macports.log | cut -d" " -f10)
2022-10-25 19:21:00 -03:00
[ -z $stuck_dep ] && break
# Deactivate the stuck dependency and try again.
sudo " $macports /bin/port " -f deactivate $stuck_dep
done
# Remove MacPorts error detection log.
rm -f macports.log
2022-07-24 00:18:26 -03:00
# Save build tag to skip this later. Doing it here (once everything is
# in place) is important to avoid potential issues with retried builds.
2022-08-31 15:10:42 -03:00
save_buildtag " $( basename " $macports " ) "
2022-07-24 00:18:26 -03:00
else
echo [ -] Not installing dependencies again
fi
2021-11-17 14:43:48 -03:00
else
# Determine Debian architecture.
case $arch in
x86) arch_deb = "i386" ; ;
x86_64) arch_deb = "amd64" ; ;
arm32) arch_deb = "armhf" ; ;
*) arch_deb = " $arch " ; ;
esac
2021-11-08 22:46:53 -03:00
2022-02-07 14:13:05 -03:00
# Establish general dependencies.
2022-07-25 18:29:11 -03:00
pkgs = "cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream"
2021-11-17 14:43:48 -03:00
if [ " $( dpkg --print-architecture) " = " $arch_deb " ]
then
pkgs = " $pkgs build-essential "
else
2022-07-24 00:49:10 -03:00
# Add foreign architecture if required.
2023-06-30 17:53:28 -03:00
if ! dpkg --print-foreign-architectures | grep -Fqx " $arch_deb "
2022-07-24 00:49:10 -03:00
then
sudo dpkg --add-architecture " $arch_deb "
2023-06-16 23:36:50 -03:00
2022-07-24 00:49:10 -03:00
# Force an apt-get update.
2022-07-24 13:31:58 -03:00
save_buildtag aptupdate " arch_ $arch_deb "
2022-07-24 00:49:10 -03:00
fi
2021-11-17 14:43:48 -03:00
pkgs = " $pkgs crossbuild-essential- $arch_deb "
fi
2022-02-07 14:13:05 -03:00
# Establish architecture-specific dependencies we don't want listed on the readme...
2022-07-25 18:29:11 -03:00
pkgs = " $pkgs linux-libc-dev: $arch_deb qttools5-dev: $arch_deb qtbase5-private-dev: $arch_deb "
2022-02-07 14:13:05 -03:00
# ...and the ones we do want listed. Non-dev packages fill missing spots on the list.
2021-11-17 14:43:48 -03:00
libpkgs = ""
longest_libpkg = 0
2023-07-10 23:14:17 -03:00
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev
2021-11-17 14:43:48 -03:00
do
libpkgs = " $libpkgs $pkg : $arch_deb "
2022-02-07 14:13:05 -03:00
length = $( echo -n $pkg | sed 's/-dev$//' | sed "s/qtdeclarative/qt/" | wc -c)
2021-11-17 14:43:48 -03:00
[ $length -gt $longest_libpkg ] && longest_libpkg = $length
done
2022-04-06 15:28:23 -03:00
# Determine toolchain architecture triplet.
2021-11-17 14:43:48 -03:00
case $arch in
2022-04-06 15:28:23 -03:00
x86) arch_triplet = "i686-linux-gnu" ; ;
arm32) arch_triplet = "arm-linux-gnueabihf" ; ;
arm64) arch_triplet = "aarch64-linux-gnu" ; ;
*) arch_triplet = " $arch -linux-gnu " ; ;
2021-11-17 14:43:48 -03:00
esac
2021-11-08 22:46:53 -03:00
2021-12-04 11:35:26 -03:00
# Determine library directory name for this architecture.
case $arch in
x86) libdir = "i386-linux-gnu" ; ;
2022-04-06 15:28:23 -03:00
*) libdir = " $arch_triplet " ; ;
2021-12-04 11:35:26 -03:00
esac
2023-06-30 17:53:28 -03:00
# Create CMake cross toolchain file.
2022-07-26 20:55:58 -03:00
toolchain_file_new = " $cache_dir /toolchain. $arch_deb .cmake "
cat << EOF > " $toolchain_file_new "
2021-11-08 22:46:53 -03:00
set( CMAKE_SYSTEM_NAME Linux)
set( CMAKE_SYSTEM_PROCESSOR $arch )
2022-04-06 15:28:23 -03:00
set( CMAKE_AR $arch_triplet -ar)
set( CMAKE_ASM_COMPILER $arch_triplet -gcc)
set( CMAKE_C_COMPILER $arch_triplet -gcc)
set( CMAKE_CXX_COMPILER $arch_triplet -g++)
set( CMAKE_LINKER $arch_triplet -ld)
set( CMAKE_OBJCOPY $arch_triplet -objcopy)
set( CMAKE_RANLIB $arch_triplet -ranlib)
set( CMAKE_SIZE $arch_triplet -size)
set( CMAKE_STRIP $arch_triplet -strip)
2021-11-08 22:46:53 -03:00
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
2021-12-04 11:35:26 -03:00
set( ENV{ PKG_CONFIG_PATH} "" )
2023-04-08 01:19:05 -03:00
set( ENV{ PKG_CONFIG_LIBDIR} " /usr/lib/ $libdir /pkgconfig:/usr/share/ $libdir /pkgconfig:/usr/share/pkgconfig " )
2022-02-11 13:55:12 -03:00
2022-07-26 20:55:58 -03:00
include( " $( realpath " $toolchain_file " ) " )
2021-11-08 22:46:53 -03:00
EOF
2022-07-26 20:55:58 -03:00
toolchain_file = " $toolchain_file_new "
2022-04-06 15:28:23 -03:00
strip_binary = " $arch_triplet -strip "
2021-11-08 22:46:53 -03:00
2023-06-30 17:53:28 -03:00
# Create a separate toolchain file for library compilation without including
# our own toolchain files, letting libraries set their own C(XX)FLAGS instead.
# The file is saved on a fixed location, since running CMake again on a library
# we've already built before will *not* update its toolchain file path; therefore,
# we cannot point them to our working directory, which may change across builds.
toolchain_file_libs = " $cache_dir /toolchain. $arch_deb .libs.cmake "
grep -Ev "^include\(" " $toolchain_file " > " $toolchain_file_libs "
2022-07-24 00:18:26 -03:00
# Install dependencies only if we're in a new build and/or architecture.
2022-07-24 13:31:58 -03:00
if check_buildtag " $arch_deb "
2022-07-24 00:18:26 -03:00
then
# Install or update dependencies.
echo [ -] Installing dependencies through apt
2022-07-24 13:31:58 -03:00
if check_buildtag aptupdate
2022-07-24 00:49:10 -03:00
then
sudo apt-get update
# Save build tag to skip apt-get update later, unless a new architecture
2022-07-24 13:31:58 -03:00
# is added to dpkg, in which case, this saved tag file gets replaced.
save_buildtag aptupdate
2022-07-24 00:49:10 -03:00
fi
2022-07-24 00:18:26 -03:00
DEBIAN_FRONTEND = noninteractive sudo apt-get -y install $pkgs $libpkgs
sudo apt-get clean
# Save build tag to skip this later. Doing it here (once everything is
# in place) is important to avoid potential issues with retried builds.
2022-07-24 13:31:58 -03:00
save_buildtag " $arch_deb "
2022-07-24 00:18:26 -03:00
else
echo [ -] Not installing dependencies again
fi
2021-11-17 14:43:48 -03:00
fi
2021-11-08 22:46:53 -03:00
2022-07-26 20:55:58 -03:00
# Point CMake to the toolchain file.
[ -e " $toolchain_file " ] && cmake_flags_extra = " $cmake_flags_extra -D \"CMAKE_TOOLCHAIN_FILE= $toolchain_file \" "
2021-11-17 14:43:48 -03:00
# Clean workspace.
echo [ -] Cleaning workspace
2022-07-24 00:49:10 -03:00
rm -rf build
2021-11-17 14:43:48 -03:00
2021-11-28 13:57:58 -03:00
# Add ARCH to skip the arch_detect process.
2021-11-17 14:43:48 -03:00
case $arch in
2022-02-11 14:06:07 -03:00
32 | x86) cmake_flags_extra = " $cmake_flags_extra -D ARCH=i386 " ; ;
2022-08-31 15:10:42 -03:00
64 | x86_64*) cmake_flags_extra = " $cmake_flags_extra -D ARCH=x86_64 " ; ;
2023-06-09 12:23:23 -03:00
ARM32 | arm32) cmake_flags_extra = " $cmake_flags_extra -D ARCH=arm -D NEW_DYNAREC=ON " ; ;
2023-06-09 11:21:12 -04:00
ARM64 | arm64) cmake_flags_extra = " $cmake_flags_extra -D ARCH=arm64 -D NEW_DYNAREC=ON " ; ;
2022-02-11 14:06:07 -03:00
*) cmake_flags_extra = " $cmake_flags_extra -D \"ARCH= $arch \" " ; ;
2021-11-17 14:43:48 -03:00
esac
2021-11-08 22:46:53 -03:00
2021-11-28 13:57:58 -03:00
# Add git hash.
2021-11-17 15:09:21 -03:00
git_hash = $( git rev-parse --short HEAD 2> /dev/null)
2021-11-24 21:49:36 -03:00
if [ " $CI " = "true" ]
then
2021-11-25 14:22:55 -03:00
# Backup strategy when running under Jenkins.
2021-11-24 21:49:36 -03:00
[ -z " $git_hash " ] && git_hash = $( echo $GIT_COMMIT | cut -c 1-8)
2022-03-12 16:42:45 -03:00
elif [ -n " $git_hash " ]
2021-11-24 21:49:36 -03:00
then
2021-11-25 14:22:55 -03:00
# Append + to denote a dirty tree.
2021-11-24 21:49:36 -03:00
git diff --quiet 2> /dev/null || git_hash = " $git_hash + "
fi
2022-03-12 16:42:45 -03:00
[ -n " $git_hash " ] && cmake_flags_extra = " $cmake_flags_extra -D \"EMU_GIT_HASH= $git_hash \" "
2021-11-28 13:57:58 -03:00
# Add copyright year.
year = $( date +%Y)
2022-03-12 16:42:45 -03:00
[ -n " $year " ] && cmake_flags_extra = " $cmake_flags_extra -D \"EMU_COPYRIGHT_YEAR= $year \" "
2021-11-08 22:46:53 -03:00
2021-11-17 14:43:48 -03:00
# Run CMake.
echo [ -] Running CMake with flags [ $cmake_flags $cmake_flags_extra ]
2022-03-21 13:53:23 -03:00
eval cmake -G Ninja $cmake_flags $cmake_flags_extra -S . -B build
2021-11-17 14:43:48 -03:00
status = $?
if [ $status -ne 0 ]
then
echo [ !] CMake failed with status [ $status ]
exit 3
fi
2021-11-08 22:46:53 -03:00
2022-07-26 19:34:02 -03:00
# Run actual build, unless we're running a dry build to precondition a node.
if [ " $BUILD_TAG " != "precondition" ]
2021-11-17 14:43:48 -03:00
then
2022-07-26 19:34:02 -03:00
echo [ -] Running build
cmake --build build -j$( nproc)
status = $?
if [ $status -ne 0 ]
then
echo [ !] Build failed with status [ $status ]
exit 4
fi
else
# Copy dummy binary into place.
echo [ -] Preconditioning build node
mkdir -p build/src
if is_windows
then
cp " $( which cp) " " build/src/ $project .exe "
elif is_mac
then
2022-07-26 19:37:35 -03:00
: # Special check during app bundle generation.
2022-07-26 19:34:02 -03:00
else
cp " $( which cp) " " build/src/ $project "
fi
2021-11-17 14:43:48 -03:00
fi
2021-11-08 22:46:53 -03:00
2022-07-24 00:18:26 -03:00
# Download Discord Game SDK from their CDN if we're in a new build.
2022-07-26 19:34:02 -03:00
discord_version = "3.2.1"
discord_zip = " $cache_dir /discord_game_sdk- $discord_version .zip "
if [ ! -e " $discord_zip " ]
2022-02-13 15:43:13 -03:00
then
2022-07-24 00:18:26 -03:00
# Download file.
2022-02-13 15:43:13 -03:00
echo [ -] Downloading Discord Game SDK
2022-07-26 19:34:02 -03:00
rm -f " $cache_dir /discord_game_sdk " * # remove old versions
wget -qO " $discord_zip " " https://dl-game-sdk.discordapp.net/ $discord_version /discord_game_sdk.zip "
2022-02-13 15:43:13 -03:00
status = $?
if [ $status -ne 0 ]
then
echo [ !] Discord Game SDK download failed with status [ $status ]
2022-07-24 00:18:26 -03:00
rm -f " $discord_zip "
2022-02-13 15:43:13 -03:00
fi
2022-07-24 00:18:26 -03:00
else
echo [ -] Not downloading Discord Game SDK again
2022-02-13 15:43:13 -03:00
fi
# Determine Discord Game SDK architecture.
case $arch in
2022-06-27 15:02:00 -03:00
32) arch_discord = "x86" ; ;
2022-08-31 15:10:42 -03:00
64 | x86_64*) arch_discord = "x86_64" ; ;
2022-06-27 15:02:00 -03:00
arm64 | ARM64) arch_discord = "aarch64" ; ;
*) arch_discord = " $arch " ; ;
2022-02-13 15:43:13 -03:00
esac
2022-02-14 11:57:12 -03:00
# Create temporary directory for archival.
echo [ -] Gathering archive files
rm -rf archive_tmp
mkdir archive_tmp
if [ ! -d "archive_tmp" ]
then
echo [ !] Archive directory creation failed
exit 5
fi
2021-11-17 14:43:48 -03:00
# Archive the executable and its dependencies.
# The executable should always be archived last for the check after this block.
status = 0
if is_windows
then
# Determine Program Files directory for Ghostscript and 7-Zip.
# Manual checks because MSYS is bad at passing the ProgramFiles variables.
pf = "/c/Program Files"
sevenzip = " $pf /7-Zip/7z.exe "
[ " $arch " = "32" -a -d "/c/Program Files (x86)" ] && pf = "/c/Program Files (x86)"
# Archive Ghostscript DLL from local official distribution installation.
for gs in " $pf " /gs/gs*.*.*
do
cp -p " $gs " /bin/gsdll*.dll archive_tmp/
done
2022-02-13 15:43:13 -03:00
# Archive Discord Game SDK DLL.
2022-07-24 00:18:26 -03:00
" $sevenzip " e -y -o"archive_tmp" " $discord_zip " " lib/ $arch_discord /discord_game_sdk.dll "
2022-02-13 15:43:13 -03:00
[ ! -e "archive_tmp/discord_game_sdk.dll" ] && echo [ !] No Discord Game SDK for architecture [ $arch_discord ]
2021-11-08 22:46:53 -03:00
2023-07-10 23:01:06 -03:00
# Archive XAudio2 DLL if required.
grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt || cp -p " /home/ $project /dll $arch /xaudio2 " * archive_tmp/
2021-11-08 22:46:53 -03:00
2021-11-28 13:57:58 -03:00
# Archive executable, while also stripping it if requested.
if [ $strip -ne 0 ]
then
" $strip_binary " -o " archive_tmp/ $project .exe " " build/src/ $project .exe "
status = $?
else
mv " build/src/ $project .exe " " archive_tmp/ $project .exe "
status = $?
fi
2021-11-17 14:43:48 -03:00
elif is_mac
then
2022-04-06 15:28:23 -03:00
# Archive app bundle with libraries.
cmake_flags_install =
[ $strip -ne 0 ] && cmake_flags_install = " $cmake_flags_install --strip "
cmake --install build --prefix " $( pwd ) /archive_tmp " $cmake_flags_install
status = $?
if [ $status -eq 0 ]
then
# Archive Discord Game SDK library.
2022-07-24 00:18:26 -03:00
unzip -j " $discord_zip " " lib/ $arch_discord /discord_game_sdk.dylib " -d "archive_tmp/" *".app/Contents/Frameworks"
2022-04-06 15:28:23 -03:00
[ ! -e "archive_tmp/" *".app/Contents/Frameworks/discord_game_sdk.dylib" ] && echo [ !] No Discord Game SDK for architecture [ $arch_discord ]
2022-08-31 15:10:42 -03:00
# Hack to convert x86_64 binaries to x86_64h when building that architecture.
if [ " $arch " = "x86_64h" ]
then
find archive_tmp -type f | while IFS = read line
do
2022-08-31 17:07:15 -03:00
# Parse and patch a fat header (0xCAFEBABE, big endian) first.
macho_offset = 0
if [ " $( dd if = " $line " bs = 1 count = 4 status = none) " = " $( printf '\xCA\xFE\xBA\xBE' ) " ]
2022-08-31 15:10:42 -03:00
then
2022-08-31 17:07:15 -03:00
# Get the number of fat architectures.
fat_archs = $(( $( dd if = " $line " bs = 1 skip = 4 count = 4 status = none | rev | tr -d '\n' | od -An -vtu4) ))
# Go through fat architectures.
fat_offset = 8
for fat_arch in $( seq 1 $fat_archs )
do
# Check CPU type.
if [ " $( dd if = " $line " bs = 1 skip = $fat_offset count = 4 status = none) " = " $( printf '\x01\x00\x00\x07' ) " ]
then
# Change CPU subtype in the fat header from ALL (0x00000003) to H (0x00000008).
printf '\x00\x00\x00\x08' | dd of = " $line " bs = 1 seek = $(( fat_offset + 4 )) count = 4 conv = notrunc status = none
# Save offset for this architecture's Mach-O header.
macho_offset = $(( $( dd if = " $line " bs = 1 skip = $(( fat_offset + 8 )) count = 4 status = none | rev | tr -d '\n' | od -An -vtu4) ))
# Stop looking for the x86_64 slice.
break
fi
# Move on to the next architecture.
fat_offset = $(( fat_offset + 20 ))
done
fi
# Now patch a 64-bit Mach-O header (0xFEEDFACF, little endian), either at
# the beginning or as a sub-header within a fat binary as parsed above.
2022-08-31 18:16:31 -03:00
if [ " $( dd if = " $line " bs = 1 skip = $macho_offset count = 8 status = none) " = " $( printf '\xCF\xFA\xED\xFE\x07\x00\x00\x01' ) " ]
2022-08-31 17:07:15 -03:00
then
# Change CPU subtype in the Mach-O header from ALL (0x00000003) to H (0x00000008).
printf '\x08\x00\x00\x00' | dd of = " $line " bs = 1 seek = $(( macho_offset + 8 )) count = 4 conv = notrunc status = none
2022-08-31 15:10:42 -03:00
fi
done
fi
2022-05-01 16:10:47 -03:00
# Sign app bundle, unless we're in an universal build.
[ $skip_archive -eq 0 ] && codesign --force --deep -s - "archive_tmp/" *".app"
2022-07-26 19:34:02 -03:00
elif [ " $BUILD_TAG " = "precondition" ]
then
# Continue with no app bundle on a dry build.
status = 0
2022-04-06 15:28:23 -03:00
fi
2021-11-17 14:43:48 -03:00
else
2022-07-24 00:18:26 -03:00
cwd_root = " $( pwd ) "
2022-07-24 14:25:24 -03:00
check_buildtag " libs. $arch_deb "
2022-02-15 19:45:10 -03:00
2022-03-06 01:30:19 -03:00
if grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt
2022-02-14 13:41:52 -03:00
then
2023-06-12 16:07:28 -03:00
# Build openal-soft 1.23.1 manually to fix audio issues. This is a temporary
2022-03-06 01:30:19 -03:00
# workaround until a newer version of openal-soft trickles down to Debian repos.
2023-06-12 16:07:28 -03:00
prefix = " $cache_dir /openal-soft-1.23.1 "
2022-07-24 14:25:24 -03:00
if [ ! -d " $prefix " ]
2022-03-06 01:30:19 -03:00
then
2022-07-26 19:34:02 -03:00
rm -rf " $cache_dir /openal-soft- " * # remove old versions
2023-06-12 16:07:28 -03:00
wget -qO - https://github.com/kcat/openal-soft/archive/refs/tags/1.23.1.tar.gz | tar zxf - -C " $cache_dir " || rm -rf " $prefix "
2022-03-06 01:30:19 -03:00
fi
2023-01-30 15:35:10 -03:00
# Patches to build with the old PipeWire version in Debian.
sed -i -e 's/>=0.3.23//' " $prefix /CMakeLists.txt "
sed -i -e 's/PW_KEY_CONFIG_NAME/"config.name"/g' " $prefix /alc/backends/pipewire.cpp "
2022-07-24 14:25:24 -03:00
prefix_build = " $prefix /build- $arch_deb "
2023-06-30 17:53:28 -03:00
cmake -G Ninja -D " CMAKE_TOOLCHAIN_FILE= $toolchain_file_libs " -D " CMAKE_INSTALL_PREFIX= $cwd_root /archive_tmp/usr " -S " $prefix " -B " $prefix_build " || exit 99
2022-07-24 14:25:24 -03:00
cmake --build " $prefix_build " -j$( nproc) || exit 99
cmake --install " $prefix_build " || exit 99
2022-03-06 01:30:19 -03:00
# Build SDL2 without sound systems.
sdl_ss = OFF
2022-02-14 13:41:52 -03:00
else
2022-03-12 16:42:45 -03:00
# Build FAudio 22.03 manually to remove the dependency on GStreamer. This is a temporary
# workaround until a newer version of FAudio trickles down to Debian repos.
2022-04-20 14:01:38 -03:00
prefix = " $cache_dir /FAudio-22.03 "
2022-07-24 14:25:24 -03:00
if [ ! -d " $prefix " ]
2022-03-06 01:30:19 -03:00
then
2022-07-26 19:34:02 -03:00
rm -rf " $cache_dir /FAudio- " * # remove old versions
2022-04-20 14:01:38 -03:00
wget -qO - https://github.com/FNA-XNA/FAudio/archive/refs/tags/22.03.tar.gz | tar zxf - -C " $cache_dir " || rm -rf " $prefix "
2022-03-06 01:30:19 -03:00
fi
2022-07-24 14:25:24 -03:00
prefix_build = " $prefix /build- $arch_deb "
2023-06-30 17:53:28 -03:00
cmake -G Ninja -D " CMAKE_TOOLCHAIN_FILE= $toolchain_file_libs " -D " CMAKE_INSTALL_PREFIX= $cwd_root /archive_tmp/usr " -S " $prefix " -B " $prefix_build " || exit 99
2022-07-24 14:25:24 -03:00
cmake --build " $prefix_build " -j$( nproc) || exit 99
cmake --install " $prefix_build " || exit 99
2022-03-06 01:30:19 -03:00
# Build SDL2 with sound systems.
sdl_ss = ON
2022-02-14 13:41:52 -03:00
fi
2022-02-15 19:45:10 -03:00
2022-10-25 14:27:32 -03:00
# Build SDL2 with video systems (and dependencies) only if the SDL interface is used.
2022-04-26 00:39:10 -03:00
sdl_ui = OFF
grep -qiE "^QT:BOOL=ON" build/CMakeCache.txt || sdl_ui = ON
2023-01-14 19:13:14 -03:00
# Build rtmidi without JACK support to remove the dependency on libjack, as
# the Debian libjack is very likely to be incompatible with the system jackd.
2022-04-20 14:01:38 -03:00
prefix = " $cache_dir /rtmidi-4.0.0 "
2022-07-24 14:25:24 -03:00
if [ ! -d " $prefix " ]
2022-02-15 19:45:10 -03:00
then
2022-07-26 19:34:02 -03:00
rm -rf " $cache_dir /rtmidi- " * # remove old versions
2022-04-20 14:01:38 -03:00
wget -qO - https://github.com/thestk/rtmidi/archive/refs/tags/4.0.0.tar.gz | tar zxf - -C " $cache_dir " || rm -rf " $prefix "
2022-02-15 19:45:10 -03:00
fi
2022-07-24 14:25:24 -03:00
prefix_build = " $prefix /build- $arch_deb "
2023-06-30 17:53:28 -03:00
cmake -G Ninja -D RTMIDI_API_JACK = OFF -D " CMAKE_TOOLCHAIN_FILE= $toolchain_file_libs " -D " CMAKE_INSTALL_PREFIX= $cwd_root /archive_tmp/usr " -S " $prefix " -B " $prefix_build " || exit 99
2022-07-24 14:25:24 -03:00
cmake --build " $prefix_build " -j$( nproc) || exit 99
cmake --install " $prefix_build " || exit 99
2022-02-14 13:41:52 -03:00
2023-01-30 18:26:14 -03:00
# Build FluidSynth without sound systems to remove the dependencies on libjack
# and other sound system libraries. We don't output audio through FluidSynth.
2023-01-14 19:13:14 -03:00
prefix = " $cache_dir /fluidsynth-2.3.0 "
if [ ! -d " $prefix " ]
then
rm -rf " $cache_dir /fluidsynth- " * # remove old versions
wget -qO - https://github.com/FluidSynth/fluidsynth/archive/refs/tags/v2.3.0.tar.gz | tar zxf - -C " $cache_dir " || rm -rf " $prefix "
fi
prefix_build = " $prefix /build- $arch_deb "
2023-01-30 18:26:14 -03:00
cmake -G Ninja -D enable-dbus= OFF -D enable-jack= OFF -D enable-oss= OFF -D enable-sdl2= OFF -D enable-pulseaudio= OFF -D enable-pipewire= OFF -D enable-alsa= OFF \
2023-06-30 17:53:28 -03:00
-D " CMAKE_TOOLCHAIN_FILE= $toolchain_file_libs " -D " CMAKE_INSTALL_PREFIX= $cwd_root /archive_tmp/usr " \
2023-01-30 18:26:14 -03:00
-S " $prefix " -B " $prefix_build " || exit 99
2023-01-14 19:13:14 -03:00
cmake --build " $prefix_build " -j$( nproc) || exit 99
cmake --install " $prefix_build " || exit 99
2022-03-21 13:53:23 -03:00
# Build SDL2 for joystick and FAudio support, with most components
# disabled to remove the dependencies on PulseAudio and libdrm.
2022-04-20 14:01:38 -03:00
prefix = " $cache_dir /SDL2-2.0.20 "
if [ ! -d " $prefix " ]
2022-02-15 19:47:53 -03:00
then
2022-07-26 19:34:02 -03:00
rm -rf " $cache_dir /SDL2- " * # remove old versions
2022-04-20 14:01:38 -03:00
wget -qO - https://www.libsdl.org/release/SDL2-2.0.20.tar.gz | tar zxf - -C " $cache_dir " || rm -rf " $prefix "
2022-02-15 19:47:53 -03:00
fi
2022-07-24 14:25:24 -03:00
prefix_build = " $cache_dir /SDL2-2.0.20-build- $arch_deb "
2022-04-26 00:39:10 -03:00
cmake -G Ninja -D SDL_SHARED = ON -D SDL_STATIC = OFF \
\
-D SDL_AUDIO = $sdl_ss -D SDL_DUMMYAUDIO = $sdl_ss -D SDL_DISKAUDIO = OFF -D SDL_OSS = OFF -D SDL_ALSA = $sdl_ss -D SDL_ALSA_SHARED = $sdl_ss \
-D SDL_JACK = $sdl_ss -D SDL_JACK_SHARED = $sdl_ss -D SDL_ESD = OFF -D SDL_ESD_SHARED = OFF -D SDL_PIPEWIRE = $sdl_ss \
2022-03-21 13:53:23 -03:00
-D SDL_PIPEWIRE_SHARED = $sdl_ss -D SDL_PULSEAUDIO = $sdl_ss -D SDL_PULSEAUDIO_SHARED = $sdl_ss -D SDL_ARTS = OFF -D SDL_ARTS_SHARED = OFF \
-D SDL_NAS = $sdl_ss -D SDL_NAS_SHARED = $sdl_ss -D SDL_SNDIO = $sdl_ss -D SDL_SNDIO_SHARED = $sdl_ss -D SDL_FUSIONSOUND = OFF \
2022-04-26 00:39:10 -03:00
-D SDL_FUSIONSOUND_SHARED = OFF -D SDL_LIBSAMPLERATE = $sdl_ss -D SDL_LIBSAMPLERATE_SHARED = $sdl_ss \
\
-D SDL_VIDEO = $sdl_ui -D SDL_X11 = $sdl_ui -D SDL_X11_SHARED = $sdl_ui -D SDL_WAYLAND = $sdl_ui -D SDL_WAYLAND_SHARED = $sdl_ui \
-D SDL_WAYLAND_LIBDECOR = $sdl_ui -D SDL_WAYLAND_LIBDECOR_SHARED = $sdl_ui -D SDL_WAYLAND_QT_TOUCH = OFF -D SDL_RPI = OFF -D SDL_VIVANTE = OFF \
-D SDL_VULKAN = OFF -D SDL_KMSDRM = $sdl_ui -D SDL_KMSDRM_SHARED = $sdl_ui -D SDL_OFFSCREEN = $sdl_ui -D SDL_RENDER = $sdl_ui \
\
-D SDL_JOYSTICK = ON -D SDL_HIDAPI_JOYSTICK = ON -D SDL_VIRTUAL_JOYSTICK = ON \
\
2022-04-26 17:59:25 -03:00
-D SDL_ATOMIC = OFF -D SDL_EVENTS = ON -D SDL_HAPTIC = OFF -D SDL_POWER = OFF -D SDL_THREADS = ON -D SDL_TIMERS = ON -D SDL_FILE = OFF \
2022-04-26 17:47:28 -03:00
-D SDL_LOADSO = ON -D SDL_CPUINFO = ON -D SDL_FILESYSTEM = $sdl_ui -D SDL_DLOPEN = OFF -D SDL_SENSOR = OFF -D SDL_LOCALE = OFF \
2022-04-26 00:39:10 -03:00
\
2023-06-30 17:53:28 -03:00
-D " CMAKE_TOOLCHAIN_FILE= $toolchain_file_libs " -D " CMAKE_INSTALL_PREFIX= $cwd_root /archive_tmp/usr " \
2022-07-24 14:25:24 -03:00
-S " $prefix " -B " $prefix_build " || exit 99
cmake --build " $prefix_build " -j$( nproc) || exit 99
cmake --install " $prefix_build " || exit 99
2023-06-16 23:28:03 -03:00
2023-06-27 13:09:11 -03:00
# We rely on the host to provide Vulkan libs to sidestep any potential
# dependency issues. While Qt expects libvulkan.so, at least Debian only
# ships libvulkan.so.1 without a symlink, so make our own as a workaround.
# The relative paths prevent appimage-builder from flattening the links.
2023-06-30 17:54:13 -03:00
mkdir -p " archive_tmp/usr/lib/ $libdir "
2023-06-27 13:09:11 -03:00
relroot = "../../../../../../../../../../../../../../../../../../../../../../../../../../../../.."
ln -s " $relroot /usr/lib/libvulkan.so.1 " "archive_tmp/usr/lib/libvulkan.so"
2023-06-30 17:54:13 -03:00
ln -s " $relroot /usr/lib/ $libdir /libvulkan.so.1 " " archive_tmp/usr/lib/ $libdir /libvulkan.so "
2023-06-27 13:09:11 -03:00
2023-07-11 18:54:53 -03:00
# The FluidSynth packaged by Debian bullseye is ABI incompatible with
# the newer version we compile, despite sharing a major version. Since we
# don't run into the one breaking ABI change they made, just symlink it.
ln -s " $( readlink "archive_tmp/usr/lib/libfluidsynth.so.3" ) " "archive_tmp/usr/lib/libfluidsynth.so.2"
2022-02-13 15:43:13 -03:00
# Archive Discord Game SDK library.
2022-07-24 00:18:26 -03:00
7z e -y -o"archive_tmp/usr/lib" " $discord_zip " " lib/ $arch_discord /discord_game_sdk.so "
2022-02-14 14:46:17 -03:00
[ ! -e "archive_tmp/usr/lib/discord_game_sdk.so" ] && echo [ !] No Discord Game SDK for architecture [ $arch_discord ]
2022-02-13 15:43:13 -03:00
2022-02-12 13:16:46 -03:00
# Archive readme with library package versions.
echo Libraries used to compile this $arch build of $project : > archive_tmp/README
dpkg-query -f '${Package} ${Version}\n' -W $libpkgs | sed "s/-dev / /" | sed "s/qtdeclarative/qt/" | while IFS = " " read pkg version
do
for i in $( seq $( expr $longest_libpkg - $( echo -n $pkg | wc -c) ) )
do
echo -n " " >> archive_tmp/README
done
echo $pkg $version >> archive_tmp/README
done
2022-04-26 00:39:10 -03:00
# Archive metadata.
project_id = $( ls src/unix/assets/*.*.xml | head -1 | grep -oP '/\K([^/]+)(?=\.[^\.]+\.[^\.]+$)' )
metainfo_base = archive_tmp/usr/share/metainfo
mkdir -p " $metainfo_base "
cp -p " src/unix/assets/ $project_id . " *".xml" " $metainfo_base / $project_id .appdata.xml "
2022-10-25 16:13:52 -03:00
applications_base = archive_tmp/usr/share/applications
mkdir -p " $applications_base "
cp -p " src/unix/assets/ $project_id .desktop " " $applications_base / "
2022-04-26 00:39:10 -03:00
2022-03-21 14:37:07 -03:00
# Archive icons.
2022-10-25 16:13:52 -03:00
icon_base = archive_tmp/usr/share/icons/hicolor
for icon_size in src/unix/assets/[ 0-9] *x[ 0-9] *
do
icon_dir = " $icon_base / $( basename " $icon_size " ) "
mkdir -p " $icon_dir "
cp -rp " $icon_size " " $icon_dir /apps "
done
2023-04-07 22:33:53 -03:00
project_icon = $( find " $icon_base / " [ 0-9] *x[ 0-9] */* -type f -name '*.png' -o -name '*.svg' | head -1 | grep -oP '/\K([^/]+)(?=\.[^\.]+$)' )
2021-11-08 22:46:53 -03:00
2021-11-28 13:57:58 -03:00
# Archive executable, while also stripping it if requested.
2022-02-11 22:47:23 -03:00
mkdir -p archive_tmp/usr/local/bin
2021-11-28 13:57:58 -03:00
if [ $strip -ne 0 ]
then
2022-02-11 22:47:23 -03:00
" $strip_binary " -o " archive_tmp/usr/local/bin/ $project " " build/src/ $project "
2021-11-28 13:57:58 -03:00
status = $?
else
2022-02-11 22:47:23 -03:00
mv " build/src/ $project " " archive_tmp/usr/local/bin/ $project "
2021-11-28 13:57:58 -03:00
status = $?
fi
2021-11-17 14:43:48 -03:00
fi
2021-11-08 22:46:53 -03:00
2021-11-28 13:57:58 -03:00
# Check if the executable strip/move succeeded.
2021-11-17 14:43:48 -03:00
if [ $status -ne 0 ]
2021-11-08 22:46:53 -03:00
then
2021-11-28 13:57:58 -03:00
echo [ !] Executable strip/move failed with status [ $status ]
2021-11-17 14:43:48 -03:00
exit 6
2021-11-08 22:46:53 -03:00
fi
2022-05-01 16:10:47 -03:00
# Stop if artifact archive creation was disabled.
if [ $skip_archive -ne 0 ]
then
echo [ -] Skipping artifact archive creation
exit 0
fi
2021-11-17 14:43:48 -03:00
# Produce artifact archive.
echo [ -] Creating artifact archive
if is_windows
2021-11-12 21:53:12 -03:00
then
2021-11-17 14:43:48 -03:00
# Create zip.
2022-02-11 22:47:23 -03:00
cd archive_tmp
2022-02-07 17:39:59 -03:00
" $sevenzip " a -y " $( cygpath -w " $cwd " ) \\ $package_name .zip " *
2021-11-17 14:43:48 -03:00
status = $?
elif is_mac
2021-11-12 21:53:12 -03:00
then
2022-05-01 16:10:47 -03:00
# Create zip.
2022-04-06 15:28:23 -03:00
cd archive_tmp
2022-05-02 22:01:41 -03:00
zip --symlinks -r " $cwd / $package_name .zip " .
2022-04-06 15:28:23 -03:00
status = $?
2021-11-12 21:53:12 -03:00
else
2022-02-11 22:47:23 -03:00
# Determine AppImage runtime architecture.
case $arch in
x86) arch_appimage = "i686" ; ;
arm32) arch_appimage = "armhf" ; ;
arm64) arch_appimage = "aarch64" ; ;
*) arch_appimage = " $arch " ; ;
esac
2022-02-13 15:15:40 -03:00
# Get version for AppImage metadata.
2022-04-26 00:39:10 -03:00
project_version = $( grep -oP '#define\s+EMU_VERSION\s+"\K([^"]+)' "build/src/include/" *"/version.h" 2> /dev/null)
2022-02-13 15:15:40 -03:00
[ -z " $project_version " ] && project_version = unknown
2022-04-26 00:39:10 -03:00
build_num = $( grep -oP '#define\s+EMU_BUILD_NUM\s+\K([0-9]+)' "build/src/include/" *"/version.h" 2> /dev/null)
2022-03-12 16:42:45 -03:00
[ -n " $build_num " -a " $build_num " != "0" ] && project_version = " $project_version -b $build_num "
2022-02-13 15:15:40 -03:00
2022-04-26 00:59:22 -03:00
# Generate modified AppImage metadata to suit build requirements.
cat << EOF > AppImageBuilder-generated.yml
2022-10-25 14:27:32 -03:00
# This file is automatically generated by .ci/build.sh and will be
2022-04-26 00:59:22 -03:00
# overwritten if edited. Please edit .ci/AppImageBuilder.yml instead.
EOF
while IFS = read line
do
# Skip blank or comment lines.
echo " $line " | grep -qE '^(#|$)' && continue
2022-10-25 14:27:32 -03:00
# Parse "# if OPTION:TYPE=VALUE" CMake condition lines.
2022-04-26 00:59:22 -03:00
condition = $( echo " $line " | grep -oP '# if \K(.+)' )
if [ -n " $condition " ]
then
# Skip line if the condition is not matched.
grep -qiE " ^ $condition " build/CMakeCache.txt || continue
fi
# Copy line.
echo " $line " >> AppImageBuilder-generated.yml
2023-01-30 22:37:55 -03:00
# Workaround for appimage-builder issues 272 and 283 (i686 and armhf are also missing)
if [ " $arch_appimage " != "x86_64" -a " $line " = " files:" ]
then
2023-01-31 14:07:37 -03:00
# Some mild arbitrary code execution with a dummy package...
[ ! -d /runtime ] && sudo apt-get -y -o 'DPkg::Post-Invoke::=mkdir -p /runtime; chmod 777 /runtime' install libsixel1 > /dev/null 2>& 1
2023-01-30 22:37:55 -03:00
echo " include:" >> AppImageBuilder-generated.yml
for loader in " /lib/ $libdir /ld-linux " *.so.*
do
for loader_copy in " $loader " " /lib/ $( basename " $loader " ) "
do
2023-02-06 19:37:51 -03:00
if [ ! -e " /runtime/compat $loader_copy " ]
then
mkdir -p " /runtime/compat $( dirname " $loader_copy " ) "
ln -s " $loader " " /runtime/compat $loader_copy "
fi
2023-01-30 22:37:55 -03:00
echo " - /runtime/compat $loader_copy " >> AppImageBuilder-generated.yml
done
done
fi
2022-04-26 00:59:22 -03:00
done < .ci/AppImageBuilder.yml
2022-02-11 22:47:23 -03:00
# Download appimage-builder if necessary.
2023-01-30 22:37:55 -03:00
appimage_builder_url = " https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0- $( uname -m) .AppImage "
2022-07-26 19:34:02 -03:00
appimage_builder_binary = " $cache_dir / $( basename " $appimage_builder_url " ) "
if [ ! -e " $appimage_builder_binary " ]
then
rm -rf " $cache_dir / " *".AppImage" # remove old versions
wget -qO " $appimage_builder_binary " " $appimage_builder_url "
fi
2022-02-11 22:47:23 -03:00
2022-07-26 19:34:02 -03:00
# Symlink appimage-builder binary and global cache directory.
rm -rf appimage-builder.AppImage appimage-builder-cache " $project - " *".AppImage" # also remove any dangling AppImages which may interfere with the renaming process
ln -s " $appimage_builder_binary " appimage-builder.AppImage
chmod u+x appimage-builder.AppImage
2022-04-26 17:57:57 -03:00
mkdir -p " $cache_dir /appimage-builder-cache "
ln -s " $cache_dir /appimage-builder-cache " appimage-builder-cache
2022-02-11 22:47:23 -03:00
# Run appimage-builder in extract-and-run mode for Docker compatibility.
2023-01-30 22:37:55 -03:00
# --appdir is a workaround for appimage-builder issue 270 reported by us.
2022-11-20 14:09:21 -03:00
for retry in 1 2 3 4 5
do
project = " $project " project_id = " $project_id " project_version = " $project_version " project_icon = " $project_icon " arch_deb = " $arch_deb " \
arch_appimage = " $arch_appimage " appimage_path = " $cwd / $package_name .AppImage " APPIMAGE_EXTRACT_AND_RUN = 1 ./appimage-builder.AppImage \
--recipe AppImageBuilder-generated.yml --appdir " $( grep -oP '^\s+path: \K(.+)' AppImageBuilder-generated.yml) "
status = $?
[ $status -eq 0 ] && break
2023-04-03 18:10:31 -03:00
[ $status -eq 127 ] && rm -rf /tmp/appimage_extracted_*
2022-11-20 14:09:21 -03:00
done
2022-02-11 22:47:23 -03:00
2022-10-25 14:27:32 -03:00
# Remove appimage-builder binary on failure, just in case it's corrupted.
[ $status -ne 0 ] && rm -f " $appimage_builder_binary "
2021-11-13 01:53:00 -03:00
fi
2021-11-17 14:43:48 -03:00
# Check if the archival succeeded.
if [ $status -ne 0 ]
2021-11-08 22:46:53 -03:00
then
2021-11-17 14:43:48 -03:00
echo [ !] Artifact archive creation failed with status [ $status ]
exit 7
2021-11-08 22:46:53 -03:00
fi
2021-11-17 14:43:48 -03:00
# All good.
echo [ -] Build of [ $package_name ] for [ $arch ] with flags [ $cmake_flags ] successful
exit 0