#!/usr/bin/env bash set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")/../.." source Packaging/OpenDingux/targets.sh source Packaging/OpenDingux/package-opk.sh usage() { >&2 echo "Usage: build.sh [--profile-generate|--profile-use] [--profile-dir PATH] [target]" >&2 usage_target } declare -rA BUILDROOT_REPOS=( [lepus]=https://github.com/OpenDingux/buildroot.git [retrofw]=https://github.com/retrofw/buildroot.git [rg99]=https://github.com/OpenDingux/buildroot.git [rg350]=https://github.com/OpenDingux/buildroot.git [gkd350h]=https://github.com/tonyjih/RG350_buildroot.git ) declare -rA BUILDROOT_DEFCONFIGS=( [lepus]='od_lepus_defconfig BR2_EXTERNAL=board/opendingux' [retrofw]='RetroFW_defconfig BR2_EXTERNAL=retrofw' [rg99]='od_rs90_defconfig BR2_EXTERNAL=board/opendingux' [rg350]='od_gcw0_defconfig BR2_EXTERNAL=board/opendingux' [gkd350h]='rg350_defconfig BR2_EXTERNAL=board/opendingux' ) declare TARGET declare BUILD_DIR declare BUILDROOT declare BUILDROOT_TARGET declare TOOLCHAIN declare -a CMAKE_CONFIGURE_OPTS=() declare PROFILE_GENERATE=0 declare PROFILE_USE=0 declare PROFILE_DIR="%q{HOME}/devilutionx-profile" declare BUILD_TYPE=release main() { parse_args "$@" BUILDROOT_TARGET="$TARGET" # If a TOOLCHAIN environment variable is set, just use that. if [[ -z ${TOOLCHAIN:-} ]]; then BUILDROOT="${BUILDROOT:-$HOME/devilutionx-buildroots/$BUILDROOT_TARGET}" TOOLCHAIN="${BUILDROOT}/output/host" fi >&2 echo "Building for target ${TARGET} in ${BUILD_DIR}" set -x if [[ -n ${BUILDROOT:-} ]]; then prepare_buildroot make_buildroot fi build package_opk } parse_args() { local -a positional=() while [[ $# -gt 0 ]]; do case "$1" in --profile-generate) PROFILE_GENERATE=1 shift ;; --profile-use) PROFILE_USE=1 shift ;; --profile-dir) shift if [[ $# -eq 0 ]]; then usage exit 64 fi PROFILE_DIR="$1" shift ;; -*|--*) >&2 echo "Error: unknown argument $1" >&2 echo usage exit 64 ;; *) positional+=("$1") shift ;; esac done if [[ ${#positional[@]} -ne 1 ]] || ! check_target "${positional[0]}"; then >&2 echo "Error: target is required" >&2 echo usage exit 64 fi TARGET="${positional[0]}" BUILD_DIR="build-${TARGET}" if (( PROFILE_GENERATE )) && (( PROFILE_USE )); then >&2 echo "Error: at most one of --profile-use and --profile-generate is allowed" exit 64 fi if [[ $TARGET = rg99 ]]; then OPK_EXTRA_FILES+=( Packaging/OpenDingux/devilutionx-from-disk.sh Packaging/OpenDingux/devilutionx-umount-opk-and-run.sh ) OPK_DESKTOP_EXEC="devilutionx-from-disk.sh" fi if (( PROFILE_GENERATE )); then CMAKE_CONFIGURE_OPTS+=( "-DDEVILUTIONX_PROFILE_GENERATE=ON" "-DDEVILUTIONX_PROFILE_DIR=${PROFILE_DIR}" ) OPK_DESKTOP_NAME="DevilutionX PG" OPK_DESKTOP_EXEC="profile-generate.sh" OPK_EXTRA_FILES+=( Packaging/OpenDingux/profile-generate.sh test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo ) local -a demo_saves=( test/fixtures/timedemo/WarriorLevel1to2/demo_0_reference_spawn_0.sv test/fixtures/timedemo/WarriorLevel1to2/spawn_0.sv ) if [[ $TARGET = rg99 ]]; then # We use unpacked saves on RG99. mkdir -p "$BUILD_DIR/demo-saves" unpack_and_minify_mpq --output-dir "$BUILD_DIR/demo-saves" "${demo_saves[@]}" OPK_EXTRA_FILES+=("$BUILD_DIR/demo-saves"/*) else OPK_EXTRA_FILES+=("${demo_saves[@]}") fi fi if (( PROFILE_USE )); then CMAKE_CONFIGURE_OPTS+=( "-DDEVILUTIONX_PROFILE_USE=ON" "-DDEVILUTIONX_PROFILE_DIR=${PROFILE_DIR}" ) fi } prepare_buildroot() { if [[ -d $BUILDROOT ]]; then return fi if [[ "${BUILDROOT_REPOS[$BUILDROOT_TARGET]}" == *.tar.gz ]]; then mkdir -p "$BUILDROOT" curl -L --fail "${BUILDROOT_REPOS[$BUILDROOT_TARGET]}" | \ tar -xz --strip-components 1 -C "$BUILDROOT" else git clone --depth=1 "${BUILDROOT_REPOS[$BUILDROOT_TARGET]}" "$BUILDROOT" fi cd "$BUILDROOT" mkdir -p ../shared-dl ln -s ../shared-dl dl # Work around a BR2_EXTERNAL initialization bug in older buildroots. mkdir -p output touch output/.br-external.mk local -a config_args=(${BUILDROOT_DEFCONFIGS[$BUILDROOT_TARGET]}) local -r config="${config_args[0]}" # If the buildroot uses per-package directories, disable them. # Otherwise, we'd have to buildroot the entire buildroot (up to `host-finalize`) to get # the merged host directory. if grep -q BR2_PER_PACKAGE_DIRECTORIES=y "configs/${config}"; then local -r new_config="${config%_defconfig}_no_ppd_defconfig" sed 's/BR2_PER_PACKAGE_DIRECTORIES=y/# BR2_PER_PACKAGE_DIRECTORIES is not selected/' \ "configs/${config}" > "configs/${new_config}" config_args[0]="$new_config" fi make "${config_args[@]}" cd - } make_buildroot() { cd "$BUILDROOT" local -a env_args=( # Unset client variables that cause issues with buildroot -u PERL_MM_OPT -u CMAKE_GENERATOR -u CMAKE_GENERATOR_PLATFORM -u CMAKE_GENERATOR_TOOLSET -u CMAKE_GENERATOR_INSTANCE # Enable parallelism BR2_JLEVEL=0 ) env "${env_args[@]}" make toolchain sdl cd - } cmake_configure() { # libzt uses `-fstack-protector` GCC flag by default. # We disable `-fstack-protector` because it isn't supported by target libc. cmake -S. -B"$BUILD_DIR" \ -G "Unix Makefiles" \ "-DTARGET_PLATFORM=$TARGET" \ -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN}/usr/share/buildroot/toolchainfile.cmake" \ -DBUILD_TESTING=OFF \ -DDEVILUTIONX_SYSTEM_LIBFMT=OFF \ -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF \ -DDEVILUTIONX_SYSTEM_BZIP2=OFF \ -DSTACK_PROTECTOR=OFF \ "${CMAKE_CONFIGURE_OPTS[@]}" } cmake_build() { BR_CACHE_DIR="${HOME}/.buildroot-ccache" cmake --build "$BUILD_DIR" -j "$(getconf _NPROCESSORS_ONLN)" } strip_bin() { "${TOOLCHAIN}/usr/bin/"*-linux-strip -s -R .comment -R .gnu.version "${BUILD_DIR}/devilutionx" } build_debug() { cmake_configure -DCMAKE_BUILD_TYPE=Debug -DASAN=OFF -DUBSAN=OFF -DCMAKE_CXX_FLAGS_DEBUG="-g -fno-omit-frame-pointer" "$@" cmake_build } build_relwithdebinfo() { cmake_configure -DCMAKE_BUILD_TYPE=RelWithDebInfo "$@" cmake_build } build_minsizerel() { cmake_configure -DCMAKE_BUILD_TYPE=MinSizeRel "$@" cmake_build strip_bin } build_release() { cmake_configure -DCMAKE_BUILD_TYPE=Release "$@" cmake_build strip_bin } build() { rm -f "${BUILD_DIR}/CMakeCache.txt" build_"$BUILD_TYPE" "$@" } main "$@"