From 5b9bf43e127d213aafb3155f5ac5be172b028d62 Mon Sep 17 00:00:00 2001 From: Jay Dolan Date: Wed, 30 Sep 2026 12:54:49 -0400 Subject: [PATCH 1/4] Pin SDL3 to the jdolan/SDL ObjectivelyGPU tag The SDL_gpu query API that QueryPool uses exists only in the jdolan/SDL fork. SDL3 came from four sources before this change: a 3.4.2 dmg for the xcframework, unpinned Homebrew on macOS CI, and 3.4.12 for Linux CI and Windows. Every one now uses the ObjectivelyGPU tag, which is 3.4.12 plus the query API, so moving that tag changes SDL3 for the whole stack. - fetch-sdl3.sh downloads SDL3.dmg from the tag's release, and downloads again if the tag moves. - sdl3.targets downloads SDL3-devel-VC.zip into libs\SDL3-ObjectivelyGPU. - macOS and Linux CI build SDL3 from the tag. - Releases no longer republish SDL3.xcframework.zip, because the fork publishes it. - The local SDL switch scripts (link-sdl3-local.sh, use-sdl3.sh) and the root copy of fetch-sdl3.sh are removed. A moved tag replaces them. See jdolan/quetoo#1093. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/build.yml | 11 +++- .github/workflows/release.yml | 4 +- Documentation/install.md | 21 ++++++ Frameworks/fetch-sdl3.sh | 52 +++++++-------- Frameworks/link-sdl3-local.sh | 82 ------------------------ Frameworks/use-sdl3.sh | 50 --------------- ObjectivelyGPU.vs15/sdl3.targets | 19 +++--- ObjectivelyGPU.xcodeproj/project.pbxproj | 6 +- fetch-sdl3.sh | 59 ----------------- 9 files changed, 66 insertions(+), 238 deletions(-) delete mode 100755 Frameworks/link-sdl3-local.sh delete mode 100755 Frameworks/use-sdl3.sh delete mode 100755 fetch-sdl3.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e807bc4..a2e1b51 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,14 @@ jobs: steps: - name: Install dependencies run: | - brew install autoconf automake libtool pkg-config check cmake sdl3 + brew install autoconf automake libtool pkg-config check cmake + + - name: Build SDL3 + run: | + git clone --depth 1 --branch ObjectivelyGPU https://github.com/jdolan/SDL.git SDL3 + cmake -S SDL3 -B SDL3/build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${HOMEBREW_PREFIX} + cmake --build SDL3/build -j$(sysctl -n hw.logicalcpu) + cmake --install SDL3/build - name: Checkout Objectively uses: actions/checkout@v6 @@ -67,7 +74,7 @@ jobs: - name: Build SDL3 run: | - git clone --depth 1 --branch release-3.4.12 https://github.com/libsdl-org/SDL.git SDL3 + git clone --depth 1 --branch ObjectivelyGPU https://github.com/jdolan/SDL.git SDL3 cmake -S SDL3 -B SDL3/build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local cmake --build SDL3/build -j$(nproc) sudo cmake --install SDL3/build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 630924e..edff69c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ permissions: env: # Objectively is a source dependency (resolved via ObjectivelyGPU.xcworkspace). # Override to point a GPU release/branch at a specific Objectively ref. - # SDL3 / curl versions live in fetch-sdl3.sh / build-libcurl.sh, not here. + # SDL3 is the jdolan/SDL ObjectivelyGPU tag (fetch-sdl3.sh); curl lives in build-libcurl.sh. OBJECTIVELY_REF: "main" jobs: @@ -82,7 +82,6 @@ jobs: - name: Zip xcframeworks working-directory: ObjectivelyGPU/Frameworks run: | - zip -r "$GITHUB_WORKSPACE/SDL3.xcframework.zip" SDL3.xcframework zip -r "$GITHUB_WORKSPACE/ObjectivelyGPU.xcframework.zip" ObjectivelyGPU.xcframework - name: Create release @@ -92,7 +91,6 @@ jobs: gh release create ${{ github.ref_name }} \ --title "ObjectivelyGPU ${{ github.ref_name }}" \ --generate-notes \ - "$GITHUB_WORKSPACE/SDL3.xcframework.zip" \ "$GITHUB_WORKSPACE/ObjectivelyGPU.xcframework.zip" env: GH_TOKEN: ${{ github.token }} diff --git a/Documentation/install.md b/Documentation/install.md index 5e45718..dae5ddb 100644 --- a/Documentation/install.md +++ b/Documentation/install.md @@ -14,6 +14,27 @@ Tagged releases are published on the [GitHub releases page](https://github.com/j * [Objectively](https://github.com/jdolan/Objectively) >= 2.0.0 * [SDL3](https://github.com/libsdl-org/SDL) >= 3.2.0 +### SDL3 and occlusion queries + +`QueryPool` requires the SDL_gpu query API (`SDL_GPU_QUERY_API`), which upstream SDL does not ship yet. The +`ObjectivelyGPU` tag in [jdolan/SDL](https://github.com/jdolan/SDL) carries it, and CI for ObjectivelyGPU, +ObjectivelyMVC and Quetoo MUST build against that tag. Against any other SDL3, ObjectivelyGPU still builds, but +`QueryPool.c` emits a compiler warning and occlusion queries are disabled. + +* Linux and macOS (autotools): build SDL from source with + `git clone --branch ObjectivelyGPU https://github.com/jdolan/SDL.git`. +* macOS and iOS (Xcode): `Frameworks/fetch-sdl3.sh` downloads `SDL3.xcframework` from the tag's release. It + records the tag's commit, and downloads again if the tag moves. +* Windows (Visual Studio): `ObjectivelyGPU.vs15/sdl3.targets` downloads `SDL3-devel-VC.zip` from the tag's + release on first build. Delete `ObjectivelyGPU.vs15/libs/` to pick up a moved tag. + +To change the SDL3 revision for the whole stack, move the tag, then publish its artifacts: + +```sh +git tag -f ObjectivelyGPU && git push -f origin ObjectivelyGPU +gh workflow run objectivelygpu.yml -R jdolan/SDL +``` + ## Building ```sh diff --git a/Frameworks/fetch-sdl3.sh b/Frameworks/fetch-sdl3.sh index faabbd3..173211b 100755 --- a/Frameworks/fetch-sdl3.sh +++ b/Frameworks/fetch-sdl3.sh @@ -1,37 +1,32 @@ #!/usr/bin/env bash # -# fetch-sdl3.sh — downloads the official SDL3 Apple xcframework from libsdl.org -# on demand and caches it under Frameworks/. +# fetch-sdl3.sh — downloads SDL3.xcframework from the jdolan/SDL release for SDL3_TAG and caches it +# under Frameworks/. # -# This mirrors the Windows VS build (ObjectivelyGPU.vs15/sdl3.targets): CI and -# local developers share a single code path. The download is cached at -# Frameworks/SDL3.xcframework.stable, and Frameworks/SDL3.xcframework is a -# symlink to it. This indirection lets link-sdl3-local.sh (and use-sdl3.sh) -# repoint that same symlink at a locally-built SDL3 checkout without disturbing -# this cache. Bump SDL3_VERSION to upgrade; delete -# Frameworks/SDL3.xcframework.stable to force a re-download. +# The whole stack (ObjectivelyGPU, ObjectivelyMVC, Quetoo) pins SDL3 to one tag in jdolan/SDL, which +# carries the SDL_gpu query API. The tag's commit SHA is stored next to the cache, so moving the tag +# causes a new download. This mirrors ObjectivelyGPU.vs15/sdl3.targets on Windows. # set -euo pipefail -SDL3_VERSION="${SDL3_VERSION:-3.4.2}" +SDL3_REPO="${SDL3_REPO:-jdolan/SDL}" +SDL3_TAG="${SDL3_TAG:-ObjectivelyGPU}" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -STABLE="$SCRIPT_DIR/SDL3.xcframework.stable" XCFRAMEWORK="$SCRIPT_DIR/SDL3.xcframework" +STAMP="$SCRIPT_DIR/SDL3.xcframework.sha" -# Migrate a pre-existing plain directory (from before the .stable split) in place. -if [ -d "$XCFRAMEWORK" ] && [ ! -L "$XCFRAMEWORK" ]; then - mv "$XCFRAMEWORK" "$STABLE" +sha="$(git ls-remote "https://github.com/$SDL3_REPO.git" "refs/tags/$SDL3_TAG" | cut -f1)" +if [ -z "$sha" ]; then + echo "error: tag $SDL3_TAG not found in $SDL3_REPO" >&2 + exit 1 fi -# Point the symlink at the stable cache, creating/replacing it as needed. -relink() { - ln -sfn "$(basename "$STABLE")" "$XCFRAMEWORK" +cached() { + [ -d "$XCFRAMEWORK" ] && [ ! -L "$XCFRAMEWORK" ] && [ "$(cat "$STAMP" 2>/dev/null)" = "$sha" ] } -# Already cached? Just make sure the symlink points at it and we're done. -if [ -d "$STABLE" ]; then - relink +if cached; then exit 0 fi @@ -53,17 +48,16 @@ cleanup() { trap cleanup EXIT # Re-check after acquiring the lock; another build may have just finished. -if [ -d "$STABLE" ]; then - relink +if cached; then exit 0 fi -DMG_URL="https://github.com/libsdl-org/SDL/releases/download/release-$SDL3_VERSION/SDL3-$SDL3_VERSION.dmg" +DMG_URL="https://github.com/$SDL3_REPO/releases/download/$SDL3_TAG/SDL3.dmg" -echo "==> Downloading SDL3 $SDL3_VERSION" +echo "==> Downloading SDL3 $SDL3_REPO@$SDL3_TAG ($sha)" curl -fL --retry 3 "$DMG_URL" -o "$TMP/SDL3.dmg" -echo "==> Mounting SDL3 $SDL3_VERSION" +echo "==> Mounting SDL3.dmg" mkdir -p "$MNT" hdiutil attach "$TMP/SDL3.dmg" -nobrowse -quiet -mountpoint "$MNT" @@ -73,8 +67,10 @@ if [ -z "$src" ]; then exit 1 fi +# Replace the cache, and the .stable/.local directories of the former use-sdl3.sh layout. echo "==> Caching SDL3.xcframework" -cp -R "$src" "$STABLE" -relink +rm -rf "$XCFRAMEWORK" "$SCRIPT_DIR/SDL3.xcframework.stable" "$SCRIPT_DIR/SDL3.xcframework.local" +cp -R "$src" "$XCFRAMEWORK" +echo "$sha" > "$STAMP" -echo "==> SDL3.xcframework $SDL3_VERSION ready at Frameworks/SDL3.xcframework" +echo "==> SDL3.xcframework $SDL3_TAG ready at Frameworks/SDL3.xcframework" diff --git a/Frameworks/link-sdl3-local.sh b/Frameworks/link-sdl3-local.sh deleted file mode 100755 index 4ad603f..0000000 --- a/Frameworks/link-sdl3-local.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env bash -# -# link-sdl3-local.sh — assembles Frameworks/SDL3.xcframework.local, an -# xcframework whose macOS slice is a live symlink into a locally-built SDL3 -# checkout, instead of the officially distributed binary cached by -# fetch-sdl3.sh. -# -# Defaults to Xcode/SDL/build/Release/SDL3.framework, produced by building the -# "SDL3" target/scheme in Xcode/SDL/SDL.xcodeproj with the Release -# configuration -- this is the same project, target, and configuration -# libsdl.org's own release process uses (see build-scripts/build-release.py's -# create_dmg() and build-scripts/release-info.json's "dmg" section), so it's -# the closest thing to a "vanilla local rebuild" of an official release, -# including your working-tree changes. If you build via CMake instead, point -# SDL3_LOCAL_BUILD at that framework instead. -# -# Because the macOS slice is a symlink (not a copy), rebuilding SDL3 in the -# local checkout is picked up immediately by Xcode -- there's no need to -# re-run this script after every SDL rebuild. Re-run it only if -# SDL3_LOCAL_BUILD's *path* changes, or after deleting -# Frameworks/SDL3.xcframework.local. -# -# Use use-sdl3.sh to toggle Frameworks/SDL3.xcframework between this and the -# official release fetched by fetch-sdl3.sh. -# -set -euo pipefail - -SDL3_LOCAL_BUILD="${SDL3_LOCAL_BUILD:-$HOME/Coding/SDL/Xcode/SDL/build/Release/SDL3.framework}" - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -STABLE="$SCRIPT_DIR/SDL3.xcframework.stable" -LOCAL="$SCRIPT_DIR/SDL3.xcframework.local" - -if [ ! -d "$SDL3_LOCAL_BUILD" ]; then - echo "error: $SDL3_LOCAL_BUILD not found (set SDL3_LOCAL_BUILD to override)" >&2 - exit 1 -fi - -# The official xcframework ships headers only at Headers/SDL3/*.h (so that a -# flat -I onto that Headers/ dir resolves the project's #include -# convention). A vanilla CMake-built SDL3.framework has no such nesting. -# Fix that up once, in place, with a self-referential symlink. "." is used -# (rather than an absolute/canonicalized path) so it resolves correctly -# regardless of the Headers/Versions/Current symlink chain used to reach it; -# macOS's BSD readlink has no reliable -f (canonicalize) flag to do that -# resolution ourselves. -HEADERS="$SDL3_LOCAL_BUILD/Headers" -if [ ! -e "$HEADERS/SDL_gpu.h" ]; then - echo "error: $HEADERS doesn't look like a built SDL3 framework (no SDL_gpu.h)." >&2 - echo " Is $SDL3_LOCAL_BUILD mid-rebuild? Finish 'cmake --build' there and re-run." >&2 - exit 1 -fi -if [ ! -e "$HEADERS/SDL3" ]; then - echo "==> Patching $HEADERS with a self-referential SDL3/ symlink" - ln -s . "$HEADERS/SDL3" -fi - -# The .stable cache is our template for Info.plist and the iOS slices, which -# the local checkout doesn't build. Make sure it exists. -[ -d "$STABLE" ] || "$SCRIPT_DIR/fetch-sdl3.sh" - -echo "==> Assembling Frameworks/SDL3.xcframework.local" -rm -rf "$LOCAL" -mkdir "$LOCAL" -cp "$STABLE/Info.plist" "$LOCAL/Info.plist" - -for slice in "$STABLE"/*/; do - slice="${slice%/}" - name="$(basename "$slice")" - case "$name" in - macos-*) - mkdir "$LOCAL/$name" - ln -s "$SDL3_LOCAL_BUILD" "$LOCAL/$name/SDL3.framework" - ;; - *) - # No local build for iOS/simulator slices; fall back to stable. - ln -s "../SDL3.xcframework.stable/$name" "$LOCAL/$name" - ;; - esac -done - -echo "==> Frameworks/SDL3.xcframework.local ready (macOS slice -> $SDL3_LOCAL_BUILD)" diff --git a/Frameworks/use-sdl3.sh b/Frameworks/use-sdl3.sh deleted file mode 100755 index 8e705bd..0000000 --- a/Frameworks/use-sdl3.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -# -# use-sdl3.sh — toggles Frameworks/SDL3.xcframework between the official -# stable release (fetch-sdl3.sh) and a locally-built SDL3 checkout -# (link-sdl3-local.sh). -# -# ObjectivelyGPU/Frameworks/SDL3.xcframework is the single copy of SDL3 that -# ObjectivelyGPU, ObjectivelyMVC, and Quetoo all link against (ObjectivelyMVC's -# own Frameworks/SDL3.xcframework is a symlink back to this one; Quetoo links -# this path directly). Running this script here is enough to flip SDL3 for -# all three projects at once -- nothing to run in the sibling repos. -# -# Usage: -# ./use-sdl3.sh stable # official release from libsdl.org (fetch-sdl3.sh) -# ./use-sdl3.sh local # your local SDL checkout (link-sdl3-local.sh) -# ./use-sdl3.sh # print which one is currently active -# -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -XCFRAMEWORK="$SCRIPT_DIR/SDL3.xcframework" - -status() { - if [ -L "$XCFRAMEWORK" ]; then - echo "SDL3.xcframework -> $(readlink "$XCFRAMEWORK")" - elif [ -d "$XCFRAMEWORK" ]; then - echo "SDL3.xcframework is a plain directory (not managed by use-sdl3.sh yet; run fetch-sdl3.sh)" - else - echo "SDL3.xcframework is not set up yet; run '$0 stable' or '$0 local'" - fi -} - -case "${1:-}" in - stable) - "$SCRIPT_DIR/fetch-sdl3.sh" - status - ;; - local) - "$SCRIPT_DIR/link-sdl3-local.sh" - ln -sfn SDL3.xcframework.local "$XCFRAMEWORK" - status - ;; - "") - status - ;; - *) - echo "usage: $0 [stable|local]" >&2 - exit 1 - ;; -esac diff --git a/ObjectivelyGPU.vs15/sdl3.targets b/ObjectivelyGPU.vs15/sdl3.targets index 912939e..18a4196 100644 --- a/ObjectivelyGPU.vs15/sdl3.targets +++ b/ObjectivelyGPU.vs15/sdl3.targets @@ -2,15 +2,16 @@ - 3.4.12 - $(MSBuildThisFileDirectory)libs\SDL3-$(SDL3Version)\ + ObjectivelyGPU + $(MSBuildThisFileDirectory)libs\SDL3-$(SDL3Tag)\ x86 x64 @@ -23,9 +24,9 @@ - + + Command="powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference = 'Stop'; $m = New-Object System.Threading.Mutex($false, 'Global\ObjectivelySDL3'); [void]$m.WaitOne(); try { if (-not (Test-Path '$(SDL3Dir)include\SDL3\SDL.h')) { New-Item -ItemType Directory -Force libs | Out-Null; Invoke-WebRequest -Uri 'https://github.com/jdolan/SDL/releases/download/$(SDL3Tag)/SDL3-devel-VC.zip' -OutFile 'libs\sdl3.zip'; Remove-Item -Recurse -Force -ErrorAction SilentlyContinue 'libs\sdl3'; Expand-Archive -Force 'libs\sdl3.zip' 'libs\sdl3'; $d = %40(Get-ChildItem -Directory 'libs\sdl3'); if ($d.Count -ne 1) { throw 'SDL3-devel-VC.zip: expected one top-level directory' }; Move-Item $d[0].FullName '$(SDL3Dir.TrimEnd('\'))'; Remove-Item -Recurse 'libs\sdl3', 'libs\sdl3.zip' } } finally { $m.ReleaseMutex() }"" /> diff --git a/ObjectivelyGPU.xcodeproj/project.pbxproj b/ObjectivelyGPU.xcodeproj/project.pbxproj index ebe948c..174013b 100644 --- a/ObjectivelyGPU.xcodeproj/project.pbxproj +++ b/ObjectivelyGPU.xcodeproj/project.pbxproj @@ -202,8 +202,6 @@ CE1643412FF47B7D00863996 /* guide.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = guide.md; sourceTree = ""; }; CE1643422FF47B7D00863996 /* Hello.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = Hello.gif; sourceTree = ""; }; CE1643432FF47B7D00863996 /* HelloCompute.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = HelloCompute.gif; sourceTree = ""; }; - CE6049BB30055F5700B1C1E3 /* link-sdl3-local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = "link-sdl3-local.sh"; path = "Frameworks/link-sdl3-local.sh"; sourceTree = ""; }; - CE6049BC30055F5700B1C1E3 /* use-sdl3.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = "use-sdl3.sh"; path = "Frameworks/use-sdl3.sh"; sourceTree = ""; }; CEA0030000000000000000F0 /* Objectively.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Objectively.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CEBA3F5E2FF30F1E00758CA6 /* Texture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Texture.h; sourceTree = ""; }; CEBA3F5F2FF30F1E00758CA6 /* Texture.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Texture.c; sourceTree = ""; }; @@ -217,7 +215,7 @@ CEBA3F692FF3211F00758CA6 /* Shader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Shader.h; sourceTree = ""; }; CEBA3F6A2FF3211F00758CA6 /* Shader.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Shader.c; sourceTree = ""; }; CEBA3F742FF330A700758CA6 /* ComputePipeline.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ComputePipeline.c; sourceTree = ""; }; - CEBA3F7C2FF36E2300758CA6 /* fetch-sdl3.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "fetch-sdl3.sh"; sourceTree = ""; }; + CEBA3F7C2FF36E2300758CA6 /* fetch-sdl3.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = "fetch-sdl3.sh"; path = "Frameworks/fetch-sdl3.sh"; sourceTree = ""; }; CECF83942FEF65EB00CB0CCA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; CECF83952FEF65FF00CB0CCA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; CECF83962FEF65FF00CB0CCA /* ObjectivelyGPU.pc.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = ObjectivelyGPU.pc.in; sourceTree = ""; }; @@ -386,9 +384,7 @@ children = ( CEA0030000000000000000F0 /* Objectively.framework */, AA000000000000000000EE01 /* SDL3.xcframework */, - CE6049BB30055F5700B1C1E3 /* link-sdl3-local.sh */, CEBA3F7C2FF36E2300758CA6 /* fetch-sdl3.sh */, - CE6049BC30055F5700B1C1E3 /* use-sdl3.sh */, ); name = Frameworks; sourceTree = ""; diff --git a/fetch-sdl3.sh b/fetch-sdl3.sh deleted file mode 100755 index d64a3a5..0000000 --- a/fetch-sdl3.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash -# -# fetch-sdl3.sh — downloads the official SDL3 Apple xcframework from libsdl.org -# on demand and caches it under Frameworks/. -# -# This mirrors the Windows VS build (ObjectivelyGPU.vs15/sdl3.targets): CI and -# local developers share a single code path. SDL3.xcframework is downloaded -# once, on demand, and is .gitignored. Bump SDL3_VERSION to upgrade; delete -# Frameworks/SDL3.xcframework to force a re-download. -# -set -euo pipefail - -SDL3_VERSION="${SDL3_VERSION:-3.4.2}" - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -XCFRAMEWORK="$SCRIPT_DIR/SDL3.xcframework" - -# Already cached? Nothing to do. -[ -d "$XCFRAMEWORK" ] && exit 0 - -# Serialize concurrent invocations (parallel target builds) on a lock dir, -# the shell equivalent of the Global mutex used by sdl3.targets on Windows. -LOCK="$SCRIPT_DIR/.sdl3.lock" -while ! mkdir "$LOCK" 2>/dev/null; do - sleep 1 -done - -TMP="$(mktemp -d)" -MNT="$TMP/mnt" - -cleanup() { - hdiutil detach "$MNT" -quiet 2>/dev/null || true - rm -rf "$TMP" - rmdir "$LOCK" 2>/dev/null || true -} -trap cleanup EXIT - -# Re-check after acquiring the lock; another build may have just finished. -[ -d "$XCFRAMEWORK" ] && exit 0 - -DMG_URL="https://github.com/libsdl-org/SDL/releases/download/release-$SDL3_VERSION/SDL3-$SDL3_VERSION.dmg" - -echo "==> Downloading SDL3 $SDL3_VERSION" -curl -fL --retry 3 "$DMG_URL" -o "$TMP/SDL3.dmg" - -echo "==> Mounting SDL3 $SDL3_VERSION" -mkdir -p "$MNT" -hdiutil attach "$TMP/SDL3.dmg" -nobrowse -quiet -mountpoint "$MNT" - -src="$(find "$MNT" -maxdepth 2 -name SDL3.xcframework -type d | head -1)" -if [ -z "$src" ]; then - echo "error: SDL3.xcframework not found in $DMG_URL" >&2 - exit 1 -fi - -echo "==> Caching SDL3.xcframework" -cp -R "$src" "$XCFRAMEWORK" - -echo "==> SDL3.xcframework $SDL3_VERSION ready at Frameworks/SDL3.xcframework" From 85e5aae5613e7fb1daad0848dd1a91d0169424d6 Mon Sep 17 00:00:00 2001 From: Jay Dolan Date: Wed, 30 Sep 2026 12:54:49 -0400 Subject: [PATCH 2/4] Warn when SDL3 lacks the query API Without SDL_GPU_QUERY_API, QueryPool compiles to a stub and occlusion queries are disabled, with no other sign in the build. A compiler warning makes a build against stock SDL3 visible. See jdolan/quetoo#1093. Co-Authored-By: Claude Opus 5.5 (1M context) --- Sources/ObjectivelyGPU/QueryPool.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Sources/ObjectivelyGPU/QueryPool.c b/Sources/ObjectivelyGPU/QueryPool.c index 4c9ea54..8f76421 100644 --- a/Sources/ObjectivelyGPU/QueryPool.c +++ b/Sources/ObjectivelyGPU/QueryPool.c @@ -26,6 +26,14 @@ #include "QueryPool.h" #include "RenderDevice.h" +#ifndef SDL_GPU_QUERY_API + #if defined(_MSC_VER) + #pragma message("SDL3 lacks SDL_GPU_QUERY_API: occlusion queries are disabled") + #else + #warning "SDL3 lacks SDL_GPU_QUERY_API: occlusion queries are disabled" + #endif +#endif + #define _Class _QueryPool #pragma mark - Object From da3a9dc2f8131c2ebbb447f04bd6e50be983b6b8 Mon Sep 17 00:00:00 2001 From: Jay Dolan Date: Wed, 30 Sep 2026 13:11:04 -0400 Subject: [PATCH 3/4] Check that the SDL3 release matches the tag before download fetch-sdl3.sh stamped the cache with the tag's commit, even if the publish workflow had not yet rebuilt the release for a moved tag, so the old assets stayed cached for good. It now reads the commit from the release notes and fails if it differs from the tag. It also resolves annotated tags to their commit, and removes the stamp before it replaces the cache. sdl3.targets now removes a partial libs\SDL3-ObjectivelyGPU before the move, which otherwise nested the new directory inside the old one. See jdolan/quetoo#1093. Co-Authored-By: Claude Opus 5.5 (1M context) --- Frameworks/fetch-sdl3.sh | 14 ++++++++++++-- ObjectivelyGPU.vs15/sdl3.targets | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Frameworks/fetch-sdl3.sh b/Frameworks/fetch-sdl3.sh index 173211b..07edce1 100755 --- a/Frameworks/fetch-sdl3.sh +++ b/Frameworks/fetch-sdl3.sh @@ -5,7 +5,9 @@ # # The whole stack (ObjectivelyGPU, ObjectivelyMVC, Quetoo) pins SDL3 to one tag in jdolan/SDL, which # carries the SDL_gpu query API. The tag's commit SHA is stored next to the cache, so moving the tag -# causes a new download. This mirrors ObjectivelyGPU.vs15/sdl3.targets on Windows. +# causes a new download. The release notes name the commit its assets were built from; if that is +# not the tag's commit, the publish workflow has not run for the moved tag yet, and this script +# fails. This mirrors ObjectivelyGPU.vs15/sdl3.targets on Windows. # set -euo pipefail @@ -16,7 +18,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" XCFRAMEWORK="$SCRIPT_DIR/SDL3.xcframework" STAMP="$SCRIPT_DIR/SDL3.xcframework.sha" -sha="$(git ls-remote "https://github.com/$SDL3_REPO.git" "refs/tags/$SDL3_TAG" | cut -f1)" +sha="$(git ls-remote "https://github.com/$SDL3_REPO.git" "refs/tags/$SDL3_TAG" "refs/tags/$SDL3_TAG^{}" | tail -1 | cut -f1)" if [ -z "$sha" ]; then echo "error: tag $SDL3_TAG not found in $SDL3_REPO" >&2 exit 1 @@ -30,6 +32,13 @@ if cached; then exit 0 fi +released="$(curl -fsSL "https://api.github.com/repos/$SDL3_REPO/releases/tags/$SDL3_TAG" | grep -Eo 'at [0-9a-f]{40}' | head -1 | cut -c4- || true)" +if [ "$released" != "$sha" ]; then + echo "error: the $SDL3_TAG release of $SDL3_REPO was built from ${released:-an unknown commit}, not $sha" >&2 + echo "error: run: gh workflow run objectivelygpu.yml -R $SDL3_REPO" >&2 + exit 1 +fi + # Serialize concurrent invocations (parallel target builds) on a lock dir, # the shell equivalent of the Global mutex used by sdl3.targets on Windows. LOCK="$SCRIPT_DIR/.sdl3.lock" @@ -69,6 +78,7 @@ fi # Replace the cache, and the .stable/.local directories of the former use-sdl3.sh layout. echo "==> Caching SDL3.xcframework" +rm -f "$STAMP" rm -rf "$XCFRAMEWORK" "$SCRIPT_DIR/SDL3.xcframework.stable" "$SCRIPT_DIR/SDL3.xcframework.local" cp -R "$src" "$XCFRAMEWORK" echo "$sha" > "$STAMP" diff --git a/ObjectivelyGPU.vs15/sdl3.targets b/ObjectivelyGPU.vs15/sdl3.targets index 18a4196..fe261c8 100644 --- a/ObjectivelyGPU.vs15/sdl3.targets +++ b/ObjectivelyGPU.vs15/sdl3.targets @@ -26,7 +26,7 @@ Condition="!Exists('$(SDL3Dir)include\SDL3\SDL.h')"> + Command="powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference = 'Stop'; $m = New-Object System.Threading.Mutex($false, 'Global\ObjectivelySDL3'); [void]$m.WaitOne(); try { if (-not (Test-Path '$(SDL3Dir)include\SDL3\SDL.h')) { New-Item -ItemType Directory -Force libs | Out-Null; Invoke-WebRequest -Uri 'https://github.com/jdolan/SDL/releases/download/$(SDL3Tag)/SDL3-devel-VC.zip' -OutFile 'libs\sdl3.zip'; Remove-Item -Recurse -Force -ErrorAction SilentlyContinue 'libs\sdl3'; Expand-Archive -Force 'libs\sdl3.zip' 'libs\sdl3'; $d = %40(Get-ChildItem -Directory 'libs\sdl3'); if ($d.Count -ne 1) { throw 'SDL3-devel-VC.zip: expected one top-level directory' }; Remove-Item -Recurse -Force -ErrorAction SilentlyContinue '$(SDL3Dir.TrimEnd('\'))'; Move-Item $d[0].FullName '$(SDL3Dir.TrimEnd('\'))'; Remove-Item -Recurse 'libs\sdl3', 'libs\sdl3.zip' } } finally { $m.ReleaseMutex() }"" /> From 3ccc4dc715cb18b5cc6c4d7f8028d13ac6066cd2 Mon Sep 17 00:00:00 2001 From: Jay Dolan Date: Wed, 30 Sep 2026 13:14:45 -0400 Subject: [PATCH 4/4] Document that the SDL3 publish run must finish first gh workflow run only queues the run. Until it finishes, the moved tag's release still serves the previous assets. Co-Authored-By: Claude Opus 5.5 (1M context) --- Documentation/install.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/install.md b/Documentation/install.md index dae5ddb..1e3a170 100644 --- a/Documentation/install.md +++ b/Documentation/install.md @@ -28,11 +28,14 @@ ObjectivelyMVC and Quetoo MUST build against that tag. Against any other SDL3, O * Windows (Visual Studio): `ObjectivelyGPU.vs15/sdl3.targets` downloads `SDL3-devel-VC.zip` from the tag's release on first build. Delete `ObjectivelyGPU.vs15/libs/` to pick up a moved tag. -To change the SDL3 revision for the whole stack, move the tag, then publish its artifacts: +To change the SDL3 revision for the whole stack, move the tag, then publish its artifacts. The publish run +MUST finish before any consumer builds, because until then the release still serves the previous assets. +`fetch-sdl3.sh` refuses a release that was built from another commit. ```sh git tag -f ObjectivelyGPU && git push -f origin ObjectivelyGPU gh workflow run objectivelygpu.yml -R jdolan/SDL +gh run watch -R jdolan/SDL --exit-status "$(gh run list -R jdolan/SDL -w objectivelygpu.yml -L 1 --json databaseId -q '.[0].databaseId')" ``` ## Building