--- a/homebrew-appbundle-gtk4-dmg.sh +++ b/homebrew-appbundle-gtk4_sdl3-dmg.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Freeciv - Copyright (C) 2022-2023 - Freeciv team +# Freeciv - Copyright (C) 2022-2026 - Freeciv team # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) @@ -11,14 +11,18 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# Variant of homebrew-appbundle.sh: GTK4 client only, libraries bundled -# inside the package. Output: dist/Freeciv.app, dist/Freeciv Server.app and -# dist/Freeciv-.dmg +# Variant of homebrew-appbundle.sh: GTK4 and SDL3 clients, libraries bundled +# inside the packages. Output in dist/: +# Freeciv.app GTK4 client +# Freeciv [SDL3].app SDL3 client +# Freeciv Server.app Terminal launcher for the server from Freeciv.app +# Freeciv-GTK4-.dmg Freeciv.app and Freeciv Server.app +# Freeciv-SDL3-.dmg Freeciv [SDL3].app and Freeciv Server.app # # Required: # brew install dylibbundler meson ninja pkg-config gettext icu4c \ # readline sqlite curl xz zstd gtk4 librsvg adwaita-icon-theme lua@5.4 \ -# sdl3 sdl3_mixer gdk-pixbuf +# sdl3 sdl3_image sdl3_ttf sdl3_mixer gdk-pixbuf # # Work from the top-level source directory, regardless of where the # script was started from @@ -42,7 +46,7 @@ CONTENTSDIR="${APPDIR}/Contents" # Clean start (changing the configuration requires a fresh build directory) -rm -rf "${DISTDIR}" build +rm -rf "${DISTDIR}" build build-sdl3 if ! mkdir -p "${CONTENTSDIR}/Resources" "${CONTENTSDIR}/MacOS" ; then echo "Failed to create \"${CONTENTSDIR}\"" >&2 @@ -211,10 +215,140 @@ echo "${LEFT}" >&2 fi +# === Freeciv [SDL3].app =================================================== + +SDLAPP="${DISTDIR}/Freeciv [SDL3].app" +SDLCONTENTS="${SDLAPP}/Contents" + +if ! mkdir -p "${SDLCONTENTS}/Resources" "${SDLCONTENTS}/MacOS" ; then + echo "Failed to create \"${SDLCONTENTS}\"" >&2 + exit 1 +fi + +if ! cp data/freeciv-client.icns "${SDLCONTENTS}/Resources/" ; then + echo "Failed to copy file \"freeciv-client.icns\"" >&2 + exit 1 +fi + +# Info.plist - the executable is a launcher script that sets up the environment +cat > "${SDLCONTENTS}/Info.plist" < + + + + CFBundleName + Freeciv [SDL3] + CFBundleIdentifier + freeciv.sdl3 + CFBundleVersion + ${VSTRING} + CFBundleShortVersionString + ${VSTRING} + CFBundleExecutable + Freeciv + CFBundleIconFile + freeciv-client.icns + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleInfoDictionaryVersion + 6.0 + NSHighResolutionCapable + + + +EOF + +if ! echo -n "APPL????" > "${SDLCONTENTS}/PkgInfo" ; then + echo "Failed to create file \"${SDLCONTENTS}/PkgInfo\"" >&2 + exit 1 +fi + +# Launcher: points the game to data and locale files inside the bundle +cat > "${SDLCONTENTS}/MacOS/Freeciv" <<'EOF' +#!/bin/bash +CONTENTS="$(cd "$(dirname "$0")/.." && pwd)" + +export FREECIV_DATA_PATH="$CONTENTS/share/freeciv" +export FREECIV_LOCALE_PATH="$CONTENTS/share/locale" +export PATH="$CONTENTS/bin:$PATH" + +exec "$CONTENTS/bin/freeciv-sdl3" "$@" +EOF +chmod +x "${SDLCONTENTS}/MacOS/Freeciv" + +mkdir build-sdl3 || { echo "Failed to create build directory" >&2; exit 1; } + +cd build-sdl3 || exit 1 + +if ! meson setup .. \ + -Dtools=manual,ruleup \ + -Dsyslua=true \ + -Ddebug=false \ + -Dclients=sdl3 \ + -Dfcmp=cli \ + -Daudio=sdl3 \ + -Dfollowtag=macos \ + -Ddefault_library=static \ + -Dprefix="${SDLCONTENTS}" || + ! ninja || + ! ninja install +then + echo "Build failed!" >&2 + exit 1 +fi + +cd .. || exit 1 + +chmod -R u+w "${SDLCONTENTS}" + +# Bundling libraries + +SDLMACHO=() +while IFS= read -r F ; do + if file -b "$F" | grep -q 'Mach-O' ; then + SDLMACHO+=("$F") + fi +done < <(find "${SDLCONTENTS}/bin" "${SDLCONTENTS}/lib" -type f 2>/dev/null) + +SDLARGS=() +for F in "${SDLMACHO[@]}" ; do + SDLARGS+=(-x "$F") +done + +if ! dylibbundler -od -b -cd "${SDLARGS[@]}" \ + -d "${SDLCONTENTS}/Frameworks/" \ + -p "@executable_path/../Frameworks/" \ + -s "${BREW}/lib" ; then + echo "dylibbundler failed!" >&2 + exit 1 +fi + +# Ad-hoc code signing (required on Apple Silicon) + +while IFS= read -r F ; do + if file -b "$F" | grep -q 'Mach-O' ; then + codesign --force -s - "$F" + fi +done < <(find "${SDLCONTENTS}/Frameworks" "${SDLCONTENTS}/bin" "${SDLCONTENTS}/lib" -type f 2>/dev/null) + +codesign --force --deep -s - "${SDLAPP}" + +# Sanity check: nothing should reference /opt/homebrew any more +LEFT=$(find "${SDLCONTENTS}/bin" "${SDLCONTENTS}/Frameworks" "${SDLCONTENTS}/lib" -type f -exec sh -c \ + 'file -b "$1" | grep -q Mach-O && otool -L "$1" | grep -H --label="$1" "/opt/homebrew"' _ {} \; 2>/dev/null) +if [ -n "${LEFT}" ] ; then + echo "Warning: references to /opt/homebrew remain in ${SDLAPP}:" >&2 + echo "${LEFT}" >&2 +fi + # --- Freeciv Server.app ----------------------------------------------------- # A separate small bundle, so that the server gets its own icon in Launchpad. -# It contains no binaries: it opens freeciv-server from Freeciv.app (next to -# it, or in /Applications) in a Terminal window. +# It contains no binaries: it opens freeciv-server from Freeciv.app or +# Freeciv [SDL3].app (next to it, or in /Applications) in a Terminal window. SERVERAPP="${DISTDIR}/Freeciv Server.app" SERVERCONTENTS="${SERVERAPP}/Contents" @@ -268,13 +402,15 @@ EOF chmod +x "${SERVERCONTENTS}/MacOS/FreecivServer" -# Script run inside Terminal: finds Freeciv.app and starts the server +# Script run inside Terminal: finds Freeciv.app or Freeciv [SDL3].app and starts the server cat > "${SERVERCONTENTS}/Resources/freeciv-server.command" <<'EOF' #!/bin/bash -# Locate Freeciv.app: next to this Freeciv Server.app first, then in /Applications +# Locate Freeciv.app or Freeciv [SDL3].app: next to this Freeciv Server.app +# first, then in /Applications SELF="$(cd "$(dirname "$0")/../../.." && pwd)" APP="" -for CAND in "$SELF/Freeciv.app" "/Applications/Freeciv.app" ; do +for CAND in "$SELF/Freeciv.app" "$SELF/Freeciv [SDL3].app" \ + "/Applications/Freeciv.app" "/Applications/Freeciv [SDL3].app" ; do if [ -x "$CAND/Contents/bin/freeciv-server" ] ; then APP="$CAND" break @@ -282,7 +418,7 @@ done if [ -z "$APP" ] ; then - echo "Freeciv.app not found next to Freeciv Server.app or in /Applications." + echo "Freeciv.app or Freeciv [SDL3].app not found next to Freeciv Server.app or in /Applications." echo "Press Enter to close." read -r exit 1 @@ -299,12 +435,14 @@ # --- DMG ------------------------------------------------------------------ STAGE="${DISTDIR}/dmg-stage" + +# GTK4: Freeciv.app and Freeciv Server.app mkdir -p "${STAGE}" cp -R "${APPDIR}" "${STAGE}/" cp -R "${SERVERAPP}" "${STAGE}/" ln -s /Applications "${STAGE}/Applications" -DMG="${DISTDIR}/Freeciv-${VSTRING}.dmg" +DMG="${DISTDIR}/Freeciv-GTK4-${VSTRING}.dmg" rm -f "${DMG}" # hdiutil create is deprecated in macOS 27 in favour of diskutil image; # fall back to hdiutil on older systems that lack "diskutil image" @@ -317,4 +455,22 @@ fi rm -rf "${STAGE}" +# SDL3: Freeciv [SDL3].app and Freeciv Server.app +mkdir -p "${STAGE}" +cp -R "${SDLAPP}" "${STAGE}/" +cp -R "${SERVERAPP}" "${STAGE}/" +ln -s /Applications "${STAGE}/Applications" + +SDLDMG="${DISTDIR}/Freeciv-SDL3-${VSTRING}.dmg" +rm -f "${SDLDMG}" +if ! diskutil image create from --format UDZO \ + --volumeName "Freeciv [SDL3] ${VSTRING}" "${STAGE}" "${SDLDMG}" && + ! hdiutil create -volname "Freeciv [SDL3] ${VSTRING}" -srcfolder "${STAGE}" \ + -ov -format UDZO "${SDLDMG}" ; then + echo "Failed to create DMG" >&2 + exit 1 +fi +rm -rf "${STAGE}" + echo "Done: ${DMG}" +echo "Done: ${SDLDMG}"