diff --git a/.github/workflows/build-all.yaml b/.github/workflows/build-all.yaml index a28a56aa9..af26d4716 100644 --- a/.github/workflows/build-all.yaml +++ b/.github/workflows/build-all.yaml @@ -19,7 +19,7 @@ jobs: --security-opt apparmor:unconfined strategy: matrix: - flavour: [pkg-appimage-snapshot, pkg-appimage-deployment, pkg-appimage] + flavour: [deployment, test, dev] steps: ## This is for debugging only and helps developing the workflow. # - name: Environment Variables @@ -58,11 +58,14 @@ jobs: ldconfig - name: Build Oolite run: | - ShellScripts/common/build_oolite.sh ${{matrix.flavour}} + ./mk.sh build ${{matrix.flavour}} --github-repository="$GITHUB_REPOSITORY" + - name: Package Oolite + run: | + ./mk.sh pkg-appimage ${{matrix.flavour}} - name: Archive installer uses: actions/upload-artifact@v6 with: - name: oolite-linux-${{matrix.flavour}} + name: oolite-linux-appimage-${{matrix.flavour}} path: | build/oolite*.AppImage retention-days: 5 @@ -90,11 +93,15 @@ jobs: fetch-depth: 0 - name: Build flatpak run: | - installers/flatpak/create_flatpak.sh + echo "Installing gitversion..." + source ShellScripts/Linux/install_gitversion_fn.sh + mkdir -p /usr/local/bin + install_gitversion "." + ./mk.sh pkg-flatpak deployment --github-repository="$GITHUB_REPOSITORY" - name: Archive installer uses: actions/upload-artifact@v6 with: - name: oolite-flatpak + name: oolite-linux-flatpak-deployment path: | build/space.oolite.Oolite*.flatpak retention-days: 5 @@ -103,7 +110,7 @@ jobs: runs-on: windows-latest strategy: matrix: - flavour: [pkg-win-snapshot, pkg-win-deployment, pkg-win] + flavour: [deployment, test, dev] steps: ## This is for debugging only and helps developing the workflow. # - name: Environment Variables @@ -117,6 +124,7 @@ jobs: - name: Set up MSYS2 uses: msys2/setup-msys2@v2 with: + msystem: UCRT64 update: true cache: false - name: Checkout Oolite @@ -139,12 +147,20 @@ jobs: shell: msys2 {0} env: msystem: UCRT64 + PYTHONUTF8: "1" + run: | + ./mk.sh build ${{matrix.flavour}} --github-repository="$GITHUB_REPOSITORY" + - name: Package Oolite + shell: msys2 {0} + env: + msystem: UCRT64 + PYTHONUTF8: "1" run: | - ShellScripts/common/build_oolite.sh ${{matrix.flavour}} + ./mk.sh pkg-win ${{matrix.flavour}} - name: Archive installer uses: actions/upload-artifact@v6 with: - name: oolite-windows-${{matrix.flavour}} + name: oolite-windows-nsis-${{matrix.flavour}} path: | build/OoliteInstall*.exe retention-days: 5 @@ -164,7 +180,7 @@ jobs: uses: actions/download-artifact@v7 with: path: artifacts - - name: Calculate version number and set OOLITE_VERSION + - name: Calculate version number and set VER_FULL id: version run: | set -x @@ -184,14 +200,14 @@ jobs: echo "Found AppImage: $APPIMAGE_PATH" # 3. Run with packageinfo and extract the string inside quotes chmod +x "$APPIMAGE_PATH" - VERSION_STR=$("$APPIMAGE_PATH" packageinfo | awk -F'"' '/^[[:space:]]*version =/ {print $2; exit}') - if [[ -z "$VERSION_STR" ]]; then + VER_FULL=$("$APPIMAGE_PATH" packageinfo | awk -F'"' '/^[[:space:]]*version =/ {print $2; exit}') + if [[ -z "$VER_FULL" ]]; then echo "❌ Failed to extract version string from packageinfo output!" >&2 exit 1 fi - echo "Extracted Version: $VERSION_STR" + echo "Extracted Version: $VER_FULL" # 4. Output the extracted version for subsequent steps - echo "OOLITE_VERSION=$VERSION_STR" >> "$GITHUB_OUTPUT" + echo "VER_FULL=$VER_FULL" >> "$GITHUB_OUTPUT" - name: Remove old prereleases if: github.ref == 'refs/heads/master' || endsWith(github.ref, 'maintenance') uses: s00d/delete-older-releases@0.2.1 @@ -208,17 +224,17 @@ jobs: with: repo_token: "${{ secrets.GITHUB_TOKEN }}" # automatic_release_tag: "latest" - automatic_release_tag: "${{ steps.version.outputs.OOLITE_VERSION }}" + automatic_release_tag: "${{ steps.version.outputs.VER_FULL }}" prerelease: true - title: "Oolite ${{ steps.version.outputs.OOLITE_VERSION }}" + title: "Oolite ${{ steps.version.outputs.VER_FULL }}" files: | - artifacts/oolite-windows-pkg-win-snapshot/OoliteInstall-*-dev.exe - artifacts/oolite-windows-pkg-win-deployment/OoliteInstall-*.exe - artifacts/oolite-windows-pkg-win/OoliteInstall-*.exe - artifacts/oolite-linux-pkg-appimage-snapshot/*.AppImage - artifacts/oolite-linux-pkg-appimage-deployment/*.AppImage - artifacts/oolite-linux-pkg-appimage/*.AppImage - artifacts/oolite-flatpak/*.flatpak + artifacts/oolite-windows-nsis-deployment/OoliteInstall-*.exe + artifacts/oolite-windows-nsis-test/OoliteInstall-*.exe + artifacts/oolite-windows-nsis-dev/OoliteInstall-*-dev.exe + artifacts/oolite-linux-appimage-deployment/*.AppImage + artifacts/oolite-linux-appimage-test/*.AppImage + artifacts/oolite-linux-appimage-dev/*.AppImage + artifacts/oolite-linux-flatpak-deployment/*.flatpak - name: Remove old workflow runs if: github.ref == 'refs/heads/master' || endsWith(github.ref, 'maintenance') uses: Mattraks/delete-workflow-runs@v2 diff --git a/.github/workflows/test_builds.yaml b/.github/workflows/test_builds.yaml index dfb1c4426..43bd7d77c 100644 --- a/.github/workflows/test_builds.yaml +++ b/.github/workflows/test_builds.yaml @@ -32,7 +32,7 @@ jobs: cat << EOF >> ~/.curlrc header = "Authorization: Bearer $GITHUB_TOKEN" header = "Accept: application/vnd.github+json" - EOF + EOF - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -47,17 +47,16 @@ jobs: - name: Install Mozilla static library run: | ShellScripts/Linux/install_mozilla_js.sh system - - name: Build and test Oolite - if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name + - name: Build Oolite run: | - ShellScripts/common/build_oolite.sh test - - name: Build Oolite (no test) - if: github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + ./mk.sh build dev + - name: Test Oolite + if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name run: | - ShellScripts/common/build_oolite.sh + ./mk.sh test dev - name: Build AppImage run: | - ShellScripts/common/build_oolite.sh pkg-appimage-snapshot + ./mk.sh pkg-appimage dev fedora: runs-on: ubuntu-latest @@ -82,7 +81,7 @@ jobs: cat << EOF >> ~/.curlrc header = "Authorization: Bearer $GITHUB_TOKEN" header = "Accept: application/vnd.github+json" - EOF + EOF - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -97,17 +96,16 @@ jobs: ShellScripts/Linux/install_mozilla_js.sh system echo "/usr/local/lib64" | tee -a /etc/ld.so.conf ldconfig - - name: Build and test Oolite - if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name + - name: Build Oolite run: | - ShellScripts/common/build_oolite.sh test - - name: Build Oolite (no test) - if: github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + ./mk.sh build dev + - name: Test Oolite + if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name run: | - ShellScripts/common/build_oolite.sh + ./mk.sh test dev - name: Build AppImage run: | - ShellScripts/common/build_oolite.sh pkg-appimage-snapshot + ./mk.sh pkg-appimage dev arch: runs-on: ubuntu-latest @@ -132,7 +130,7 @@ jobs: cat << EOF >> ~/.curlrc header = "Authorization: Bearer $GITHUB_TOKEN" header = "Accept: application/vnd.github+json" - EOF + EOF - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -147,17 +145,16 @@ jobs: ShellScripts/Linux/install_mozilla_js.sh system echo "/usr/local/lib" | tee -a /etc/ld.so.conf ldconfig - - name: Build and test Oolite - if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name + - name: Build Oolite run: | - ShellScripts/common/build_oolite.sh test - - name: Build Oolite (no test) - if: github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + ./mk.sh build dev + - name: Test Oolite + if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name run: | - ShellScripts/common/build_oolite.sh + ./mk.sh test dev - name: Build AppImage run: | - ShellScripts/common/build_oolite.sh pkg-appimage-snapshot + ./mk.sh pkg-appimage dev windows: runs-on: windows-latest @@ -191,18 +188,20 @@ jobs: EOF cp ~/.curlrc /c/Users/runneradmin/.curlrc 2>/dev/null || true ShellScripts/Windows/install_deps.sh clang - - name: Build and test Oolite - if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name + + - name: Build Oolite shell: msys2 {0} env: msystem: UCRT64 + PYTHONUTF8: "1" run: | - ShellScripts/common/build_oolite.sh test + ./mk.sh build dev - - name: Build Oolite (no test) - if: github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + - name: Test Oolite + if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name shell: msys2 {0} env: msystem: UCRT64 + PYTHONUTF8: "1" run: | - ShellScripts/common/build_oolite.sh + ./mk.sh test dev diff --git a/Makefile b/Makefile deleted file mode 100755 index 6a25ab871..000000000 --- a/Makefile +++ /dev/null @@ -1,97 +0,0 @@ -# Use bash as the explicit shell and enable strict error handling for safety -SHELL := /bin/bash -.SHELLFLAGS := -eu -o pipefail -c - -NATIVE_FILE ?= clang.ini -BUILDER ?= unknown - -# Modern, self-documenting help target. -# It parses the '##' comments next to targets automatically. -.PHONY: help -help: ## Show this help message - @echo "Usage: make [target]" - @echo "" - @echo "Targets:" - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-25s\033[0m %s\n", $$1, $$2}' - -# Macro for Meson workflow -define meson_build - meson setup build/meson_$(2) $(1) -Dgithub_repository=${GITHUB_REPOSITORY} --native-file $(NATIVE_FILE) --reconfigure 2>/dev/null || meson setup build/meson_$(2) $(1) -Dgithub_repository=${GITHUB_REPOSITORY} --native-file $(NATIVE_FILE) - meson compile -C build/meson_$(2) -endef - -# Helper macro for syncing OXP files cleanly -define sync_debug_oxp - mkdir -p build/meson_$(1)/oolite.app/AddOns - rm -rf build/meson_$(1)/oolite.app/AddOns/Basic-debug.oxp - cp -rf DebugOXP/Debug.oxp build/meson_$(1)/oolite.app/AddOns/Basic-debug.oxp -endef - -## -## Development Targets -## - -.PHONY: release -release: ## Build a test release executable - $(call meson_build,-Ddebug=false -Dstrip_bin=true -Db_lto=true,release) - $(call sync_debug_oxp,release) - -.PHONY: release-deployment -release-deployment: ## Build a release deployment executable - $(call meson_build,-Ddeployment_release_configuration=true -Ddebug=false -Dstrip_bin=true -Db_lto=true,deployment) - -.PHONY: release-snapshot -release-snapshot: ## Build a snapshot release executable - $(call meson_build,-Dsnapshot_build=true -Ddebug=false -Dstrip_bin=false,snapshot) - $(call sync_debug_oxp,snapshot) - -.PHONY: debug -debug: ## Build a debug executable - $(call meson_build,-Ddebug=true -Dstrip_bin=false,debug) - $(call sync_debug_oxp,debug) - -.PHONY: test -test: release-snapshot ## Run test suite - tests/run_test.sh - -.PHONY: clean -clean: ## Remove all generated build artifacts - rm -rf build/meson_* - -.PHONY: all -all: release release-deployment release-snapshot debug ## Build all standard development targets - -.PHONY: remake -remake: clean all - -## -## Packaging Targets -## - -.PHONY: pkg-flatpak -pkg-flatpak: ## Package a Flatpak application - ./installers/flatpak/create_flatpak.sh - -.PHONY: pkg-appimage -pkg-appimage: release ## Package a test release AppImage - installers/appimage/create_appimage.sh meson_release/oolite.app "test" - -.PHONY: pkg-appimage-deployment -pkg-appimage-deployment: release-deployment ## Package a deployment AppImage - installers/appimage/create_appimage.sh meson_deployment/oolite.app - -.PHONY: pkg-appimage-snapshot -pkg-appimage-snapshot: release-snapshot ## Package a snapshot AppImage - installers/appimage/create_appimage.sh meson_snapshot/oolite.app "dev" - -.PHONY: pkg-win -pkg-win: release ## Package a Windows NSIS test release installer - installers/win32/create_nsis.sh meson_release/oolite.app "test" - -.PHONY: pkg-win-deployment -pkg-win-deployment: release-deployment ## Package a Windows NSIS deployment installer - installers/win32/create_nsis.sh meson_deployment/oolite.app - -.PHONY: pkg-win-snapshot -pkg-win-snapshot: release-snapshot ## Package a Windows NSIS snapshot installer - installers/win32/create_nsis.sh meson_snapshot/oolite.app "dev" diff --git a/README.md b/README.md index 44a3ba468..642ccb527 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ where XXX is a version number. Many Linux package managers support Flatpak so yo double click the downloaded file to install it. The AppImage is named `Oolite_XXX-x86_64.AppImage` where XXX is a version number. Download this -file to where you would like it stored, make it executable and run, for example by typing +file to where you would like it stored, ./mk.sh it executable and run, for example by typing ```bash chmod +x Oolite_XXX-x86_64.AppImage @@ -122,54 +122,81 @@ default, but you can supply a further argument to specify an alternative like do ### Building Oolite -Next run this in your Bash or MSYS2 prompt to build Oolite: +The underlying build system is Meson, but it is recommended to build via the mk.sh script which also allow you to pass +meson setup, compile, configure and install flags. Type the following for help: ```bash -ShellScripts/common/build_oolite.sh release +./mk.sh help ``` -The completed build (executable and games files) can be found in the oolite.app directory. +Oolite has various build types: -Subsequently, you can clean and build as follows: +- **"dev"**: Keeps debug symbols in the binary. +- **"deployment"**: Intended for production builds. Removes debug symbols from the binary, but makes them available in + a separate symbols file. +- **"test"**: Used for test releases; supports the debug console, which expansion developers use to debug their OXPs. + Removes debug symbols from the binary, but makes them available in a separate symbols file. + +You can run this in your Bash or MSYS2 prompt to build Oolite for development: ```bash -make clean -make release +./mk.sh build dev ``` -You can run a test from your Bash or MSYS2 prompt as follows: +Optionally you can pass `--setup-flags` and/or `--compile-flags` to pass specific options to meson. The completed build +(executable and games files) can be found in the `build/meson_dev/oolite.app` directory. + +build dev runs 2 actions which can be run independently: `setup dev` which runs meson setup and `compile dev` which runs +meson compile. + +If for some reason the build fails, you can try cleaning the build folder first, although meson should not usually +require this step: ```bash -make test +./mk.sh clean dev ``` -Other targets are release-deployment for a production release and release-snapshot for a debug release. +You can run a test of the development build that launches the game and takes a snapshot from your Bash or MSYS2 prompt +as follows: +```bash +./mk.sh test dev +``` +You can modify build options of the build directory (such as `--prefix`): -### Other Linux Make Targets +```bash +./mk.sh configure dev --configure-flags="" +``` -This target builds an AppImage for testing which can be found in build: +You can install the build folder: ```bash -make pkg-appimage +./mk.sh install dev ``` -The target pkg-appimage-deployment is the production release, while pkg-appimage-snapshot is for debugging. +Optionally you can pass `--install-flags` to pass specific options to meson. -This target builds a Flatpak which can be found in build: +### Other Linux ./mk.sh Actions + +This action builds an AppImage for development which can be found in the `build` folder: + +```bash +./mk.sh pkg-appimage dev +``` + +This action builds a Flatpak which can be found in the `build` folder: ```bash -make pkg-flatpak +./mk.sh pkg-flatpak deployment ``` -Although there is a top level Makefile, the underlying build system is Meson. You can run the deployment -build directly using Meson build commands like this: +### Other Windows ./mk.sh Actions + +This action builds a Windows NSIS installer for development which can be found in the `build` folder: ```bash -meson setup build/meson_deployment -Ddeployment_release_configuration=true -Ddebug=false -Dstrip_bin=true -Db_lto=true --native-file clang.ini --reconfigure -meson compile -C build/meson_deployment -meson install -C build/meson_deployment +./mk.sh pkg-win dev ``` ### Mac OS @@ -196,7 +223,7 @@ guide to the source tree. - **ShellScripts**: Scripts to build from source on Windows and Linux - **installers**: Files used to create various installers - **Resources**: Game assets and resource files for Mac and GNUstep application bundles -- **Schemata**: Plist schema files for the [OXP Verifier](http://wiki.alioth.net/index.php/OXP_howto#OXP_Verifier) + - **Schemata**: Plist schema files for the [OXP Verifier](http://wiki.alioth.net/index.php/OXP_howto#OXP_Verifier) - **src**: Objective-C and C sources, incuding header files - **Cocoa**: Files that are only compiled on Mac OS X - **Core**: Files that are compiled on all platforms diff --git a/ShellScripts/Linux/build_gnustep.sh b/ShellScripts/Linux/build_gnustep.sh index d98b1457f..c8771cc41 100755 --- a/ShellScripts/Linux/build_gnustep.sh +++ b/ShellScripts/Linux/build_gnustep.sh @@ -1,6 +1,6 @@ #!/bin/bash # Parameter one: "system", "home", or "build" (defaults to home). -# Parameter two: Escalate command (defaults to sudo for 'system'). +# Parameter two: escalate command (defaults to sudo for 'system'). run_script() { local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) @@ -9,7 +9,8 @@ run_script() { echo "Building GNUStep libraries" source dep_location_fn.sh - dep_location LIB_SUBDIR TARGET ESCALATE "gnustep" $1 $2 + local lib_subdir target escalate + dep_location lib_subdir target escalate "gnustep" $1 $2 mkdir -p ../../build @@ -52,7 +53,7 @@ run_script() { rm -rf build mkdir build cd build - if ! cmake -DCMAKE_INSTALL_PREFIX="$TARGET" -DCMAKE_INSTALL_LIBDIR="$LIB_SUBDIR" -DTESTS=on -DCMAKE_BUILD_TYPE=Release -DGNUSTEP_INSTALL_TYPE=NONE -DEMBEDDED_BLOCKS_RUNTIME=ON -DOLDABI_COMPAT=OFF ../; then + if ! cmake -DCMAKE_INSTALL_PREFIX="$target" -DCMAKE_INSTALL_LIBDIR="$lib_subdir" -DTESTS=on -DCMAKE_BUILD_TYPE=Release -DGNUSTEP_INSTALL_TYPE=NONE -DEMBEDDED_BLOCKS_RUNTIME=ON -DOLDABI_COMPAT=OFF ../; then echo "❌ libobjc2 cmake configure failed!" >&2 return 1 fi @@ -61,29 +62,29 @@ run_script() { echo "❌ libobjc2 cmake build failed!" >&2 return 1 fi - $ESCALATE cmake --install . + $escalate cmake --install . cd ../.. cd tools-make make clean - local lib_dir="$TARGET/$LIB_SUBDIR" - export CPPFLAGS="-I$TARGET/include" + local lib_dir="$target/$lib_subdir" + export CPPFLAGS="-I$target/include" export LDFLAGS="-L$lib_dir" - if ! ./configure --prefix="$TARGET" --with-library-combo=ng-gnu-gnu --with-runtime-abi=gnustep-2.2 "--with-libdir=$LIB_SUBDIR"; then + if ! ./configure --prefix="$target" --with-library-combo=ng-gnu-gnu --with-runtime-abi=gnustep-2.2 "--with-libdir=$lib_subdir"; then echo "❌ tools-make configure failed!" >&2 return 1 fi make - $ESCALATE make install + $escalate make install cd .. cd libs-base make clean export LD_LIBRARY_PATH="$lib_dir:$LD_LIBRARY_PATH" - source "$TARGET/share/GNUstep/Makefiles/GNUstep.sh" + source "$target/share/GNUstep/Makefiles/GNUstep.sh" if ! ./configure; then echo "❌ libs-base configure failed!" >&2 return 1 @@ -92,7 +93,7 @@ run_script() { echo "❌ libs-base make failed!" >&2 return 1 fi - $ESCALATE make install + $escalate make install popd } diff --git a/ShellScripts/Linux/install_freedesktop_fn.sh b/ShellScripts/Linux/install_freedesktop_fn.sh deleted file mode 100644 index b3a66a81c..000000000 --- a/ShellScripts/Linux/install_freedesktop_fn.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -x -# -# Installs the manifest and injects version number -# -# Requires environment variables: -# VERSION -# APP_DATE -# - -echo "I am install_freedesktop_fn.sh $@" -printenv | sort - -install_freedesktop() { - # Install metainfo (eg. for FlatHub and AppImageHub) - # $1: oolite.app directory path (source) - # $2: app folder (destination) - # $3: debug symbol folder - # $4: appdata or metainfo - - local err_msg="❌ Error: Failed to" - - local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) - pushd "$script_dir" - - source ../common/get_version.sh - - echo "Installing metainfo to to $2" - - local appbin="$2/bin" - local appshr="$2/share" - - # Install binaries and scripts - install -D "$1/oolite" "$appbin/oolite" || { echo "$err_msg install oolite binary" >&2; return 1; } - if [[ -f "$1/oolite.debug" ]]; then - install -D "$1/oolite.debug" "$2/$3/oolite.debug" || { echo "$err_msg install oolite debug symbols" >&2; return 1; } - fi - install -D "$1/run_oolite.sh" "$appbin/run_oolite.sh" || { echo "$err_msg install run_oolite.sh" >&2; return 1; } - - # Resources copy - local resourcesdir="$appshr/oolite/Resources" - mkdir -p "$resourcesdir" - cp -rf "$1/Resources/." "$resourcesdir/" || { echo "$err_msg copy Resources folder" >&2; return 1; } - - # AddOns copy if folder exists in oolite.app - if [ -d "$1/AddOns" ]; then - local addonsdir="$appshr/oolite/AddOns" - mkdir -p "$addonsdir" - cp -rf "$1/AddOns/." "$addonsdir/" || { echo "$err_msg copy AddOns folder" >&2; return 1; } - fi - - rm -f "$resourcesdir/GNUstep.conf.orig" - install -D "GNUstep.conf.template" "$resourcesdir/GNUstep.conf.template" || { echo "$err_msg GNUstep template" >&2; return 1; } - - local app_metainfo="$appshr/metainfo/space.oolite.Oolite.$4.xml" - install -D ../../installers/FreeDesktop/space.oolite.Oolite.metainfo.xml.template "$app_metainfo" || { echo "$err_msg metainfo template" >&2; return 1; } - - sed -i "s/@VER@/${VER_FULL}/g" "$app_metainfo" - sed -i "s/@DATE@/${APP_DATE}/g" "$app_metainfo" - - echo =========================================== - echo Our manifest looks like this: - cat "$app_metainfo" - echo =========================================== - - # Desktop and Icon - install -D ../../installers/FreeDesktop/space.oolite.Oolite.desktop "$appshr/applications/space.oolite.Oolite.desktop" || { echo "$err_msg desktop file" >&2; return 1; } - - install -D "$1/Resources/Textures/oolite-logo1.png" "$appshr/icons/hicolor/256x256/apps/space.oolite.Oolite.png" || { echo "$err_msg icon file" >&2; return 1; } - - popd -} \ No newline at end of file diff --git a/ShellScripts/Linux/install_gitversion_fn.sh b/ShellScripts/Linux/install_gitversion_fn.sh new file mode 100644 index 000000000..62d761cb2 --- /dev/null +++ b/ShellScripts/Linux/install_gitversion_fn.sh @@ -0,0 +1,23 @@ +install_gitversion() { + local outputdir="$1" + + # If current user ID is NOT 0 (root) + if [[ $EUID -ne 0 ]]; then + echo "This script requires root to install dependencies. Rerun and escalate privileges (eg. sudo ...)" + return 1 + fi + + local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + pushd "$script_dir" + + source ../common/download_github_release_fn.sh + + local gitversion_tgz + download_github_release gitversion_tgz "GitTools" "GitVersion" "linux-x64" "$outputdir" + tar xfz ${gitversion_tgz} --directory "$outputdir" + chmod +x "$outputdir/gitversion" + mv "$outputdir/gitversion" /usr/local/bin/gitversion + rm -f ${gitversion_tgz} + + popd +} \ No newline at end of file diff --git a/ShellScripts/Linux/install_mozilla_js.sh b/ShellScripts/Linux/install_mozilla_js.sh index be51a2dea..192e38a95 100755 --- a/ShellScripts/Linux/install_mozilla_js.sh +++ b/ShellScripts/Linux/install_mozilla_js.sh @@ -1,19 +1,20 @@ #!/bin/bash # Parameter one: "system", "home", or "build" (defaults to home). -# Parameter two: Escalate command (defaults to sudo for 'system'). +# Parameter two: escalate command (defaults to sudo for 'system'). run_script() { # Get the directory where the script is located local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) source "$script_dir/dep_location_fn.sh" - dep_location LIB_SUBDIR TARGET ESCALATE "mozilla_js" $1 $2 + local lib_subdir target escalate + dep_location lib_subdir target escalate "mozilla_js" $1 $2 # The URL to your specific GitHub release asset local release_url="https://github.com/OoliteProject/mozillajs-linux/releases/download/0.0.1/mozilla-js-static-lib.tar.gz" - echo "Installing Mozilla JS static library to $TARGET" - [[ -n "$ESCALATE" ]] && echo "Using escalation: $ESCALATE" + echo "Installing Mozilla JS static library to $target" + [[ -n "$escalate" ]] && echo "Using escalation: $escalate" # Download and extract # Curl downloads as current user, Tar extracts using escalation @@ -32,12 +33,12 @@ run_script() { fi # Move headers to include - if ! $ESCALATE cp -r "$temp_staging/include/"* "$TARGET/include/"; then + if ! $escalate cp -r "$temp_staging/include/"* "$target/include/"; then echo "❌ Mozilla JS library header install failed!" >&2 return 1 fi # Move libs from 'lib' in tarball to 'lib64' on system - if ! $ESCALATE cp -r "$temp_staging/lib/"* "$TARGET/$LIB_SUBDIR/"; then + if ! $escalate cp -r "$temp_staging/lib/"* "$target/$lib_subdir/"; then echo "❌ Mozilla JS library lib install failed!" >&2 return 1 fi diff --git a/ShellScripts/Linux/install_package_fn.sh b/ShellScripts/Linux/install_package_fn.sh index affdaa29e..476ad8a43 100644 --- a/ShellScripts/Linux/install_package_fn.sh +++ b/ShellScripts/Linux/install_package_fn.sh @@ -15,7 +15,7 @@ install_package() { "base-devel") case "$CURRENT_DISTRO" in debian) pkg_name="build-essential" ;; - redhat) pkg_name="gcc gcc-c++ make" ;; + redhat) pkg_name="gcc gcc-c++" ;; arch) pkg_name="base-devel" ;; esac ;; diff --git a/ShellScripts/Linux/install_packages_root.sh b/ShellScripts/Linux/install_packages_root.sh index 5d3672c79..ddd9a31a5 100755 --- a/ShellScripts/Linux/install_packages_root.sh +++ b/ShellScripts/Linux/install_packages_root.sh @@ -14,9 +14,8 @@ run_script() { local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" - source ../common/download_github_fn.sh - - source ./install_package_fn.sh + source install_gitversion_fn.sh + source install_package_fn.sh if ! install_package base-devel; then return 1 @@ -101,12 +100,7 @@ run_script() { # install gitversion local outputdir="../../build" mkdir -p "$outputdir" - download_latest_release gitversion_tgz "GitTools" "GitVersion" "linux-x64" "$outputdir" - tar xfz ${gitversion_tgz} --directory "$outputdir" - chmod +x "$outputdir/gitversion" - mv "$outputdir/gitversion" /usr/local/bin/gitversion - rm -f ${gitversion_tgz} - + install_gitversion "$outputdir" popd } diff --git a/ShellScripts/Linux/os_detection.sh b/ShellScripts/Linux/os_detection.sh index 20e62ab61..8dc20794e 100644 --- a/ShellScripts/Linux/os_detection.sh +++ b/ShellScripts/Linux/os_detection.sh @@ -5,7 +5,11 @@ if [ -f /etc/os-release ]; then . /etc/os-release - OS_FAMILY="${ID} ${ID_LIKE}" + if [[ -v ID_LIKE ]]; then + OS_FAMILY="${ID} ${ID_LIKE}" + else + OS_FAMILY="${ID}" + fi else echo "❌ /etc/os-release not found - cannot detect OS!" >&2 exit 1 diff --git a/ShellScripts/Windows/install_deps.sh b/ShellScripts/Windows/install_deps.sh index ce6669d84..f9cc4677b 100755 --- a/ShellScripts/Windows/install_deps.sh +++ b/ShellScripts/Windows/install_deps.sh @@ -35,7 +35,7 @@ run_script() { local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" - source ../common/download_github_fn.sh + source ../common/download_github_release_fn.sh local oolite_deps_url="https://api.github.com/repos/OoliteProject/oolite_windeps_build/releases/latest" @@ -47,7 +47,6 @@ run_script() { pacboy -S jq --noconfirm pacman -S unzip --noconfirm pacboy -S python-pip --noconfirm - pacman -S make --noconfirm pacboy -S meson --noconfirm pacboy -S ninja --noconfirm pacboy -S nsis --noconfirm @@ -59,16 +58,17 @@ run_script() { pacboy -S mesa --noconfirm pacboy -S sdl3 --noconfirm + mkdir -p ../../build/packages cd ../../build # install gitversion + local gitversion_zip local outputdir="." - download_latest_release gitversion_zip "GitTools" "GitVersion" "win-x64" "$outputdir" + download_github_release gitversion_zip "GitTools" "GitVersion" "win-x64" "$outputdir" unzip -o ${gitversion_zip} -d "$outputdir" chmod +x "$outputdir/gitversion.exe" mv "$outputdir/gitversion.exe" "$MINGW_PREFIX/bin/gitversion.exe" rm -f ${gitversion_zip} - mkdir -p packages cd packages curl -s "$oolite_deps_url" | \ grep -oP '"browser_download_url": "\K[^"]+' | \ diff --git a/ShellScripts/common/build_oolite.sh b/ShellScripts/common/build_oolite.sh deleted file mode 100755 index b68fc19bc..000000000 --- a/ShellScripts/common/build_oolite.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# No parameters: build target = release -# One parameter: build target - -run_script() { - local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) - pushd "$script_dir" - - cd ../.. - - local target - if [[ -z "$1" ]]; then - target=release - else - target=$1 - fi - - make clean - if ! make $target; then - echo "❌ Oolite build failed!" >&2 - return 1 - fi - echo "✅ Oolite build completed successfully" - - popd -} - -run_script "$@" -status=$? - - -# Exit only if not sourced -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - exit $status -fi \ No newline at end of file diff --git a/ShellScripts/common/download_github_fn.sh b/ShellScripts/common/download_github_release_fn.sh similarity index 92% rename from ShellScripts/common/download_github_fn.sh rename to ShellScripts/common/download_github_release_fn.sh index 6b0b95ecd..7abe8c69f 100755 --- a/ShellScripts/common/download_github_fn.sh +++ b/ShellScripts/common/download_github_release_fn.sh @@ -1,7 +1,7 @@ #!/bin/bash -download_latest_release() { - local -n downloaded_file="$1" +download_github_release() { + local -n _downloaded_file="$1" local owner="$2" local repository="$3" local filter="$4" @@ -39,5 +39,5 @@ download_latest_release() { echo "Downloading latest release: ${filename}..." >&2 curl -L -O --output-dir "${outputdir}" "${download_url}" - downloaded_file="${outputdir}/${filename}" + _downloaded_file="${outputdir}/${filename}" } \ No newline at end of file diff --git a/ShellScripts/common/generate_manifest_fn.sh b/ShellScripts/common/generate_manifest_fn.sh index 2fe7a426a..b6e5428ed 100755 --- a/ShellScripts/common/generate_manifest_fn.sh +++ b/ShellScripts/common/generate_manifest_fn.sh @@ -1,17 +1,12 @@ generate_manifest() { - # Locate the xcconfig file - local oolite_version_file="src/Cocoa/oolite-version.xcconfig" - - if [[ ! -f "$oolite_version_file" ]]; then - echo "❌ $oolite_version_file not found!" >&2 - popd > /dev/null - return 1 - fi - - # Extract definition of $OOLITE_VERSION from the xcconfig - source "$oolite_version_file" - + local output_file="$1" + local deployment_release="$2" + local ver_full="$3" + local ver_quad="$4" + local ver_githash="$5" + local build_time="$6" source ShellScripts/common/get_gitremote_fn.sh + local git_remote get_gitremote git_remote # Redirect the entire block output into the manifest_output file @@ -20,21 +15,24 @@ generate_manifest() { echo " title = \"Oolite core\";" echo " identifier = \"org.oolite.oolite\";" echo " " - echo " version = \"$VER_FULL\";" + echo " version = \"$ver_full\";" + echo " version_quad = \"$ver_quad\";" + echo " git_commit_hash = \"$ver_githash\";" + echo " build_time = \"$build_time\";" echo " git_remote_url = \"$git_remote\";" - echo " git_commit_hash = \"$VER_GITHASH\";" - if [[ "$DEPLOYMENT_RELEASE_CONFIGURATION" == "yes" ]]; then + if [[ "$deployment_release" == "yes" ]]; then echo " debug_functionality_support = no;" else echo " debug_functionality_support = yes;" fi - - echo " required_oolite_version = \"$OOLITE_VERSION\";" + IFS='.' read -r major minor rest <<< "$ver_full" + local ver_short="$major.$minor" + echo " required_oolite_version = \"${ver_short}\";" echo " " echo " license = \"GPL 2+ / CC-BY-NC-SA 3.0 - see LICENSE.md for details\";" echo " author = \"Giles Williams, Jens Ayton and contributors\";" echo " information_url = \"https://oolite.space/\";" echo "}" - } > "$1" -} \ No newline at end of file + } > "$output_file" +} diff --git a/ShellScripts/common/get_build_date_fn.sh b/ShellScripts/common/get_build_date_fn.sh new file mode 100755 index 000000000..4413809d2 --- /dev/null +++ b/ShellScripts/common/get_build_date_fn.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Calculates the Oolite build date +# + +SUITE_PARENT=$(basename "${BASH_SOURCE[1]}") # Get the name of the script that is sourcing this file +ALLOWED_SCRIPT="get_version.sh" # Define the ONLY script allowed to source this +if [[ "$SUITE_PARENT" != "$ALLOWED_SCRIPT" ]]; then + echo "❌ This file can only be sourced by $ALLOWED_SCRIPT!" >&2 + unset SUITE_PARENT ALLOWED_SCRIPT + return 1 2>/dev/null || exit 1 +fi +unset SUITE_PARENT ALLOWED_SCRIPT + +get_build_date() { + local -n _cpp_date="$1" + local -n _app_date="$2" + local -n _buildtime="$3" + local -n _builder="$4" + local buildtime="$5" + + + if [[ -z "$buildtime" ]]; then + local getversion_timestamp=$(git log -1 --format=%ct) + _buildtime=$(date -u -d "@$getversion_timestamp" "+%Y.%m.%d %H:%M") + else + _buildtime="$buildtime" + fi + + local clean_date="${_buildtime//./-}" + _cpp_date=$(date -u -d "$clean_date" +"%b%e %Y") + _app_date=$(date -u -d "$clean_date" +"%Y-%m-%d") + + if [[ "$GITHUB_REPOSITORY" == "OoliteProject/oolite" ]]; then + _builder="OoliteProject" + else + _builder="unknown" + fi +} \ No newline at end of file diff --git a/ShellScripts/common/get_gitremote_fn.sh b/ShellScripts/common/get_gitremote_fn.sh index 932a7d8b5..0694be38f 100644 --- a/ShellScripts/common/get_gitremote_fn.sh +++ b/ShellScripts/common/get_gitremote_fn.sh @@ -1,6 +1,6 @@ get_gitremote() { # Accept a variable name as the first argument to use as a nameref return - local -n final_url=$1 + local -n _final_url=$1 local raw_url resolved_git_dir upstream_url @@ -21,12 +21,12 @@ get_gitremote() { # If we successfully found an upstream URL, use it. if [[ -n "$upstream_url" ]]; then - final_url="$upstream_url" + _final_url="$upstream_url" else - final_url="UNKNOWN" + _final_url="UNKNOWN" fi else # It's already a standard web URL (GitHub, GitLab, etc.) - final_url="$raw_url" + _final_url="$raw_url" fi } \ No newline at end of file diff --git a/ShellScripts/common/get_version.sh b/ShellScripts/common/get_version.sh index 66f241dac..f774abcfa 100755 --- a/ShellScripts/common/get_version.sh +++ b/ShellScripts/common/get_version.sh @@ -1,58 +1,127 @@ #!/bin/bash # -# Calculates the Oolite version number if not passed via env variables. Output goes to stdout. +# Calculates the Oolite version number and build dates # -SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) -pushd "$SCRIPT_DIR" > /dev/null -mkdir -p ../../build -cd ../../build - -# Timestamp of last commit/push -if [[ -z "${GETVERSION_TIMESTAMP}" ]]; then - # Run timestamp exactly once and export it for any subsequent child scripts - export GETVERSION_TIMESTAMP=$(git log -1 --format=%ct) +if [[ -v MINGW_PREFIX ]]; then + WIN_PID=$(ps -p $$ | awk 'NR>1 {print $4}') + PARENT_PROCESS=$(powershell.exe -Command " + \$parentId = (gwmi Win32_Process -Filter 'ProcessId = $WIN_PID').ParentProcessId + if (\$parentId) { + Write-Output (gwmi Win32_Process -Filter \"ProcessId = \$parentId\").Name + } + " 2>/dev/null | tr -d '\r') + if [ "$PARENT_PROCESS" = "python.exe" ] && ps | grep -q "meson"; then + PARENT_PROCESS="meson" + fi +else + PARENT_PROCESS=$(ps -p $PPID -o comm= 2>/dev/null || true) fi -# Date conversions use UTC for consistency -# Convert to __DATE__ format (e.g., Feb 20 2026) -CPP_DATE=$(date -u -d "@$GETVERSION_TIMESTAMP" +"%b %e %Y") -# Convert to YYYY-MM-DD -APP_DATE=$(date -u -d "@$GETVERSION_TIMESTAMP" +"%Y-%m-%d") -# Convert to YYMMDD format (e.g., 260313) -VER_DATE=$(date -u -d "@$GETVERSION_TIMESTAMP" +"%y%m%d") -# Convert to YYYY.MM.DD HH:MM format (e.g., 2026.06.21 07:56) -BUILDTIME=$(date -u -d "@$GETVERSION_TIMESTAMP" "+%Y.%m.%d %H:%M") - -if [[ -z "${VER_FULL}" ]]; then - if [[ -z "${GITVERSION_JSON}" ]]; then - # Run GitVersion exactly once and export it for any subsequent child scripts - if ! command -v gitversion &> /dev/null; then - echo "❌ gitversion binary not found!" >&2 - exit 1 +if [[ "$PARENT_PROCESS" != "meson" ]] || [[ -z "$MESON_BUILD_ROOT" ]]; then + SUITE_PARENT=$(basename "${BASH_SOURCE[1]}") # Get the name of the script that is sourcing this file + ALLOWED_SCRIPT="create_flatpak_fn.sh" # Define the ONLY script allowed to source this + if [[ "$SUITE_PARENT" != "$ALLOWED_SCRIPT" ]]; then + echo "❌ Parent process is $PARENT_PROCESS, Bash parent is $SUITE_PARENT. This file can only be called by meson or sourced by $ALLOWED_SCRIPT!" >&2 + unset SUITE_PARENT ALLOWED_SCRIPT + return 1 2>/dev/null || exit 1 + fi + unset SUITE_PARENT ALLOWED_SCRIPT +fi + + +run_script() { + local build_dir="$1" # Input string arguments + + if [[ -z "$build_dir" ]]; then + echo "❌ build_dir argument is required!" >&2 + return 1 + fi + + source "ShellScripts/common/get_build_date_fn.sh" + local output_ver_githash=$(git rev-parse --short=7 HEAD) + local dirty_suffix="" + git diff --quiet || dirty_suffix="-dirty" + local lookup_hash="${output_ver_githash}${dirty_suffix}" + local output_ver_full="" + local output_buildtime="" + local version_file="$build_dir/.meson_version" + if [[ -z "${VER_FULL-}" ]]; then + if [[ -f "$version_file" ]]; then # Check if cache exists and has a matching hash context + local githash ver_full ver_quad ver_gitrev cpp_date app_date buildtime builder + source "$version_file" 2>/dev/null + if [[ "$ver_githash" == "$lookup_hash" ]]; then + echo "$ver_full" + return 0 + fi fi - export GITVERSION_JSON=$(gitversion) + else + output_ver_full="$VER_FULL" fi - VER_MAJ=$(echo "$GITVERSION_JSON" | jq -r '.Major') - VER_MIN=$(echo "$GITVERSION_JSON" | jq -r '.Minor') - VER_REV=$(echo "$GITVERSION_JSON" | jq -r '.Patch') - if [[ "" == "$VER_REV" ]]; then - VER_REV="0" + + if [[ -z "$output_ver_full" ]]; then + local exact_tag="" # Check for an exact Git tag first on a clean tree + if [[ -z "$dirty_suffix" ]]; then + exact_tag=$(git describe --tags --exact-match HEAD 2>/dev/null) + fi + if [[ -n "$exact_tag" ]]; then + output_ver_full="$exact_tag" + else + if ! command -v gitversion &> /dev/null; then # exact tag didn't hit, use gitversion for ver_full + echo "❌ gitversion binary not found!" >&2 + exit 1 + fi + local gitversion_json=$(gitversion) # Run gitversion and get json output + local ver_semver=$(echo "$gitversion_json" | jq -r '.SemVer') + if [[ -z "$dirty_suffix" ]]; then + output_ver_full="$ver_semver" + else + local ver_uncommitted=$(echo "$gitversion_json" | jq -r '.UncommittedChanges') + output_ver_full="${ver_semver}+dirty.${ver_uncommitted}" + fi + fi fi - VER_DIST=$(echo "$GITVERSION_JSON" | jq -r '.VersionSourceDistance') - VER_SEMVER=$(echo "$GITVERSION_JSON" | jq -r '.SemVer') - VER_UNCOMMITTED=$(echo "$GITVERSION_JSON" | jq -r '.UncommittedChanges') - if git diff --quiet; then - VER_FULL=$VER_SEMVER + local clean_ver="${output_ver_full#v}" # Strip any leading 'v', prerelease tags (-alpha), or build metadata (+) + clean_ver="${clean_ver%%-*}" # Example: "v1.91.0-alpha.1+dirty.3" -> "1.91.0" + clean_ver="${clean_ver%%+*}" + local ver_maj=$(echo "$clean_ver" | cut -d. -f1) # Parse out Major, Minor, Patch using standard dot delimiters + local ver_min=$(echo "$clean_ver" | cut -d. -f2) + local ver_rev=$(echo "$clean_ver" | cut -d. -f3) + [[ -z "$ver_rev" ]] && ver_rev="0" + + if [[ -z "$dirty_suffix" ]]; then # Use git for other metrics for clean repository + local closest_tag=$(git describe --tags --abbrev=0 2>/dev/null) # Derive distance from closest Git tag + local ver_dist="0" + if [[ -n "$closest_tag" ]]; then + ver_dist=$(git rev-list --count "${closest_tag}..HEAD") + else + ver_dist=$(git rev-list --count HEAD) + fi + output_ver_quad="$ver_maj.$ver_min.$ver_rev.$ver_dist" else - VER_FULL="${VER_SEMVER}+dirty.${VER_UNCOMMITTED}" + local ver_uncommitted=$(git status --porcelain 2>/dev/null | wc -l) # Dirty repo: get uncommitted file count + output_ver_quad="$ver_maj.$ver_min.$ver_rev.$ver_uncommitted" fi - VER_NSIS="$VER_MAJ.$VER_MIN.$VER_REV.$VER_DIST" - VER_GITREV=$(git rev-list --count HEAD) - VER_GITHASH=$(git rev-parse --short=7 HEAD) -fi + local output_cpp_date output_app_date output_builder + get_build_date output_cpp_date output_app_date output_buildtime output_builder "${BUILDTIME-}" + + cat << EOF > "$version_file" # Write new values to the hidden cache file +ver_githash="$lookup_hash" +ver_full="$output_ver_full" +ver_quad="$output_ver_quad" +cpp_date="$output_cpp_date" +app_date="$output_app_date" +buildtime="$output_buildtime" +builder="$output_builder" +EOF -echo "$VER_FULL" -popd > /dev/null + echo "$output_ver_full" +} + +# Exit only if not sourced +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_script "$@" + exit $? +fi diff --git a/ShellScripts/common/install.sh b/ShellScripts/common/install.sh index 2b1dd59b6..3f4e3e0fd 100755 --- a/ShellScripts/common/install.sh +++ b/ShellScripts/common/install.sh @@ -2,17 +2,28 @@ # Processes Oolite data files after compilation run_script() { + local stageprogpath="$1" + local bindir="$2" + local datadir="$3" + local host_os="$4" + local deployment_release="$5" + local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" > /dev/null cd ../.. - set -x - local appname=$(basename "$STAGEPROGPATH") - local progdir=$(dirname "$STAGEPROGPATH") - local installdir="${INSTALLDIR:-$MESON_INSTALL_DESTDIR_PREFIX}" - local fullbindir="$installdir/$BINDIR" - local fulldatadir="$installdir/$DATADIR/oolite" # don't use appname here as Obj-C has oolite specifically + set -x + local appname=$(basename "$stageprogpath") + local progdir=$(dirname "$stageprogpath") + local installdir="$MESON_INSTALL_DESTDIR_PREFIX" + local fullbindir="$installdir/$bindir" + rm -f "$fullbindir/oolite" + if [[ "$host_os" == "linux" ]]; then + rm -f "$fullbindir/run_oolite.sh" + fi + local fulldatadir="$installdir/$datadir/oolite" # don't use appname here as Obj-C has oolite specifically + rm -rf "$fulldatadir" local progpath="$fullbindir/$appname" if ! mkdir -p "$fullbindir"; then echo "❌ Failed to create folder '$fullbindir'!" >&2 @@ -22,17 +33,26 @@ run_script() { echo "❌ Failed to create folder '$fulldatadir'!" >&2 return 1 fi - if ! cp -fu "$STAGEPROGPATH" "$progpath"; then - echo "❌ Failed to copy '$STAGEPROGPATH' to '$progpath'!" >&2 + if ! cp -fu "$stageprogpath" "$progpath"; then + echo "❌ Failed to copy '$stageprogpath' to '$progpath'!" >&2 return 1 - fi - if [[ "$HOST_OS" == "linux" ]]; then + fi + if [[ "$host_os" == "linux" ]]; then local run_oolite_src="$progdir/run_oolite.sh" local run_oolite_dst="$fullbindir/run_oolite.sh" if ! cp -fu "$run_oolite_src" "$run_oolite_dst"; then echo "❌ Failed to copy '$run_oolite_src' to '$run_oolite_dst'!" >&2 return 1 fi + local debugname="$appname.debug" + local oolite_debug_src="$progdir/$debugname" + if [[ -f "$oolite_debug_src" ]]; then + local oolite_debug_dst="$fullbindir/$debugname" + if ! cp -fu "$oolite_debug_src" "$oolite_debug_dst"; then + echo "❌ Failed to copy '$oolite_debug_src' to '$oolite_debug_dst'!" >&2 + return 1 + fi + fi fi local resources_src="$progdir/Resources/." local resources_dst="$fulldatadir/Resources" diff --git a/ShellScripts/common/parse_manifest_fn.sh b/ShellScripts/common/parse_manifest_fn.sh new file mode 100644 index 000000000..8f01e4ff1 --- /dev/null +++ b/ShellScripts/common/parse_manifest_fn.sh @@ -0,0 +1,25 @@ +parse_manifest() { + local -n _ver_full="$1" + local -n _ver_quad="$2" + local -n _githash="$3" + local -n _buildtime="$4" + local -n _app_date="$5" + local input_file="$6" + + if [[ ! -f "$input_file" ]]; then # Ensure the manifest file exists before parsing + echo "❌ Manifest file '$input_file' not found." >&2 + return 1 + fi + + get_manifest_value() { # Helper function to extract a string inside quotes for a given key + local key="$1" + grep -E "^[[:space:]]*${key}[[:space:]]*=" "$input_file" | sed -E 's/.*"[[:space:]]*([^"]*)[[:space:]]*".*/\1/' + } + + _ver_full=$(get_manifest_value "version") + _ver_quad=$(get_manifest_value "version_quad") + _githash=$(get_manifest_value "git_commit_hash") + _buildtime=$(get_manifest_value "build_time") + local clean_date="${_buildtime//./-}" + _app_date=$(date -u -d "${clean_date:0:10}" +"%Y-%m-%d" 2>/dev/null || echo "") +} \ No newline at end of file diff --git a/ShellScripts/common/post_build.sh b/ShellScripts/common/post_build.sh index eed95d57d..cc6871a1d 100755 --- a/ShellScripts/common/post_build.sh +++ b/ShellScripts/common/post_build.sh @@ -2,6 +2,20 @@ # Processes Oolite data files after compilation run_script() { + local origprogpath="$1" + local progdir="$2" + local host_os="$3" + local debug="$4" + local deployment_release="$5" + local espeak="$6" + local strip_bin="$7" + local ver_full="$8" + local ver_quad="$9" + local ver_githash="${10}" + local buildtime="${11}" + local gnustep_folder="${12}" + local stamp_file="${13}" + local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" > /dev/null @@ -9,29 +23,34 @@ run_script() { cd ../.. set -x - local appname=$(basename "$ORIGPROGPATH") - local appdir=$(dirname "$ORIGPROGPATH") - local progpath="$PROGDIR/$appname" - mkdir -p "$PROGDIR/Resources" - - generate_manifest "$PROGDIR/Resources/manifest.plist" + local appname=$(basename "$origprogpath") + local appdir=$(dirname "$origprogpath") + local progpath="$progdir/$appname" + local resourcesdir="$progdir/Resources" + mkdir -p "$resourcesdir" - if [[ ! -f "$ORIGPROGPATH" ]]; then - echo "❌ 'Oolite binary at '$ORIGPROGPATH' does not exist!" >&2 + if [[ ! -f "$origprogpath" ]]; then + echo "❌ 'Oolite binary at '$origprogpath' does not exist!" >&2 return 1 fi - if ! cp -fu "$ORIGPROGPATH" "$progpath"; then - echo "❌ Failed to copy '$ORIGPROGPATH' to '$progpath'!" >&2 + if ! cp -fu "$origprogpath" "$progpath"; then + echo "❌ Failed to copy '$origprogpath' to '$progpath'!" >&2 return 1 fi - cp -fu "$ORIGPROGPATH" "$progpath" - cp -fu src/Cocoa/Info-Oolite.plist "$PROGDIR/Resources/Info-gnustep.plist" + generate_manifest "$resourcesdir/manifest.plist" "$deployment_release" "$ver_full" "$ver_quad" "$ver_githash" "$buildtime" + cp -fu src/Cocoa/Info-Oolite.plist "$resourcesdir/Info-gnustep.plist" + if [[ "$deployment_release" == "no" ]]; then + local addonsdir="$progdir/AddOns" + mkdir -p "$addonsdir" + rm -rf "$addonsdir/Basic-debug.oxp" + cp -rf DebugOXP/Debug.oxp "$addonsdir/Basic-debug.oxp" + fi # Voice Data - if [[ "$ESPEAK" == "yes" ]]; then - if [[ "$HOST_OS" == "windows" ]]; then + if [[ "$espeak" == "yes" ]]; then + if [[ "$host_os" == "windows" ]]; then # Windows espeak-ng-data - cp -rfu "$MINGW_PREFIX/share/espeak-ng-data" "$PROGDIR/Resources" + cp -rfu "$MINGW_PREFIX/share/espeak-ng-data" "$resourcesdir" else # Linux search paths for espeak-ng-data local SEARCH_PATHS=( @@ -44,7 +63,7 @@ run_script() { local path for path in "${SEARCH_PATHS[@]}"; do if [[ -d "$path" ]]; then - cp -rfu "$path" "$PROGDIR/Resources" + cp -rfu "$path" "$resourcesdir" found_data=true break fi @@ -59,19 +78,19 @@ run_script() { fi # Replace specific voices with Oolite-specific versions - rm -f "$PROGDIR/Resources/espeak-ng-data/voices/!v/f2" - rm -f "$PROGDIR/Resources/espeak-ng-data/voices/default" - cp -rfu Resources/. "$PROGDIR/Resources" - rm -f "$PROGDIR/Resources/AIReference.html" "$PROGDIR/Resources/*.icns" + rm -f "$resourcesdir/espeak-ng-data/voices/!v/f2" + rm -f "$resourcesdir/espeak-ng-data/voices/default" + cp -rfu Resources/. "$resourcesdir" + rm -f "$resourcesdir/AIReference.html" "$resourcesdir/*.icns" # Strip binary if requested - if [[ "$STRIP_BIN" == "yes" ]]; then - if [[ "$HOST_OS" == "windows" ]]; then + if [[ "$strip_bin" == "yes" ]]; then + if [[ "$host_os" == "windows" ]]; then # Windows: Standard GNU strip is safest for PE/COFF strip "$progpath" else # Linux - local debugpath="$PROGDIR/$appname.debug" + local debugpath="$progdir/$appname.debug" # Extract symbols to file objcopy --only-keep-debug "$progpath" "$debugpath" # Compress the debug sections in the symbol file @@ -81,34 +100,34 @@ run_script() { # Add the debug link objcopy --add-gnu-debuglink="$debugpath" "$progpath" fi - elif [[ "$HOST_OS" == "linux" ]]; then + elif [[ "$host_os" == "linux" ]]; then # Compress the debug sections in the binary objcopy --compress-debug-sections=zlib-gnu "$progpath" fi - if [[ "$HOST_OS" == "windows" ]]; then + if [[ "$host_os" == "windows" ]]; then # Determine and copy DLL dependencies local unix_prefix=$(cygpath -u "$MINGW_PREFIX") - ldd "$progpath" | grep "$unix_prefix" | awk '{print $3}' | xargs -I {} cp -rfu {} "$PROGDIR" + ldd "$progpath" | grep "$unix_prefix" | awk '{print $3}' | xargs -I {} cp -rfu {} "$progdir" else # Copy Linux-specific wrapper script - cp -fu ShellScripts/Linux/run_oolite.sh "$PROGDIR" - local gnustep_conf="$GNUSTEP_FOLDER/etc/GNUstep/GNUstep.conf" - if [ ! -f "$gnustep_conf" ] && [ "$GNUSTEP_FOLDER" = "/usr" ] && [ -f "/etc/GNUstep/GNUstep.conf" ]; then + cp -fu ShellScripts/Linux/run_oolite.sh "$progdir" + local gnustep_conf="$gnustep_folder/etc/GNUstep/GNUstep.conf" + if [ ! -f "$gnustep_conf" ] && [ "$gnustep_folder" = "/usr" ] && [ -f "/etc/GNUstep/GNUstep.conf" ]; then gnustep_conf="/etc/GNUstep/GNUstep.conf" fi - install -D "$gnustep_conf" "$PROGDIR/Resources/GNUstep.conf.orig" || { echo "$err_msg GNUstep config" >&2; return 1; } + install -D "$gnustep_conf" "$resourcesdir/GNUstep.conf.orig" || { echo "$err_msg GNUstep config" >&2; return 1; } # If we're using GNUstep libraries that aren't in a system folder copy them ldd "$progpath" | \ grep -E "libgnustep-base|libobjc\.so\." | \ grep -vE "^[[:space:]]*.*=>[[:space:]]*/(usr/(local/)?|lib(64)?/)" | \ awk '{print $3}' | \ - xargs -I {} cp -Lrfu {} "$PROGDIR/" + xargs -I {} cp -Lrfu {} "$progdir/" fi echo "✅ Oolite post-build completed successfully" - touch "$appdir/$STAMP_FILE" + touch "$appdir/$stamp_file" popd > /dev/null } @@ -118,4 +137,4 @@ status=$? # Exit only if not sourced if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then exit $status -fi \ No newline at end of file +fi diff --git a/ShellScripts/Linux/GNUstep.conf.template b/installers/FreeDesktop/GNUstep.conf.template similarity index 100% rename from ShellScripts/Linux/GNUstep.conf.template rename to installers/FreeDesktop/GNUstep.conf.template diff --git a/installers/FreeDesktop/install_freedesktop_fn.sh b/installers/FreeDesktop/install_freedesktop_fn.sh new file mode 100644 index 000000000..b6d11f959 --- /dev/null +++ b/installers/FreeDesktop/install_freedesktop_fn.sh @@ -0,0 +1,42 @@ +#!/bin/bash -x +# +# Installs the manifest and injects version number + + +install_freedesktop() { + local -n output_ver_full="$1" # Oolite version + local build_folder="$2" # oolite.app directory path (source) + local app_folder="$3" # app folder (destination) + local symbol_folder="$4" # debug symbol folder + local metainfo_suffix="$5" # can be appdata or metainfo + + local err_msg="❌ Error: Failed to install" + + source ../../ShellScripts/common/parse_manifest_fn.sh + + echo "Installing metainfo to $app_folder" + + local ver_quad githash buildtime app_date + parse_manifest output_ver_full ver_quad githash buildtime app_date "$build_folder/Resources/manifest.plist" + + local freedesktopdir="../../installers/FreeDesktop" + local appshr="$app_folder/share" + local resourcesdir="$appshr/oolite/Resources" + rm -f "$resourcesdir/GNUstep.conf.orig" + install -D "$freedesktopdir/GNUstep.conf.template" "$resourcesdir/GNUstep.conf.template" || { echo "$err_msg GNUstep template" >&2; return 1; } + + local app_metainfo="$appshr/metainfo/space.oolite.Oolite.$metainfo_suffix.xml" + install -D "$freedesktopdir/space.oolite.Oolite.metainfo.xml.template" "$app_metainfo" || { echo "$err_msg metainfo template" >&2; return 1; } + + sed -i "s/@VER@/${output_ver_full}/g" "$app_metainfo" + sed -i "s/@DATE@/${app_date}/g" "$app_metainfo" + + echo =========================================== + echo Our manifest looks like this: + cat "$app_metainfo" + echo =========================================== + + # Desktop and Icon + install -D "$freedesktopdir/space.oolite.Oolite.desktop" "$appshr/applications/space.oolite.Oolite.desktop" || { echo "$err_msg desktop file" >&2; return 1; } + install -D "$build_folder/Resources/Textures/oolite-logo1.png" "$appshr/icons/hicolor/256x256/apps/space.oolite.Oolite.png" || { echo "$err_msg icon file" >&2; return 1; } +} \ No newline at end of file diff --git a/installers/appimage/create_appimage.sh b/installers/appimage/create_appimage_fn.sh similarity index 76% rename from installers/appimage/create_appimage.sh rename to installers/appimage/create_appimage_fn.sh index e81c99d75..92a827287 100755 --- a/installers/appimage/create_appimage.sh +++ b/installers/appimage/create_appimage_fn.sh @@ -1,32 +1,24 @@ #!/bin/bash -x # # Creates the appimage. -# First parameter can be set to build type, typically one of "test", "dev" or omitted for release builds. -# -echo I am $0 $@ +create_appimage() { + local build_type="$1" # Typically one of "deployment", "test", "dev" + local build_folder="$2" # Build folder -run_script() { - # First parameter is a suffix for the build type eg. test, dev local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" + source ../FreeDesktop/install_freedesktop_fn.sh + source ../../ShellScripts/Linux/os_detection.sh - mkdir -p ../../build - cd ../../build - source ../ShellScripts/Linux/os_detection.sh - source ../ShellScripts/common/get_version.sh - source ../ShellScripts/Linux/install_freedesktop_fn.sh - + cd ../../build/appimage local arch=$(uname -m) local APPDIR="./oolite.AppDir" export APPDIR local appbin="$APPDIR/bin" local appshr="$APPDIR/share" - rm -rf "$APPDIR" - local abs_oolitedir=$(realpath -m "$1") - local abs_appdir=$(realpath -m "$APPDIR") - if ! install_freedesktop "$abs_oolitedir" "$abs_appdir" bin appdata; then + if ! install_freedesktop ver_full "../$build_folder" "$APPDIR" "bin" "appdata"; then return 1 fi @@ -44,10 +36,10 @@ run_script() { local DESKTOP="$appshr/applications/space.oolite.Oolite.desktop" export DESKTOP local suffix - if (( $# == 2 )); then - suffix="_${2}-${VER_FULL}" + if [[ "$build_type" != "deployment" ]]; then + suffix="_$build_type-$ver_full" else - suffix="-$VER_FULL" + suffix="-$ver_full" fi local OUTNAME="oolite${suffix}-${arch}.AppImage" export OUTNAME @@ -94,20 +86,10 @@ run_script() { fi echo "Creating AppImage $OUTNAME..." - if ! $appimagetool_bin "$abs_appdir" "$OUTNAME"; then + if ! $appimagetool_bin "$APPDIR" "../$OUTNAME"; then echo "❌ AppImage creation failed!" >&2 return 1 fi popd } - -run_script "$@" -status=$? - - -# Exit only if not sourced -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - exit $status -fi - diff --git a/installers/flatpak/create_flatpak.sh b/installers/flatpak/create_flatpak.sh deleted file mode 100755 index 0ded5d34b..000000000 --- a/installers/flatpak/create_flatpak.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash -x - -echo "I am $0 $@" - -run_script() { - # First parameter is a suffix for the build type eg. test, dev - local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) - pushd "$script_dir" - - cd ../.. - mkdir -p build - cd build - if ! command -v gitversion &> /dev/null; then - echo "Installing gitversion..." - source ../ShellScripts/common/download_github_fn.sh - local outputdir="." - download_latest_release gitversion_tgz "GitTools" "GitVersion" "linux-x64" "$outputdir" - tar xfz ${gitversion_tgz} --directory "$outputdir" - chmod +x "$outputdir/gitversion" - mkdir -p /usr/local/bin - mv "$outputdir/gitversion" /usr/local/bin/gitversion - rm -f ${gitversion_tgz} - fi - source ../ShellScripts/common/get_version.sh - - cp ../installers/flatpak/space.oolite.Oolite.* ./ - - mkdir -p shared-modules/glu - if ! curl -o shared-modules/glu/glu-9.json -L https://github.com/flathub/shared-modules/raw/refs/heads/master/glu/glu-9.json; then - echo "❌ Flatpak download of glu shared module failed!" >&2 - return 1 - fi - - local manifest="space.oolite.Oolite.yaml" - - local env_block="env:\n VER_FULL: \"$VER_FULL\"\n GITHUB_REPOSITORY: \"$GITHUB_REPOSITORY\"" - # Swap the comment - sed -i "s|#[[:space:]]*CI builds add an env block here|$env_block|g" "$manifest" || return 1 - - # check manifest - local lint_exceptions=$(mktemp /tmp/oolite-lint-XXXXXX.json) - cat < "$lint_exceptions" -{ - "space.oolite.Oolite": [ - "finish-args-has-dev-input" - ] -} -EOF - trap 'rm -f "$lint_exceptions"' RETURN EXIT - - if command -v flatpak-builder-lint >/dev/null 2>&1; then - if ! flatpak-builder-lint manifest "$manifest" --exceptions --user-exceptions="$lint_exceptions"; then - echo "❌ Flatpak manifest lint failed!" >&2 - cat "$manifest" - echo "❌ Flatpak manifest lint failed!" >&2 - return 1 - fi - else - echo "Native linter not found. Falling back to Flatpak container..." - if ! flatpak run --filesystem="$lint_exceptions" --command=flatpak-builder-lint org.flatpak.Builder manifest "$manifest" --exceptions --user-exceptions="$lint_exceptions"; then - echo "❌ Flatpak manifest lint failed!" >&2 - return 1 - fi - fi - - # 3. Clean up - rm -f "$lint_exceptions" - trap - RETURN EXIT - - echo "Creating Flatpak..." - if ! flatpak remote-add \ - --user \ - --if-not-exists \ - flathub https://flathub.org/repo/flathub.flatpakrepo; then - echo "❌ Flatpak adding Flathub remote failed!" >&2 - return 1 - fi - - local total_lines=$(wc -l < $manifest) - local start_line=$((total_lines - 3)) - sed -i "${start_line},\$d" $manifest - cat <> $manifest - - type: dir - path: ../ -EOF - - # show effective manifest - flatpak-builder --show-manifest $manifest - - if ! flatpak-builder \ - --user \ - --force-clean \ - --repo=repo \ - --install-deps-from=flathub \ - --disable-rofiles-fuse \ - build-dir \ - $manifest; then - echo "❌ Flatpak build failed!" >&2 - return 1 - fi - - local suffix - if (( $# == 1 )); then - suffix="_${1}-${VER_FULL}" - else - suffix="-$VER_FULL" - fi - local ARCH=$(uname -m) - local filename="space.oolite.Oolite${suffix}-${ARCH}.flatpak" - echo "Creating Flatpak $filename..." - if ! flatpak build-bundle \ - repo \ - "$filename" \ - space.oolite.Oolite; then - echo "❌ Flatpak bundle creation failed!" >&2 - return 1 - fi - local debugname="space.oolite.Oolite.Debug${suffix}-${ARCH}.flatpak" - if ! flatpak build-bundle \ - --runtime \ - repo \ - "$debugname" \ - space.oolite.Oolite.Debug; then - echo "❌ Flatpak bundle creation failed!" >&2 - return 1 - fi - - popd -} - -run_script "$@" -status=$? - - -# Exit only if not sourced -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - exit $status -fi - diff --git a/installers/flatpak/create_flatpak_fn.sh b/installers/flatpak/create_flatpak_fn.sh new file mode 100755 index 000000000..0ce28358a --- /dev/null +++ b/installers/flatpak/create_flatpak_fn.sh @@ -0,0 +1,121 @@ +#!/bin/bash -x + +create_flatpak() { + local build_type="$1" + local github_repository="$2" # GitHub repository (set by GitHub Actions) + + local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + pushd "$script_dir" + + cd ../.. + flatpak_dir="build/flatpak" + mkdir -p "$flatpak_dir" + source ShellScripts/common/get_version.sh + run_script "$flatpak_dir" + local githash ver_full ver_quad ver_gitrev cpp_date app_date buildtime builder + source "$flatpak_dir/.meson_version" + cd "$flatpak_dir" + + cp ../../installers/flatpak/space.oolite.Oolite.* ./ + mkdir -p shared-modules/glu + if ! curl -o shared-modules/glu/glu-9.json -L https://github.com/flathub/shared-modules/raw/refs/heads/master/glu/glu-9.json; then + echo "❌ Flatpak download of glu shared module failed!" >&2 + return 1 + fi + + local manifest="space.oolite.Oolite.yaml" + if ! sed -i "s|^[[:space:]]*- \./mk.sh.*| - ./mk.sh flatpak-internal $build_type --ver-full=\"$ver_full\" --buildtime=\"$buildtime\" --github-repository=\"$github_repository\"|" "$manifest"; then + echo "❌ Replacement of ./mk.sh line in $manifest failed!" >&2 + return 1 + fi + tail -n 12 $manifest + +# local lint_exceptions=$(mktemp /tmp/oolite-lint-XXXXXX.json) +# cat < "$lint_exceptions" +#{ +# "space.oolite.Oolite": [ +# "finish-args-has-dev-input" +# ] +#} +#EOF +# trap 'rm -f "$lint_exceptions"' RETURN EXIT +# if command -v flatpak-builder-lint >/dev/null 2>&1; then # check manifest +# if ! flatpak-builder-lint manifest "$manifest" --exceptions --user-exceptions="$lint_exceptions"; then +# echo "❌ Flatpak manifest lint failed!" >&2 +# cat "$manifest" +# echo "❌ Flatpak manifest lint failed!" >&2 +# return 1 +# fi +# else +# echo "Native linter not found. Falling back to Flatpak container..." +# if ! flatpak run --filesystem="$lint_exceptions" --command=flatpak-builder-lint org.flatpak.Builder manifest "$manifest" --exceptions --user-exceptions="$lint_exceptions"; then +# echo "❌ Flatpak manifest lint failed!" >&2 +# return 1 +# fi +# fi +# rm -f "$lint_exceptions" # Clean up +# trap - RETURN EXIT + + echo "Creating Flatpak..." + if ! flatpak remote-add \ + --user \ + --if-not-exists \ + flathub https://flathub.org/repo/flathub.flatpakrepo; then + echo "❌ Flatpak adding Flathub remote failed!" >&2 + return 1 + fi + + if ! sed -i "/- type: git/{ + N; + /url:.*oolite\.git/{ + N;N; + c\\ + - type: dir\\ + path: ../../ + } + }" "$manifest"; then + echo "❌ Replacement of Oolite git repo source lines in $manifest failed!" >&2 + return 1 + fi + tail -n 12 $manifest + + if ! flatpak-builder \ + --user \ + --force-clean \ + --repo=repo \ + --install-deps-from=flathub \ + --disable-rofiles-fuse \ + build-dir \ + $manifest; then + echo "❌ Flatpak build failed!" >&2 + return 1 + fi + + local suffix + if [[ "$build_type" != "deployment" ]]; then + suffix="_$build_type-$ver_full" + else + suffix="-$ver_full" + fi + local ARCH=$(uname -m) + local filename="space.oolite.Oolite${suffix}-${ARCH}.flatpak" + echo "Creating Flatpak $filename..." + if ! flatpak build-bundle \ + repo \ + "../$filename" \ + space.oolite.Oolite; then + echo "❌ Flatpak bundle creation failed!" >&2 + return 1 + fi + local debugname="space.oolite.Oolite.Debug${suffix}-${ARCH}.flatpak" + if ! flatpak build-bundle \ + --runtime \ + repo \ + "../$debugname" \ + space.oolite.Oolite.Debug; then + echo "❌ Flatpak bundle creation failed!" >&2 + return 1 + fi + + popd +} diff --git a/installers/flatpak/flatpak_build.sh b/installers/flatpak/flatpak_build.sh deleted file mode 100755 index 503f5d8c1..000000000 --- a/installers/flatpak/flatpak_build.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -x -# -# Prepares the app directory for the flatpak builder -# - -echo "I am flatpak_build.sh $@" -printenv | sort - -source ShellScripts/common/get_version.sh -source ShellScripts/Linux/install_freedesktop_fn.sh - -export ADDITIONAL_CFLAGS="-DBUILD_DATE='\"$CPP_DATE\"'" -export ADDITIONAL_OBJCFLAGS="-DBUILD_DATE='\"$CPP_DATE\"'" -make release-deployment - -ABS_OOLITEDIR=$(realpath -m "build/meson_deployment/oolite.app") -install_freedesktop $ABS_OOLITEDIR /app lib/debug/bin metainfo -# Ensure the destination directory exists -mkdir -p /app/lib/debug/source/oolite -# Copy the src directory recursively -cp -r src /app/lib/debug/source/oolite/ || { - echo "❌ $err_msg install oolite source code" >&2 - return 1 -} diff --git a/installers/flatpak/flatpak_postbuild_fn.sh b/installers/flatpak/flatpak_postbuild_fn.sh new file mode 100755 index 000000000..a60f0a352 --- /dev/null +++ b/installers/flatpak/flatpak_postbuild_fn.sh @@ -0,0 +1,21 @@ +#!/bin/bash -x +# +# Prepares the app directory for the flatpak builder +# + +flatpak_postbuild() { + local build_folder="$1" # Build folder + + local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + pushd "$script_dir" + source ../FreeDesktop/install_freedesktop_fn.sh + + cd ../../build/flatpak + install_freedesktop ver_full "../$build_folder" "/app" "lib/debug/bin" "metainfo" + mkdir -p /app/lib/debug/source/oolite # Ensure the destination directory exists + cp -r ../../src /app/lib/debug/source/oolite/ || { # Copy the src directory recursively + echo "❌ $err_msg install oolite source code" >&2 + return 1 + } + popd +} \ No newline at end of file diff --git a/installers/flatpak/space.oolite.Oolite.yaml b/installers/flatpak/space.oolite.Oolite.yaml index 33456d2ff..16398f6ae 100644 --- a/installers/flatpak/space.oolite.Oolite.yaml +++ b/installers/flatpak/space.oolite.Oolite.yaml @@ -111,13 +111,14 @@ modules: buildsystem: simple build-options: no-debuginfo: true - # CI builds add an env block here build-commands: - - source installers/flatpak/flatpak_build.sh + # Update --ver-full for FlatHub release. For CI and local builds, create_flatpak.sh replaces + # --ver-full and --github-repository values + - ./mk.sh flatpak deployment --ver-full="1.92.1" --buildtime="2026.03.19 07:13" --github-repository="OoliteProject/oolite" sources: # Update tag and commit for FlatHub release. For CI and local builds, create_flatpak.sh replaces git source with: # - type: dir - # path: ../ + # path: ../../ - type: git url: https://github.com/OoliteProject/oolite.git tag: "1.92.1.0" diff --git a/installers/win32/OOlite.nsi b/installers/win32/OOlite.nsi index 0f24d7858..9f0f0cd8c 100644 --- a/installers/win32/OOlite.nsi +++ b/installers/win32/OOlite.nsi @@ -1,5 +1,5 @@ ; Include the NSIS logic library. Required for the code that handles -; adding of the changelog file in the non-snapshot distributions +; adding of the changelog file in the non-dev distributions !include "LogicLib.nsh" ; Include the Sections library, required for being able to provide the @@ -14,10 +14,6 @@ ; and it's too much work to try to dynamically edit this file !include /NONFATAL "OoliteVersions.nsh" -!ifndef VER_GITREV -!warning "No GIT Revision supplied" -!define VER_GITREV 0 -!endif !ifndef VERSION !warning "No Version information supplied" !define VERSION 0.0.0.0 @@ -31,12 +27,12 @@ !ifndef OUTDIR !define OUTDIR . !endif -!ifndef SEMVER -!define SEMVER ${VERSION} +!ifndef VER_FULL +!define VER_FULL ${VERSION} !endif -!ifndef SNAPSHOT -!ifndef DEPLOYMENT +!ifndef DEV_RELEASE +!ifndef DEPLOYMENT_RELEASE !define EXTVER "-test" ; Official distribution with OXP developer tools !define ADDCHANGELOG 1 ; Official distributions go with a changelog file !else @@ -45,10 +41,10 @@ !endif !else !define EXTVER "-dev" -!define ADDCHANGELOG 0 ; Snapshot distributions do not need changelog +!define ADDCHANGELOG 0 ; Dev distributions do not need changelog !endif -!ifndef DEPLOYMENT +!ifndef DEPLOYMENT_RELEASE !define DEBUGOXPINCLUDED 1 !else !define DEBUGOXPINCLUDED 0 @@ -61,10 +57,10 @@ SetCompress auto SetCompressor LZMA SetCompressorDictSize 32 SetDatablockOptimize on -OutFile "${OUTDIR}\OoliteInstall-${SEMVER}-win${EXTVER}.exe" +OutFile "${OUTDIR}\OoliteInstall-${VER_FULL}-win${EXTVER}.exe" BrandingText "(C) 2003-2026 Giles Williams, Jens Ayton and contributors" Name "Oolite" -Caption "Oolite ${SEMVER} ${EXTVER} Setup" +Caption "Oolite ${VER_FULL} ${EXTVER} Setup" SubCaption 0 " " SubCaption 1 " " SubCaption 2 " " @@ -86,9 +82,9 @@ VIAddVersionKey "ProductName" "Oolite" VIAddVersionKey "FileDescription" "A space combat/trading game, inspired by Elite." VIAddVersionKey "LegalCopyright" "� 2003-2026 Giles Williams, Jens Ayton and contributors" VIAddVersionKey "FileVersion" "${VER}" -VIAddVersionKey "ProductVersion" "${SEMVER}" -!ifdef SNAPSHOT -VIAddVersionKey "GIT Revision" "${VER_GITHASH}" +VIAddVersionKey "ProductVersion" "${VER_FULL}" +!ifdef DEV_RELEASE +VIAddVersionKey "GIT Hash" "${VER_GITHASH}" !endif !ifdef BUILDTIME VIAddVersionKey "Build Time" "${BUILDTIME}" @@ -104,7 +100,7 @@ VIProductVersion "${VER}" !define MUI_UNICON oolite.ico !insertmacro MUI_PAGE_DIRECTORY -!ifndef DEPLOYMENT +!ifndef DEPLOYMENT_RELEASE !insertmacro MUI_PAGE_COMPONENTS !endif !insertmacro MUI_PAGE_INSTFILES @@ -127,14 +123,14 @@ VIProductVersion "${VER}" !insertmacro MUI_LANGUAGE "English" -!ifndef DEPLOYMENT +!ifndef DEPLOYMENT_RELEASE ; Create the main game and Debug OXP sections Section "Oolite Game" ooGame SectionIn RO ; The game itself cannot be unselected SectionEnd Section "Basic-debug.OXP" ooDebugOXP -; Do not use any of the Debug OXP files when we are building Deployment +; Do not use any of the Debug OXP files when we are building deployment release SetOutPath $INSTDIR File /r "${DST}\AddOns" SectionEnd @@ -200,7 +196,7 @@ uninst: done: FunctionEnd -!ifndef DEPLOYMENT +!ifndef DEPLOYMENT_RELEASE Function .onSelChange ${If} ${SectionIsSelected} ${ooDebugOXP} !insertmacro SelectSection ${ooDebugOXP} diff --git a/installers/win32/create_nsis.sh b/installers/win32/create_nsis_fn.sh similarity index 52% rename from installers/win32/create_nsis.sh rename to installers/win32/create_nsis_fn.sh index d4a74e8be..4fe950893 100644 --- a/installers/win32/create_nsis.sh +++ b/installers/win32/create_nsis_fn.sh @@ -1,24 +1,20 @@ #!/bin/bash -x # # Creates the windows installer using NSIS. -# First parameter can be set to build type, typically one of "test", "dev" or omitted for release builds. -# Accepts two verion variables: -# VER_FULL - the full version number Oolite is getting built with -# VER_NSIS - the numberical version number (x.x.x.x) that the NSIS installer is built with -# - -echo I am $0 $@ +create_nsis() { + local build_type="$1" # Typically one of "deployment", "test", "dev" + local build_folder="$2" # Build folder -run_script() { - # First parameter is a suffix for the build type eg. test, dev local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" + source ../../ShellScripts/common/parse_manifest_fn.sh mkdir -p ../../build/nsis cd ../../build/nsis - source ../../ShellScripts/common/get_version.sh - + local oolite_dir="../$build_folder" + local ver_full ver_quad ver_githash buildtime app_date + parse_manifest ver_full ver_quad ver_githash buildtime app_date "$oolite_dir/Resources/manifest.plist" cp ../../installers/win32/* ./ if ! curl -o OoliteReadMe.pdf -L https://oolite.readthedocs.io/en/latest/index.pdf; then @@ -42,32 +38,24 @@ run_script() { return 1 fi - local oolite_dir="../$1" - oolite_dir="${oolite_dir//\//\\}" - - # Passing arguments cause problems with some versions of NSIS. - # Because of this, we generate them into a separate file and include them. + # Passing arguments can cause problems with NSIS so we generate them into a separate file and include them. echo "; Version Definitions for Oolite" > OoliteVersions.nsh echo "; NOTE - This file is auto-generated by the Makefile, any manual edits will be overwritten" >> OoliteVersions.nsh - echo "!define oolite_dir ${oolite_dir}" >> OoliteVersions.nsh - echo "!define VER_MAJ ${VER_MAJ}" >> OoliteVersions.nsh - echo "!define VER_MIN ${VER_MIN}" >> OoliteVersions.nsh - echo "!define VER_REV ${VER_REV}" >> OoliteVersions.nsh - echo "!define VER_GITREV ${VER_GITREV}" >> OoliteVersions.nsh - echo "!define VER_GITHASH ${VER_GITHASH}" >> OoliteVersions.nsh - echo "!define VERSION ${VER_NSIS}" >> OoliteVersions.nsh - echo "!define SEMVER ${VER_FULL}" >> OoliteVersions.nsh - echo "!define BUILDTIME \"${BUILDTIME}\"" >> OoliteVersions.nsh + echo "!define OOLITE_DIR ${oolite_dir//\//\\}" >> OoliteVersions.nsh + echo "!define VER_GITHASH ${ver_githash}" >> OoliteVersions.nsh + echo "!define VERSION ${ver_quad}" >> OoliteVersions.nsh + echo "!define VER_FULL ${ver_full}" >> OoliteVersions.nsh + echo "!define BUILDTIME \"${buildtime}\"" >> OoliteVersions.nsh echo "!define BUILDHOST_IS64BIT 1" >> OoliteVersions.nsh - if [[ "$2" == "dev" ]]; then - echo "!define SNAPSHOT 1" >> OoliteVersions.nsh - elif [[ "$2" != "test" ]]; then - echo "!define DEPLOYMENT 1" >> OoliteVersions.nsh + if [[ "$build_type" == "deployment" ]]; then + echo "!define DEPLOYMENT_RELEASE 1" >> OoliteVersions.nsh + elif [[ "$build_type" == "dev" ]]; then + echo "!define DEV_RELEASE 1" >> OoliteVersions.nsh fi local nsis - if [[ -n "$MINGW_PREFIX" ]]; then + if [[ -v MINGW_PREFIX ]]; then nsis=$MINGW_PREFIX/bin/makensis else nsis=/nsis/makensis.exe @@ -78,13 +66,3 @@ run_script() { fi popd } - -run_script "$@" -status=$? - - -# Exit only if not sourced -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - exit $status -fi - diff --git a/meson.build b/meson.build index badc7b786..8397f071e 100644 --- a/meson.build +++ b/meson.build @@ -5,6 +5,7 @@ project( version: run_command( 'bash', files('ShellScripts/common/get_version.sh'), + meson.project_build_root(), check: true, ).stdout().strip(), default_options: [ @@ -16,19 +17,22 @@ host_os = host_machine.system() c_family = ['c', 'cpp', 'objc'] version_string = meson.project_version() -add_project_arguments( - '-DOO_VERSION_FULL="@0@"'.format(version_string), - language: c_family, -) +cat_cmd = find_program('cat', required: true) +version_file = meson.project_build_root() / '.meson_version' +cat_result = run_command(cat_cmd, version_file, check: true) +version_vars = {} +file_contents = cat_result.stdout().strip() -github_repository = get_option('github_repository') -if github_repository == 'OoliteProject/oolite' - builder = 'OoliteProject' -else - builder = 'unknown' -endif +foreach line : file_contents.split('\n') + parts = line.split('=') + key = parts[0].strip() + value = parts[1].strip('"\' ') + version_vars += { key : value } +endforeach add_project_arguments( - '-DOO_BUILDER="@0@"'.format(builder), + '-DOO_VERSION_FULL="@0@"'.format(version_string), + '-DOO_BUILD_DATE="@0@"'.format(version_vars.get('app_date')), + '-DOO_BUILDER="@0@"'.format(version_vars.get('builder')), language: c_family, ) @@ -47,7 +51,7 @@ if get_option('no_shaders') add_project_arguments('-DNO_SHADERS=1', language: c_family) endif -if get_option('deployment_release_configuration') +if get_option('deployment_release') add_project_arguments( '-DNDEBUG', '-DOO_CHECK_GL_HEAVY=0', @@ -81,10 +85,9 @@ else endif endif -if get_option('snapshot_build') +if get_option('dev_release') add_project_arguments( - '-DSNAPSHOT_BUILD', - '-DOOLITE_SNAPSHOT_VERSION="@0@"'.format(version_string), + '-DDEV_RELEASE', language: c_family, ) endif diff --git a/meson.options b/meson.options index 7ff139544..138a83074 100644 --- a/meson.options +++ b/meson.options @@ -32,20 +32,14 @@ option('debug_graphviz', type: 'boolean', value: true, description: 'Enable AI state-machine graph visualization via GraphViz syntax output') # Release Variant Control -option('deployment_release_configuration', type: 'boolean', value: false, +option('deployment_release', type: 'boolean', value: false, description: 'Force a strict production deployment setup (overrides and disables most debugging instrumentation)') -option('snapshot_build', type: 'boolean', value: false, - description: 'Mark the compilation as a development snapshot build') +option('dev_release', type: 'boolean', value: false, + description: 'Mark the compilation as a development release') option('strip_bin', type: 'boolean', value: false, description: 'Enable stripping') # Windows Specific Customizations option('pdb', type: 'boolean', value: false, description: 'Windows Clang builds only: Generate native .pdb debug symbol files') - -# GitHub repository variable from CI if available -option('github_repository', type: 'string', value: '', - description: 'GitHub repository variable from CI if available') - - diff --git a/mk.sh b/mk.sh new file mode 100755 index 000000000..80622f5c8 --- /dev/null +++ b/mk.sh @@ -0,0 +1,377 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +pushd "$SCRIPT_DIR" > /dev/null + +set -u -o pipefail # Strict expansions + +cleanup_and_exit() { # Error handling trap + local exit_code=$? + + if [[ $exit_code -eq 0 ]]; then + exit_code=1 # force 0 exit code to 1 to indicate an error + fi + echo "❌ Oolite build failed on line $1 with exit code $exit_code!" >&2 + popd > /dev/null 2>&1 || true # Always pop the directory stack before exiting + if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then # Exit only if not sourced + exit "$exit_code" + fi +} +trap 'cleanup_and_exit ${LINENO}' ERR # Trap any command errors (ERR) passing ${LINENO} to know where it failed + +output_meson_log() { + meson_log="$1/meson-logs/meson-log.txt" + if [[ -f "$meson_log" ]]; then + echo -e "\n=== MESON LOG START ===" >&2 + cat "$meson_log" >&2 + echo -e "=== MESON LOG END ===\n" >&2 + fi +} + +# --- Feature Flags & Options --- +NATIVE_FILE="" +VER_FULL="" +BUILDTIME="" +GITHUB_REPOSITORY="" +CLEAN_BUILD=false +SETUP_FLAGS=() # Array to cleanly store additional meson setup arguments +COMPILE_FLAGS=() # Array to cleanly store additional meson compile arguments +CONFIGURE_FLAGS=() # Array to cleanly store additional meson configure arguments +INSTALL_FLAGS=() # Array to cleanly store additional meson install arguments + +clean() { + echo "--> Cleaning target build directory: $1" + rm -rf "$1" +} + +meson_setup() { + local build_dir="build/meson_$1" + echo "--> Running Meson setup for: $1" + local meson_opts=("${@:2}") + if [[ -n "${VER_FULL:-}" ]]; then + export VER_FULL + fi + if [[ -n "${BUILDTIME:-}" ]]; then + export BUILDTIME + fi + if [[ -n "${GITHUB_REPOSITORY:-}" ]]; then + export GITHUB_REPOSITORY + fi + if [[ -d "$build_dir" ]] && [[ -f "$build_dir/build.ninja" ]]; then + echo "🔄 Directory exists, attempting to reconfigure..." + if ! meson setup "$build_dir" "${meson_opts[@]}" ${SETUP_FLAGS[@]+"${SETUP_FLAGS[@]}"} --native-file "${NATIVE_FILE}" --reconfigure; then + echo "❌ Meson reconfiguration failed!" >&2 + output_meson_log "$build_dir" + exit 1 + fi + else + echo "🏗️ Creating new build configuration..." + if ! meson setup "$build_dir" "${meson_opts[@]}" ${SETUP_FLAGS[@]+"${SETUP_FLAGS[@]}"} --native-file "${NATIVE_FILE}"; then + echo "❌ Meson initial setup failed!" >&2 + output_meson_log "$build_dir" + exit 1 + fi + fi +} + +meson_compile() { + local build_dir="build/meson_$1" + echo "--> Running Meson build for: $1" + if ! meson compile -C "$build_dir" ${COMPILE_FLAGS[@]+"${COMPILE_FLAGS[@]}"}; then + echo "❌ Meson compile failed!" >&2 + output_meson_log "$build_dir" + exit 1 + fi +} + +meson_configure() { + local build_dir="build/meson_$1" + echo "--> Running Meson configure for: $1" + local meson_opts=("${@:2}") + if ! meson configure "$build_dir" "${meson_opts[@]}" ${CONFIGURE_FLAGS[@]+"${CONFIGURE_FLAGS[@]}"}; then + echo "❌ Meson configure failed!" >&2 + output_meson_log "$build_dir" + exit 1 + fi +} + +meson_install() { + local build_dir="build/meson_$1" + echo "--> Running Meson install for: $1" + if ! meson install -C "$build_dir" ${INSTALL_FLAGS[@]+"${INSTALL_FLAGS[@]}"}; then + echo "❌ Meson install failed!" >&2 + output_meson_log "$build_dir" + exit 1 + fi +} + +show_help() { # Script Help Menu + echo "Usage: $0 [options] " + echo " $0 [options] " + echo "" + echo "Options:" + echo -e " \033[36m--setup-flags=\"...\"\033[0m Pass additional arguments directly to 'meson setup'" + echo -e " \033[36m--compile-flags=\"...\"\033[0m Pass additional arguments directly to 'meson compile'" + echo -e " \033[36m--configure-flags=\"...\"\033[0m Pass additional arguments directly to 'meson configure'" + echo -e " \033[36m--install-flags=\"...\"\033[0m Pass additional arguments directly to 'meson install'" + echo -e " \033[36m--native-file=\"...\"\033[0m Specify native file (defaults to clang.ini)" + echo -e " \033[36m--ver-full=\"...\"\033[0m Specify full version string" + echo -e " \033[36m--buildtime=\"...\"\033[0m Specify build time" + echo -e " \033[36m--github-repository=\"...\"\033[0m Specify target GitHub repository" + echo "" + echo "Build Type Actions (Requires build_type as second parameter):" + echo -e " \033[36msetup \033[0m Setup a release build directory" + echo -e " \033[36mcompile \033[0m Compile a build directory" + echo -e " \033[36mbuild \033[0m Setup and compile a build directory" + echo -e " \033[36mconfigure \033[0m Modify build options of an existing build directory" + echo -e " \033[36minstall \033[0m Install an existing build directory" + echo -e " \033[36mtest \033[0m Run test suites (deployment build_type excluded)" + echo -e " \033[36mclean \033[0m Clean a specific build_type's directory" + echo -e " \033[36mflatpak-internal \033[0m Build flatpak dependencies internally" + echo -e " \033[36mpkg-flatpak \033[0m Package a Flatpak application" + echo -e " \033[36mpkg-appimage \033[0m Package a Linux AppImage installer" + echo -e " \033[36mpkg-win \033[0m Package a Windows NSIS installer" + echo "" + echo "Global Actions:" + echo -e " \033[36mclean-all\033[0m Remove generated artifacts for all builds" + echo -e " \033[36mhelp\033[0m Show this breakdown menu" + echo "" + echo "Build Types:" + echo -e " \033[32mdeployment, test, dev, debug\033[0m" +} + +validate_build_type() { + local build_type="$1" + if [[ "$build_type" != "deployment" && "$build_type" != "test" && "$build_type" != "dev" && "$build_type" != "debug" ]]; then + echo "❌ Invalid build_type '$build_type'. Expected: deployment, test, dev, or debug." >&2 + exit 1 + fi +} + +execute_target() { # Target Execution Logic + local action="$1" + local build_type="${2:-}" + +case "$action" in + setup) + validate_build_type "$build_type" + if [[ "$build_type" == "deployment" ]]; then + # Arguments passed individually (acts like an array) + meson_setup "deployment" "-Ddeployment_release=true" "-Ddebug=false" "-Dstrip_bin=true" "-Db_lto=true" + elif [[ "$build_type" == "test" ]]; then + meson_setup "test" "-Ddebug=false" "-Dstrip_bin=true" "-Db_lto=true" + elif [[ "$build_type" == "dev" ]]; then + meson_setup "dev" "-Ddev_release=true" "-Ddebug=false" "-Dstrip_bin=false" + elif [[ "$build_type" == "debug" ]]; then + meson_setup "debug" "-Ddebug=true" "-Dstrip_bin=false" + fi + ;; + compile) + validate_build_type "$build_type" + meson_compile "$build_type" + ;; + build) + validate_build_type "$build_type" + execute_target "setup" "$build_type" + execute_target "compile" "$build_type" + ;; + configure) + validate_build_type "$build_type" + meson_configure "$build_type" + ;; + install) + validate_build_type "$build_type" + meson_install "$build_type" + ;; + test) + validate_build_type "$build_type" + if [[ "$build_type" == "deployment" ]]; then + echo "❌ Cannot test deployment as not set up for debug console!" >&2 + exit 1 + fi + source tests/run_test_fn.sh && run_test "$build_type" + ;; + clean) + if [[ "$build_type" == "appimage" ]]; then + clean "build/appimage" + elif [[ "$build_type" == "flatpak" ]]; then + clean "build/flatpak" + else + validate_build_type "$build_type" + clean "build/meson_$build_type" + fi + ;; + flatpak-internal) + validate_build_type "$build_type" + execute_target "build" "$build_type" + if ! meson_configure "$build_type" "--prefix=/app"; then + echo "❌ Flatpak meson configure with prefix /app failed!" >&2 + exit 1 + fi + if ! meson_install "$build_type"; then + echo "❌ Flatpak meson install failed!" >&2 + exit 1 + fi + if ! source installers/flatpak/flatpak_postbuild_fn.sh; then + echo "❌ Failed to source flatpak_postbuild_fn.sh!" >&2 + exit 1 + fi + if ! flatpak_postbuild "meson_${build_type}/oolite.app"; then + echo "❌ Flatpak post build failed!" >&2 + exit 1 + fi + ;; + pkg-flatpak) + validate_build_type "$build_type" + if ! source installers/flatpak/create_flatpak_fn.sh; then + echo "❌ Failed to source create_flatpak_fn.sh!" >&2 + exit 1 + fi + if ! create_flatpak "$build_type" "$GITHUB_REPOSITORY"; then + echo "❌ Flatpak generation failed!" >&2 + exit 1 + fi + ;; + pkg-appimage) + validate_build_type "$build_type" + local appdir=$(realpath -m "build/appimage/oolite.AppDir") + if ! meson_configure "$build_type" "--prefix=$appdir"; then + echo "❌ AppImage meson configure with prefix /app failed!" >&2 + exit 1 + fi + if ! meson_install "$build_type"; then + echo "❌ AppImage meson install failed!" >&2 + exit 1 + fi + if ! source installers/appimage/create_appimage_fn.sh; then + echo "❌ Failed to source create_appimage_fn.sh!" >&2 + exit 1 + fi + if ! create_appimage "$build_type" "meson_${build_type}/oolite.app"; then + echo "❌ AppImage generation failed!" >&2 + exit 1 + fi + ;; + pkg-win) + validate_build_type "$build_type" + if ! source installers/win32/create_nsis_fn.sh; then + echo "❌ Failed to source create_nsis_fn.sh!" >&2 + exit 1 + fi + if ! create_nsis "$build_type" "meson_${build_type}/oolite.app"; then + echo "❌ NSIS generation failed!" >&2 + exit 1 + fi + ;; + *) + echo "❌ Fatal structural error handling action '$action'" >&2 + exit 1 + ;; + esac +} + +ACTION="" +BUILD_TYPE="" + +# --- Flexible Argument Parser (Allows flags and positionals anywhere) --- +while [[ $# -gt 0 ]]; do + case "$1" in + --setup-flags=*) + read -r -a flags_array <<< "${1#*=}" + SETUP_FLAGS+=("${flags_array[@]}") + shift + ;; + --compile-flags=*) + read -r -a flags_array <<< "${1#*=}" + COMPILE_FLAGS+=("${flags_array[@]}") + shift + ;; + --configure-flags=*) + read -r -a flags_array <<< "${1#*=}" + CONFIGURE_FLAGS+=("${flags_array[@]}") + shift + ;; + --install-flags=*) + read -r -a flags_array <<< "${1#*=}" + INSTALL_FLAGS+=("${flags_array[@]}") + shift + ;; + --native-file=*) + NATIVE_FILE="${1#*=}" + shift + ;; + --ver-full=*) + VER_FULL="${1#*=}" + shift + ;; + --buildtime=*) + BUILDTIME="${1#*=}" + shift + ;; + --github-repository=*) + GITHUB_REPOSITORY="${1#*=}" + shift + ;; + help|--help|-h) + show_help + exit 0 + ;; + -*) + echo "❌ Unknown option '$1'" >&2 + show_help + exit 1 + ;; + *) + # Process sequential text items dynamically + if [[ -z "$ACTION" ]]; then + ACTION="$1" + elif [[ -z "$BUILD_TYPE" ]]; then + BUILD_TYPE="$1" + else + echo "❌ Unexpected extra argument '$1'." >&2 + show_help + exit 1 + fi + shift + ;; + esac +done + +if [[ -z "$ACTION" ]]; then + show_help # Fallback to help menu if no action was provided + exit 1 +fi + +# Intercept global action 'clean-all' before validating build_type requirements +if [[ "$ACTION" == "clean-all" ]]; then + echo "--> Cleaning all build artifacts..." + rm -rf build/meson_* + rm -rf build/flatpak + rm -rf build/appimage + trap - ERR + popd > /dev/null + echo "✅ Oolite task 'clean-all' completed successfully" + exit 0 +fi + +# Everything past this point strictly requires a build_type parameter +if [[ -z "$BUILD_TYPE" ]]; then + echo "❌ Error: Action '$ACTION' requires a target build_type parameter." >&2 + show_help + exit 1 +fi + +if [[ -z "$NATIVE_FILE" ]]; then + NATIVE_FILE="clang.ini" # Apply default if it wasn't passed as an option +fi + +execute_target "$ACTION" "$BUILD_TYPE" + +trap - ERR # Successful Exit +popd > /dev/null + +echo "✅ Oolite task '$ACTION $BUILD_TYPE' completed successfully" + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + exit 0 +fi \ No newline at end of file diff --git a/src/Core/OOLogHeader.m b/src/Core/OOLogHeader.m index c2522d6b0..1e19beb86 100644 --- a/src/Core/OOLogHeader.m +++ b/src/Core/OOLogHeader.m @@ -161,7 +161,7 @@ void OOPrintLogHeader(void) #endif NSString *versionString = nil; - #if (defined (SNAPSHOT_BUILD)) + #if (defined (DEV_RELEASE)) versionString = @"development version " @OO_VERSION_FULL; #else versionString = @"version " @OO_VERSION_FULL; diff --git a/src/Core/Universe.m b/src/Core/Universe.m index 68138c75e..bd8ecc0ce 100644 --- a/src/Core/Universe.m +++ b/src/Core/Universe.m @@ -5243,7 +5243,7 @@ - (void) drawUniverse // should come after the HUD to avoid it being overlapped by it [self drawMessage]; -#if (defined (SNAPSHOT_BUILD)) +#if (defined (DEV_RELEASE)) [self drawWatermarkString:@"Development version " @OO_VERSION_FULL]; #endif diff --git a/src/SDL/MyOpenGLView.m b/src/SDL/MyOpenGLView.m index 814d37fb3..0b4f3e8d2 100644 --- a/src/SDL/MyOpenGLView.m +++ b/src/SDL/MyOpenGLView.m @@ -145,11 +145,7 @@ - (NSMutableDictionary *) getNativeSize - (NSString*) getWindowCaption { -#ifdef BUILD_DATE - NSString *caption = [NSString stringWithFormat:@"Oolite v%@ by %@ - %s", @OO_VERSION_FULL, @OO_BUILDER, BUILD_DATE]; -#else - NSString *caption = [NSString stringWithFormat:@"Oolite v%@ by %@ - %s", @OO_VERSION_FULL, @OO_BUILDER, __DATE__]; -#endif + NSString *caption = [NSString stringWithFormat:@"Oolite v%@ by %@ - %@", @OO_VERSION_FULL, @OO_BUILDER, @OO_BUILD_DATE]; return [[caption retain] autorelease]; } diff --git a/src/meson.build b/src/meson.build index 314faa0ed..6c3dd2fb3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -35,42 +35,44 @@ oolite_bin = executable( install: false, ) +bash_prog = find_program('bash') prog_dir = meson.global_build_root() / appname + '.app' stamp_file = '.oolite_bundle.stamp' -install_env_args = [ - 'ORIGPROGPATH=' + meson.current_build_dir() / appname, - 'PROGDIR=' + prog_dir, - 'HOST_OS=' + host_os, - 'DEBUG=' + (get_option('debug') ? 'yes' : 'no'), - 'DEPLOYMENT_RELEASE_CONFIGURATION=' + ( - get_option('deployment_release_configuration') ? 'yes' : 'no' - ), - 'ESPEAK=' + (get_option('espeak') ? 'yes' : 'no'), - 'STRIP_BIN=' + (get_option('strip_bin') ? 'yes' : 'no'), - 'VER_FULL=' + version_string, - 'GNUSTEP_FOLDER=' + gnustep_folder, - 'STAMP_FILE=' + stamp_file, +post_build_args = [ + meson.current_build_dir() / appname, + prog_dir, + host_os, + get_option('debug') ? 'yes' : 'no', + get_option('deployment_release') ? 'yes' : 'no', + get_option('espeak') ? 'yes' : 'no', + get_option('strip_bin') ? 'yes' : 'no', + version_string, + version_vars.get('ver_quad'), + version_vars.get('ver_githash'), + version_vars.get('buildtime'), + gnustep_folder, + stamp_file, ] -post_build_script = find_program('../ShellScripts/common/post_build.sh') +post_build_script = files('../ShellScripts/common/post_build.sh') +generate_manifest_script = files('../ShellScripts/common/generate_manifest_fn.sh') oolite_app_bundle = custom_target('post_build', input: oolite_bin, output: stamp_file, - depend_files: [post_build_script.full_path()], command: [ - 'env', - install_env_args, - post_build_script.full_path(), + bash_prog, + post_build_script, + post_build_args, ], + depend_files: [generate_manifest_script], build_by_default: true, install: false, ) -install_env_args = [ - 'STAGEPROGPATH=' + prog_dir / appname, - 'BINDIR=' + get_option('bindir'), - 'DATADIR=' + get_option('datadir'), - 'HOST_OS=' + host_os, - 'DEPLOYMENT_RELEASE_CONFIGURATION=' + ( - get_option('deployment_release_configuration') ? 'yes' : 'no'), +install_args = [ + prog_dir / appname, + get_option('bindir'), + get_option('datadir'), + host_os, + get_option('deployment_release') ? 'yes' : 'no', ] -install_script = find_program('../ShellScripts/common/install.sh') -meson.add_install_script('env', install_env_args, install_script.full_path()) \ No newline at end of file +install_script = files('../ShellScripts/common/install.sh') +meson.add_install_script(bash_prog, install_script, install_args) diff --git a/tests/run_test.sh b/tests/run_test_fn.sh similarity index 84% rename from tests/run_test.sh rename to tests/run_test_fn.sh index f345ab359..5061c75e5 100755 --- a/tests/run_test.sh +++ b/tests/run_test_fn.sh @@ -9,7 +9,7 @@ output_log() { fi } -run_script() { +run_test() { if python3 --version >/dev/null 2>&1; then local PYTHON_CMD="python3" elif python --version >/dev/null 2>&1; then @@ -22,10 +22,10 @@ run_script() { local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) pushd "$script_dir" - local BUILD_TYPE="${1:-snapshot}" + local BUILD_TYPE="${1:-dev}" local TARGET_DIR=$(readlink -f "../build/meson_${BUILD_TYPE}/oolite.app") - if [[ -n "$MSYSTEM" ]]; then - local MESA_DLL="${MSYSTEM_PREFIX}/bin/opengl32.dll" + if [[ -v MINGW_PREFIX ]]; then + local MESA_DLL="${MINGW_PREFIX}/bin/opengl32.dll" if [[ -f "$MESA_DLL" ]]; then echo "📦 Copying $MSYSTEM Mesa driver at $MESA_DLL" cp "$MESA_DLL" "$TARGET_DIR/" @@ -50,12 +50,3 @@ run_script() { echo "✅ Oolite test completed successfully" popd } - -run_script "$@" -status=$? - -# Exit only if not sourced -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - exit $status -fi -