mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 12:40:21 +02:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dd889b35b | |||
| 032f894f7f | |||
| 9922e235c6 | |||
| 667267d9bb | |||
| 6588901e9a | |||
| 142d1358dd |
@@ -26,64 +26,6 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
macos-changes:
|
|
||||||
name: detect macOS changes
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
changed: ${{ steps.paths.outputs.changed }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- id: paths
|
|
||||||
env:
|
|
||||||
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
||||||
HEAD_SHA: ${{ github.sha }}
|
|
||||||
run: |
|
|
||||||
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
|
|
||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(conf\.lua$|scripts/(build\.sh|build_love_macos\.sh|run\.sh|setup\.sh)$|Play-Mac\.command$|mobile/macos/|src/core/SaveData\.lua$|\.github/workflows/(ci|release)\.yml$)'; then
|
|
||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
macos-build:
|
|
||||||
name: macOS LÖVE 12 build
|
|
||||||
needs: macos-changes
|
|
||||||
if: needs.macos-changes.outputs.changed == 'true'
|
|
||||||
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
- name: Build LÖVE 12 macOS runtime
|
|
||||||
run: scripts/build_love_macos.sh --fetch
|
|
||||||
- name: Build and verify macOS app
|
|
||||||
env:
|
|
||||||
LOVE_APP: ${{ github.workspace }}/.bazinga/love12/love.app
|
|
||||||
MAC_STAGE_DIR: ${{ runner.temp }}/gen1recomp-mac-stage
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
scripts/build.sh mac --no-notarize --identity - --version 0.0.0
|
|
||||||
unzip -tqq 'dist/mac/gen1recomp++-macos.zip'
|
|
||||||
app="$MAC_STAGE_DIR/gen1recomp++.app"
|
|
||||||
[ -d "$app" ]
|
|
||||||
[ -x "$app/Contents/MacOS/gen1recomp++" ]
|
|
||||||
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$app/Contents/Info.plist")" = 'gen1recomp++' ]
|
|
||||||
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleDisplayName' "$app/Contents/Info.plist")" = 'gen1recomp++' ]
|
|
||||||
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$app/Contents/Info.plist")" = 'com.theboisclub.gen1recompplusplus' ]
|
|
||||||
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$app/Contents/Info.plist")" = 0.0.0 ]
|
|
||||||
codesign --verify --deep --strict "$app"
|
|
||||||
otool -L "$app/Contents/Frameworks/love.framework/love" | grep -q '/Metal.framework/'
|
|
||||||
- name: Upload macOS build
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: gen1recomp++-macos
|
|
||||||
path: dist/mac/gen1recomp++-macos.zip
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
ios-changes:
|
ios-changes:
|
||||||
name: detect iOS changes
|
name: detect iOS changes
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -178,7 +120,7 @@ jobs:
|
|||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(scripts/build_switch\.sh$|scripts/switch/|docs/switch-.*\.md$|tests/switch_ci_workflows_test\.lua$|tests/switch_transfer_docs_test\.lua$|\.github/workflows/(ci|release|platform-artifact-comment)\.yml$|src/core/(NxAssetOverlay|Platform|GameVersion)\.lua$|src/import/CacheFs\.lua$|tests/engine/(assets_version_fallback|nx_generated_guard|nx_yellow_boot|switch_diagnostics|cache_fs_gold_nx_load)_test\.lua$|tests/engine/platform_nx)'; then
|
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(scripts/build_switch\.sh$|scripts/switch/|docs/switch-.*\.md$|tests/switch_ci_workflows_test\.lua$|tests/switch_transfer_docs_test\.lua$|\.github/workflows/(ci|release|switch-artifact-comment)\.yml$|src/core/(NxAssetOverlay|Platform|GameVersion)\.lua$|src/import/CacheFs\.lua$|tests/engine/(assets_version_fallback|nx_generated_guard|nx_yellow_boot|switch_diagnostics|cache_fs_gold_nx_load)_test\.lua$|tests/engine/platform_nx)'; then
|
||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
name: iOS artifact comment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [ci]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
comment:
|
||||||
|
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- id: artifact
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
RUN_ID: ${{ github.event.workflow_run.id }}
|
||||||
|
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||||
|
HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }}
|
||||||
|
run: |
|
||||||
|
artifact_id="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts" --jq '.artifacts[] | select(.name == "gen1recomp++-ios-ipa") | .id')"
|
||||||
|
[ -n "$artifact_id" ] || exit 0
|
||||||
|
head_owner="${HEAD_REPOSITORY%%/*}"
|
||||||
|
pr_number="$(gh api "repos/$GITHUB_REPOSITORY/pulls?state=open&head=$head_owner:$HEAD_BRANCH" --jq '.[0].number // empty')"
|
||||||
|
[ -n "$pr_number" ] || exit 0
|
||||||
|
echo "artifact_url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts/$artifact_id" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
|
||||||
|
# Upsert via comment-tag only — do not delete-all bot comments (clobbers Switch).
|
||||||
|
- name: Get build info
|
||||||
|
id: build-info
|
||||||
|
env:
|
||||||
|
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||||
|
run: |
|
||||||
|
commit_hash="$(printf '%s' "$HEAD_SHA" | cut -c1-7)"
|
||||||
|
build_time="$(date "+%Y-%m-%d %H:%M:%S")"
|
||||||
|
echo "hash=$commit_hash" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "time=$build_time" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: comment iOS artifact
|
||||||
|
if: steps.artifact.outputs.pr_number != ''
|
||||||
|
uses: thollander/actions-comment-pull-request@v3
|
||||||
|
with:
|
||||||
|
message: |
|
||||||
|
[gen1recomp++.ipa](${{ steps.artifact.outputs.artifact_url }})
|
||||||
|
|
||||||
|
**Commit**: [#${{ steps.build-info.outputs.hash }}](https://github.com/${{ github.event.workflow_run.head_repository.full_name }}/commit/${{ github.event.workflow_run.head_sha }})
|
||||||
|
**Build Time**: `${{ steps.build-info.outputs.time }}`
|
||||||
|
|
||||||
|
<sub>This comment was automatically generated. [View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }})</sub>
|
||||||
|
pr-number: ${{ steps.artifact.outputs.pr_number }}
|
||||||
|
comment-tag: ios-build-result
|
||||||
|
github-token: ${{ github.token }}
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
name: platform artifact comment
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_run:
|
|
||||||
workflows: [ci]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
comment:
|
|
||||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- id: artifacts
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
RUN_ID: ${{ github.event.workflow_run.id }}
|
|
||||||
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
|
||||||
HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
artifacts="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts")"
|
|
||||||
head_owner="${HEAD_REPOSITORY%%/*}"
|
|
||||||
pr_number="$(gh api "repos/$GITHUB_REPOSITORY/pulls?state=open&head=$head_owner:$HEAD_BRANCH" --jq '.[0].number // empty')"
|
|
||||||
[ -n "$pr_number" ] || exit 0
|
|
||||||
|
|
||||||
message="## CI build artifacts"
|
|
||||||
found=0
|
|
||||||
while IFS='|' read -r platform artifact_name artifact_file; do
|
|
||||||
artifact_id="$(printf '%s' "$artifacts" | jq -r --arg name "$artifact_name" '[.artifacts[] | select(.name == $name) | .id][0] // empty')"
|
|
||||||
if [ -n "$artifact_id" ] && [ "$artifact_id" != null ]; then
|
|
||||||
artifact_url="https://github.com/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts/$artifact_id"
|
|
||||||
message+=$'\n'"- **$platform**: [$artifact_file]($artifact_url)"
|
|
||||||
found=1
|
|
||||||
fi
|
|
||||||
done <<'ARTIFACTS'
|
|
||||||
macOS|gen1recomp++-macos|gen1recomp++-macos.zip
|
|
||||||
iOS|gen1recomp++-ios-ipa|gen1recomp++.ipa
|
|
||||||
Nintendo Switch|gen1recomp-switch-nro|gen1recomp-switch.nro
|
|
||||||
Xbox UWP|gen1recomp-xbox-uwp|gen1recomp-xbox-uwp.zip
|
|
||||||
Linux arm64|gen1recomp-linux-arm64|gen1recomp-linux-arm64.AppImage
|
|
||||||
ARTIFACTS
|
|
||||||
|
|
||||||
[ "$found" -eq 1 ] || exit 0
|
|
||||||
commit_hash="$(printf '%s' "${{ github.event.workflow_run.head_sha }}" | cut -c1-7)"
|
|
||||||
build_time="$(date -u "+%Y-%m-%d %H:%M:%S UTC")"
|
|
||||||
message+=$'\n\n'"**Commit**: [#$commit_hash](https://github.com/$HEAD_REPOSITORY/commit/${{ github.event.workflow_run.head_sha }})"
|
|
||||||
message+=$'\n'"**Build Time**: \`$build_time\`"
|
|
||||||
message+=$'\n\n'"<sub>This comment was automatically generated. [View workflow run](https://github.com/$GITHUB_REPOSITORY/actions/runs/$RUN_ID)</sub>"
|
|
||||||
|
|
||||||
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
|
|
||||||
{
|
|
||||||
echo 'message<<BUILD_MESSAGE'
|
|
||||||
printf '%s\n' "$message"
|
|
||||||
echo 'BUILD_MESSAGE'
|
|
||||||
} >> "$GITHUB_OUTPUT"
|
|
||||||
- name: comment platform artifacts
|
|
||||||
if: steps.artifacts.outputs.pr_number != ''
|
|
||||||
uses: thollander/actions-comment-pull-request@v3
|
|
||||||
with:
|
|
||||||
message: ${{ steps.artifacts.outputs.message }}
|
|
||||||
pr-number: ${{ steps.artifacts.outputs.pr_number }}
|
|
||||||
comment-tag: platform-build-result
|
|
||||||
github-token: ${{ github.token }}
|
|
||||||
@@ -344,16 +344,9 @@ jobs:
|
|||||||
echo "Identities available to codesign:"
|
echo "Identities available to codesign:"
|
||||||
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
|
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
|
||||||
|
|
||||||
- name: Build LÖVE 12 macOS runtime
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
scripts/build_love_macos.sh --fetch
|
|
||||||
|
|
||||||
- name: Build macOS + Windows + Linux
|
- name: Build macOS + Windows + Linux
|
||||||
env:
|
env:
|
||||||
GEN1TLS_DLL: ${{ github.workspace }}/dist/native/win-x64/gen1tls.dll
|
GEN1TLS_DLL: ${{ github.workspace }}/dist/native/win-x64/gen1tls.dll
|
||||||
LOVE_APP: ${{ github.workspace }}/.bazinga/love12/love.app
|
|
||||||
MAC_STAGE_DIR: ${{ runner.temp }}/gen1recomp-mac-stage
|
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
# Sign in-build (identity auto-detected from the temp keychain);
|
# Sign in-build (identity auto-detected from the temp keychain);
|
||||||
@@ -435,8 +428,8 @@ jobs:
|
|||||||
set -a; . "$ci_dir/notary.env"; set +a
|
set -a; . "$ci_dir/notary.env"; set +a
|
||||||
echo "::add-mask::$APPLE_APP_PASSWORD"
|
echo "::add-mask::$APPLE_APP_PASSWORD"
|
||||||
|
|
||||||
app="$RUNNER_TEMP/gen1recomp-mac-stage/gen1recomp++.app"
|
app=".bazinga/work/gen1recomp.app"
|
||||||
zip="dist/mac/gen1recomp++-macos.zip"
|
zip="dist/mac/gen1recomp-macos.zip"
|
||||||
[ -d "$app" ] || { echo "::error::signed app not found at $app"; exit 1; }
|
[ -d "$app" ] || { echo "::error::signed app not found at $app"; exit 1; }
|
||||||
if [ -z "${APPLE_ID:-}" ] || [ -z "${APPLE_APP_PASSWORD:-}" ] || [ -z "${APPLE_TEAM_ID:-}" ]; then
|
if [ -z "${APPLE_ID:-}" ] || [ -z "${APPLE_APP_PASSWORD:-}" ] || [ -z "${APPLE_TEAM_ID:-}" ]; then
|
||||||
echo "::error::notary.env is missing APPLE_ID / APPLE_APP_PASSWORD / APPLE_TEAM_ID."
|
echo "::error::notary.env is missing APPLE_ID / APPLE_APP_PASSWORD / APPLE_TEAM_ID."
|
||||||
@@ -481,7 +474,7 @@ jobs:
|
|||||||
outdir="dist/release"
|
outdir="dist/release"
|
||||||
rm -rf "$outdir"
|
rm -rf "$outdir"
|
||||||
mkdir -p "$outdir"
|
mkdir -p "$outdir"
|
||||||
cp "dist/mac/gen1recomp++-macos.zip" "$outdir/gen1recomp++-${v}-macos.zip"
|
cp "dist/mac/gen1recomp-macos.zip" "$outdir/gen1recomp-${v}-macos.zip"
|
||||||
cp "dist/win/gen1recomp-win64.zip" "$outdir/gen1recomp-${v}-windows.zip"
|
cp "dist/win/gen1recomp-win64.zip" "$outdir/gen1recomp-${v}-windows.zip"
|
||||||
cp "dist/linux/gen1recomp-linux.zip" "$outdir/gen1recomp-${v}-linux.zip"
|
cp "dist/linux/gen1recomp-linux.zip" "$outdir/gen1recomp-${v}-linux.zip"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
name: Switch artifact comment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [ci]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
comment:
|
||||||
|
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- id: artifact
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
RUN_ID: ${{ github.event.workflow_run.id }}
|
||||||
|
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||||
|
HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }}
|
||||||
|
run: |
|
||||||
|
artifact_id="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts" --jq '.artifacts[] | select(.name == "gen1recomp-switch-nro") | .id')"
|
||||||
|
[ -n "$artifact_id" ] || exit 0
|
||||||
|
head_owner="${HEAD_REPOSITORY%%/*}"
|
||||||
|
pr_number="$(gh api "repos/$GITHUB_REPOSITORY/pulls?state=open&head=$head_owner:$HEAD_BRANCH" --jq '.[0].number // empty')"
|
||||||
|
[ -n "$pr_number" ] || exit 0
|
||||||
|
echo "artifact_url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts/$artifact_id" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
|
||||||
|
# Upsert via comment-tag only — do not delete-all bot comments (clobbers iOS).
|
||||||
|
- name: Get build info
|
||||||
|
id: build-info
|
||||||
|
env:
|
||||||
|
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||||
|
run: |
|
||||||
|
commit_hash="$(printf '%s' "$HEAD_SHA" | cut -c1-7)"
|
||||||
|
build_time="$(date "+%Y-%m-%d %H:%M:%S")"
|
||||||
|
echo "hash=$commit_hash" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "time=$build_time" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: comment Switch artifact
|
||||||
|
if: steps.artifact.outputs.pr_number != ''
|
||||||
|
uses: thollander/actions-comment-pull-request@v3
|
||||||
|
with:
|
||||||
|
message: |
|
||||||
|
[gen1recomp-switch.nro](${{ steps.artifact.outputs.artifact_url }})
|
||||||
|
|
||||||
|
**Commit**: [#${{ steps.build-info.outputs.hash }}](https://github.com/${{ github.event.workflow_run.head_repository.full_name }}/commit/${{ github.event.workflow_run.head_sha }})
|
||||||
|
**Build Time**: `${{ steps.build-info.outputs.time }}`
|
||||||
|
|
||||||
|
<sub>This comment was automatically generated. [View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }})</sub>
|
||||||
|
pr-number: ${{ steps.artifact.outputs.pr_number }}
|
||||||
|
comment-tag: switch-build-result
|
||||||
|
github-token: ${{ github.token }}
|
||||||
+18
-13
@@ -27,15 +27,9 @@ ask() { # ask "question" -> yes by default
|
|||||||
printf '\n \033[1mPokémon Red - LÖVE2D port\033[0m\n\n'
|
printf '\n \033[1mPokémon Red - LÖVE2D port\033[0m\n\n'
|
||||||
|
|
||||||
have_love() {
|
have_love() {
|
||||||
local app version
|
command -v love >/dev/null 2>&1 && return 0
|
||||||
for app in ".bazinga/love12/love.app" "/Applications/love12.app" "$HOME/Applications/love12.app" \
|
[ -x "/Applications/love.app/Contents/MacOS/love" ] && return 0
|
||||||
"/Applications/love.app" "$HOME/Applications/love.app"; do
|
[ -x "$HOME/Applications/love.app/Contents/MacOS/love" ] && return 0
|
||||||
[ -x "$app/Contents/MacOS/love" ] || continue
|
|
||||||
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$app/Contents/Info.plist" 2>/dev/null || true)"
|
|
||||||
printf '%s' "$version" | grep -Eq '^12(\.|$)' || continue
|
|
||||||
otool -L "$app/Contents/Frameworks/love.framework/love" 2>/dev/null \
|
|
||||||
| grep -q '/Metal.framework/' && return 0
|
|
||||||
done
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,11 +57,22 @@ if ! command -v python3 >/dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! have_love && ! command -v xcodebuild >/dev/null 2>&1; then
|
# ----------------------------------------------------------------- Homebrew
|
||||||
warn "LÖVE 12 is not installed and Xcode is required to build it for macOS."
|
if ! have_love && ! command -v brew >/dev/null 2>&1 \
|
||||||
warn "Install Xcode from the App Store, launch it once, then run this again."
|
&& [ ! -x /opt/homebrew/bin/brew ] && [ ! -x /usr/local/bin/brew ]; then
|
||||||
pause_exit 1
|
warn "LÖVE (the game engine) is not installed; the easiest installer is Homebrew"
|
||||||
|
if ask "Install Homebrew now? (asks for your macOS password)"; then
|
||||||
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" \
|
||||||
|
|| { err "Homebrew install failed"; pause_exit 1; }
|
||||||
|
else
|
||||||
|
warn "OK, download LÖVE 11.x yourself from https://love2d.org,"
|
||||||
|
warn "drop love.app into /Applications, then run this again."
|
||||||
|
pause_exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
# make brew visible in THIS shell (fresh installs aren't on PATH yet)
|
||||||
|
[ -x /opt/homebrew/bin/brew ] && eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||||
|
[ -x /usr/local/bin/brew ] && eval "$(/usr/local/bin/brew shellenv)"
|
||||||
|
|
||||||
# ------------------------------------------------------------------- build
|
# ------------------------------------------------------------------- build
|
||||||
echo
|
echo
|
||||||
|
|||||||
@@ -194,9 +194,8 @@ By default the game keeps your save, options, and the private ROM-derived
|
|||||||
data cache in your OS's normal per-user app data folder. To keep everything
|
data cache in your OS's normal per-user app data folder. To keep everything
|
||||||
next to the game instead (handy for a USB stick or portable drive you carry
|
next to the game instead (handy for a USB stick or portable drive you carry
|
||||||
between computers), drop an empty file named `portable.txt` next to the app
|
between computers), drop an empty file named `portable.txt` next to the app
|
||||||
(next to `gen1recomp++.app` on macOS or `gen1recomp.exe` on Windows, or next
|
(next to `gen1recomp.app`/`.exe`, or next to `main.lua`/`conf.lua` when
|
||||||
to `main.lua`/`conf.lua` when running from source), then launch the game.
|
running from source), then launch the game. Portable mode is desktop-only
|
||||||
Portable mode is desktop-only
|
|
||||||
(Windows, Linux, macOS); it has no effect on Android or iOS, where the app
|
(Windows, Linux, macOS); it has no effect on Android or iOS, where the app
|
||||||
runs from a read-only package.
|
runs from a read-only package.
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,26 @@ get_controls
|
|||||||
[ -f "${controlfolder}/mod_${CFW_NAME}.txt" ] && source "${controlfolder}/mod_${CFW_NAME}.txt"
|
[ -f "${controlfolder}/mod_${CFW_NAME}.txt" ] && source "${controlfolder}/mod_${CFW_NAME}.txt"
|
||||||
|
|
||||||
GAMEDIR="$SHDIR/gen1recomp"
|
GAMEDIR="$SHDIR/gen1recomp"
|
||||||
|
# Anbernic stock keeps the launcher and the game folder side by side, so the
|
||||||
|
# SHDIR-relative path above is correct there and is tried first.
|
||||||
|
#
|
||||||
|
# Other firmwares (muOS, and PortMaster's layout on several devices) keep
|
||||||
|
# launcher scripts and port data in SEPARATE trees -- scripts under roms/ports,
|
||||||
|
# data under ports -- so the sibling folder holds no game.
|
||||||
|
#
|
||||||
|
# Probe for the BINARY, not the directory: on a split layout this script has
|
||||||
|
# usually already created "$SHDIR/gen1recomp/conf" and log.txt on an earlier
|
||||||
|
# failed run (see mkdir/tee below), so an existence test matches a decoy of our
|
||||||
|
# own making. Stock is unaffected -- its sibling holds the real binary and wins
|
||||||
|
# on the first test.
|
||||||
|
if [ ! -f "$GAMEDIR/bin/love.aarch64" ]; then
|
||||||
|
for candidate in "/$directory/ports/gen1recomp" \
|
||||||
|
"/mnt/sdcard/ports/gen1recomp" \
|
||||||
|
"/mnt/mmc/ports/gen1recomp" \
|
||||||
|
"/roms/ports/gen1recomp"; do
|
||||||
|
if [ -f "$candidate/bin/love.aarch64" ]; then GAMEDIR="$candidate"; break; fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
CONFDIR="$GAMEDIR/conf"
|
CONFDIR="$GAMEDIR/conf"
|
||||||
mkdir -p "$CONFDIR"
|
mkdir -p "$CONFDIR"
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ function love.conf(t)
|
|||||||
t.window.minwidth = 480
|
t.window.minwidth = 480
|
||||||
t.window.minheight = 360
|
t.window.minheight = 360
|
||||||
end
|
end
|
||||||
t.version = (love._os == "iOS" or love._os == "OS X") and "12.0" or "11.5"
|
t.version = love._os == "iOS" and "12.0" or "11.5"
|
||||||
t.window.vsync = 1
|
t.window.vsync = 1
|
||||||
t.modules.audio = not companion
|
t.modules.audio = not companion
|
||||||
t.modules.joystick = not companion
|
t.modules.joystick = not companion
|
||||||
|
|||||||
@@ -188,8 +188,8 @@ or the Switch-related workflow YAML), CI runs:
|
|||||||
head is that repo (same-repo push/PR). Fork CI never runs fused. Fork PRs into the main repo also skip Switch fused (offline selftest still runs) so untrusted head code is not executed on the self-hosted Mac; iOS device build eligibility is unchanged. Fused also waits for a successful offline selftest before starting on the Mac runner.
|
head is that repo (same-repo push/PR). Fork CI never runs fused. Fork PRs into the main repo also skip Switch fused (offline selftest still runs) so untrusted head code is not executed on the self-hosted Mac; iOS device build eligibility is unchanged. Fused also waits for a successful offline selftest before starting on the Mac runner.
|
||||||
3. On successful PR fused builds, a follow-up workflow posts a PR comment
|
3. On successful PR fused builds, a follow-up workflow posts a PR comment
|
||||||
linking the Actions artifact named `gen1recomp-switch-nro`
|
linking the Actions artifact named `gen1recomp-switch-nro`
|
||||||
(comment tag `platform-build-result`; see
|
(comment tag `switch-build-result`; see
|
||||||
`.github/workflows/platform-artifact-comment.yml`).
|
`.github/workflows/switch-artifact-comment.yml`).
|
||||||
|
|
||||||
Unrelated PRs do not burn the self-hosted Mac on Switch packaging.
|
Unrelated PRs do not burn the self-hosted Mac on Switch packaging.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
a5522634f1e581a1ebab73bf3ab4bd7a853b7a3e
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
97d4465e8c81099f79696ea4b4bb8b1f9083bc1a
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
12.0
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# macOS build
|
|
||||||
|
|
||||||
The desktop app uses the pinned LÖVE 12 runtime built from the LÖVE source
|
|
||||||
tree and the matching Apple dependency repository. The runtime enables Metal
|
|
||||||
and is fused into the branded `gen1recomp++.app` bundle.
|
|
||||||
|
|
||||||
Build the runtime and desktop app from the repository root:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
scripts/build_love_macos.sh --fetch
|
|
||||||
LOVE_APP="$PWD/.bazinga/love12/love.app" scripts/build.sh mac --no-notarize --identity -
|
|
||||||
```
|
|
||||||
|
|
||||||
The source and dependency revisions are recorded in `LOVE_SOURCE_REF` and
|
|
||||||
`APPLE_DEPENDENCIES_REF`. Delete `.bazinga/love12/source` or use `--clean`
|
|
||||||
when changing those pins.
|
|
||||||
|
|
||||||
The packaged executable is `gen1recomp++` inside `gen1recomp++.app`, and the
|
|
||||||
bundle declares LÖVE 12.0 compatibility.
|
|
||||||
+15
-75
@@ -8,7 +8,7 @@
|
|||||||
# [--notary-profile NAME] [--no-notarize]
|
# [--notary-profile NAME] [--no-notarize]
|
||||||
# [--release] # ios only: release config instead of debug
|
# [--release] # ios only: release config instead of debug
|
||||||
#
|
#
|
||||||
# Output: dist/mac/gen1recomp++-macos.zip
|
# Output: dist/mac/gen1recomp-macos.zip
|
||||||
# dist/win/gen1recomp-win64.zip
|
# dist/win/gen1recomp-win64.zip
|
||||||
# dist/linux/gen1recomp-linux.zip (fused x86_64 AppImage)
|
# dist/linux/gen1recomp-linux.zip (fused x86_64 AppImage)
|
||||||
# dist/android/debug/*.apk (full gradle output stays under
|
# dist/android/debug/*.apk (full gradle output stays under
|
||||||
@@ -27,18 +27,13 @@ ENTITLEMENTS="$ROOT/scripts/macos-entitlements.plist"
|
|||||||
|
|
||||||
APP_NAME="gen1recomp"
|
APP_NAME="gen1recomp"
|
||||||
BUNDLE_ID="com.theboisclub.pokemonred"
|
BUNDLE_ID="com.theboisclub.pokemonred"
|
||||||
MAC_APP_NAME="gen1recomp++"
|
|
||||||
MAC_BUNDLE_ID="com.theboisclub.gen1recompplusplus"
|
|
||||||
LOVE_VERSION="11.5"
|
LOVE_VERSION="11.5"
|
||||||
LOVE_MAC_VERSION="$(tr -d '[:space:]' < "$ROOT/mobile/macos/LOVE_VERSION" 2>/dev/null || echo 12.0)"
|
|
||||||
LOVE_MAC_APP="$HERE/love12/love.app"
|
|
||||||
VERSION="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo dev)"
|
VERSION="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo dev)"
|
||||||
VERSION_EXPLICIT=false
|
VERSION_EXPLICIT=false
|
||||||
IDENTITY=""
|
IDENTITY=""
|
||||||
TARGET="all"
|
TARGET="all"
|
||||||
NOTARY_PROFILE="notary-profile"
|
NOTARY_PROFILE="notary-profile"
|
||||||
NOTARIZE=true
|
NOTARIZE=true
|
||||||
FETCH_MAC_RUNTIME=false
|
|
||||||
IOS_RELEASE=false
|
IOS_RELEASE=false
|
||||||
IOS_IPA=false
|
IOS_IPA=false
|
||||||
|
|
||||||
@@ -46,22 +41,6 @@ say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
|||||||
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
|
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
|
||||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
strip_bundle_metadata() {
|
|
||||||
local bundle="$1"
|
|
||||||
xattr -rc "$bundle"
|
|
||||||
xattr -rd com.apple.FinderInfo "$bundle" 2>/dev/null || true
|
|
||||||
xattr -rd 'com.apple.fileprovider.fpfs#P' "$bundle" 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
valid_love12_app() {
|
|
||||||
local app="$1" version
|
|
||||||
[ -x "$app/Contents/MacOS/love" ] || return 1
|
|
||||||
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$app/Contents/Info.plist" 2>/dev/null || true)"
|
|
||||||
printf '%s' "$version" | grep -Eq '^12(\.|$)' || return 1
|
|
||||||
otool -L "$app/Contents/Frameworks/love.framework/love" 2>/dev/null \
|
|
||||||
| grep -q '/Metal.framework/'
|
|
||||||
}
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
mac|win|linux|android|ios|all) TARGET="$1" ;;
|
mac|win|linux|android|ios|all) TARGET="$1" ;;
|
||||||
@@ -69,7 +48,6 @@ while [ $# -gt 0 ]; do
|
|||||||
--identity) IDENTITY="$2"; shift ;;
|
--identity) IDENTITY="$2"; shift ;;
|
||||||
--notary-profile) NOTARY_PROFILE="$2"; shift ;;
|
--notary-profile) NOTARY_PROFILE="$2"; shift ;;
|
||||||
--no-notarize) NOTARIZE=false ;;
|
--no-notarize) NOTARIZE=false ;;
|
||||||
--fetch) FETCH_MAC_RUNTIME=true ;;
|
|
||||||
--release) IOS_RELEASE=true ;;
|
--release) IOS_RELEASE=true ;;
|
||||||
--ipa) IOS_IPA=true ;;
|
--ipa) IOS_IPA=true ;;
|
||||||
*) fail "unknown argument: $1" ;;
|
*) fail "unknown argument: $1" ;;
|
||||||
@@ -172,55 +150,24 @@ make_ico() { # $1 = output .ico path
|
|||||||
# --------------------------------------------------------------- macOS
|
# --------------------------------------------------------------- macOS
|
||||||
build_mac() {
|
build_mac() {
|
||||||
say "building macOS app"
|
say "building macOS app"
|
||||||
local love_app="${LOVE_APP:-}"
|
local love_app="${LOVE_APP:-/Applications/love.app}"
|
||||||
if [ -z "$love_app" ]; then
|
[ -d "$love_app" ] || fail "LÖVE.app not found at $love_app (install it or set LOVE_APP=/path/to/love.app)"
|
||||||
for candidate in "$LOVE_MAC_APP" "/Applications/love12.app" "$HOME/Applications/love12.app" \
|
|
||||||
"/Applications/love.app" "$HOME/Applications/love.app"; do
|
|
||||||
if [ -d "$candidate" ] && valid_love12_app "$candidate"; then
|
|
||||||
love_app="$candidate"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if [ ! -d "$love_app" ] && [ -z "${LOVE_APP:-}" ] && $FETCH_MAC_RUNTIME; then
|
|
||||||
"$ROOT/scripts/build_love_macos.sh" --fetch
|
|
||||||
love_app="$LOVE_MAC_APP"
|
|
||||||
fi
|
|
||||||
[ -d "$love_app" ] || fail "LÖVE 12 Metal app not found; run scripts/build_love_macos.sh --fetch or set LOVE_APP=/path/to/love.app"
|
|
||||||
local love_version
|
|
||||||
love_version=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$love_app/Contents/Info.plist" 2>/dev/null || true)
|
|
||||||
printf '%s' "$love_version" | grep -Eq '^12(\.|$)' \
|
|
||||||
|| fail "macOS build requires LÖVE $LOVE_MAC_VERSION at $love_app (set LOVE_APP to a LÖVE 12 app)"
|
|
||||||
[ -f "$love_app/Contents/Frameworks/love.framework/love" ] \
|
|
||||||
|| fail "macOS build requires love.framework at $love_app"
|
|
||||||
otool -L "$love_app/Contents/Frameworks/love.framework/love" \
|
|
||||||
| grep -q '/Metal.framework/' \
|
|
||||||
|| fail "macOS build requires a LÖVE runtime linked to Metal at $love_app"
|
|
||||||
|
|
||||||
local stage_dir="${MAC_STAGE_DIR:-${RUNNER_TEMP:-/tmp}/gen1recomp-mac-stage}"
|
local out_app="$WORK/$APP_NAME.app"
|
||||||
local out_app="$stage_dir/$MAC_APP_NAME.app"
|
|
||||||
mkdir -p "$stage_dir"
|
|
||||||
rm -rf "$out_app"
|
rm -rf "$out_app"
|
||||||
ditto --norsrc "$love_app" "$out_app"
|
cp -R "$love_app" "$out_app"
|
||||||
|
|
||||||
local love_executable="$out_app/Contents/MacOS/love"
|
|
||||||
local app_executable="$out_app/Contents/MacOS/$MAC_APP_NAME"
|
|
||||||
[ -f "$love_executable" ] || fail "LÖVE app is missing Contents/MacOS/love"
|
|
||||||
mv "$love_executable" "$app_executable"
|
|
||||||
|
|
||||||
# drop any bundled placeholder .love and fuse ours in
|
# drop any bundled placeholder .love and fuse ours in
|
||||||
find "$out_app/Contents/Resources" -maxdepth 1 -name '*.love' -delete
|
find "$out_app/Contents/Resources" -maxdepth 1 -name '*.love' -delete
|
||||||
cp "$LOVE_FILE" "$out_app/Contents/Resources/game.love"
|
cp "$LOVE_FILE" "$out_app/Contents/Resources/game.love"
|
||||||
|
|
||||||
local plist="$out_app/Contents/Info.plist"
|
local plist="$out_app/Contents/Info.plist"
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleName $MAC_APP_NAME" "$plist" 2>/dev/null \
|
/usr/libexec/PlistBuddy -c "Set :CFBundleName $APP_NAME" "$plist" 2>/dev/null \
|
||||||
|| /usr/libexec/PlistBuddy -c "Add :CFBundleName string $MAC_APP_NAME" "$plist"
|
|| /usr/libexec/PlistBuddy -c "Add :CFBundleName string $APP_NAME" "$plist"
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $MAC_APP_NAME" "$plist" 2>/dev/null \
|
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $APP_NAME" "$plist" 2>/dev/null \
|
||||||
|| /usr/libexec/PlistBuddy -c "Add :CFBundleDisplayName string $MAC_APP_NAME" "$plist"
|
|| /usr/libexec/PlistBuddy -c "Add :CFBundleDisplayName string $APP_NAME" "$plist"
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable $MAC_APP_NAME" "$plist" 2>/dev/null \
|
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID" "$plist" 2>/dev/null \
|
||||||
|| /usr/libexec/PlistBuddy -c "Add :CFBundleExecutable string $MAC_APP_NAME" "$plist"
|
|| /usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string $BUNDLE_ID" "$plist"
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $MAC_BUNDLE_ID" "$plist" 2>/dev/null \
|
|
||||||
|| /usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string $MAC_BUNDLE_ID" "$plist"
|
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" "$plist" 2>/dev/null \
|
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" "$plist" 2>/dev/null \
|
||||||
|| /usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string $VERSION" "$plist"
|
|| /usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string $VERSION" "$plist"
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSION" "$plist" 2>/dev/null \
|
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSION" "$plist" 2>/dev/null \
|
||||||
@@ -242,11 +189,6 @@ build_mac() {
|
|||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleIconFile OS X AppIcon" "$plist" 2>/dev/null \
|
/usr/libexec/PlistBuddy -c "Set :CFBundleIconFile OS X AppIcon" "$plist" 2>/dev/null \
|
||||||
|| /usr/libexec/PlistBuddy -c "Add :CFBundleIconFile string 'OS X AppIcon'" "$plist"
|
|| /usr/libexec/PlistBuddy -c "Add :CFBundleIconFile string 'OS X AppIcon'" "$plist"
|
||||||
|
|
||||||
strip_bundle_metadata "$out_app"
|
|
||||||
|
|
||||||
rm -rf "$WORK/$MAC_APP_NAME.app"
|
|
||||||
ln -s "$out_app" "$WORK/$MAC_APP_NAME.app"
|
|
||||||
|
|
||||||
local id="$IDENTITY"
|
local id="$IDENTITY"
|
||||||
if [ -z "$id" ]; then
|
if [ -z "$id" ]; then
|
||||||
id="$(security find-identity -v -p codesigning 2>/dev/null | grep 'Developer ID Application' | head -1 | sed -E 's/^[^"]*"(.*)"$/\1/' || true)"
|
id="$(security find-identity -v -p codesigning 2>/dev/null | grep 'Developer ID Application' | head -1 | sed -E 's/^[^"]*"(.*)"$/\1/' || true)"
|
||||||
@@ -268,9 +210,9 @@ build_mac() {
|
|||||||
warn "keychain profile '$NOTARY_PROFILE' not found/working, skipping notarization."
|
warn "keychain profile '$NOTARY_PROFILE' not found/working, skipping notarization."
|
||||||
warn "set it up with: xcrun notarytool store-credentials \"$NOTARY_PROFILE\" --apple-id ... --team-id ... --password ..."
|
warn "set it up with: xcrun notarytool store-credentials \"$NOTARY_PROFILE\" --apple-id ... --team-id ... --password ..."
|
||||||
else
|
else
|
||||||
local notarize_zip="$stage_dir/$MAC_APP_NAME-notarize.zip"
|
local notarize_zip="$WORK/$APP_NAME-notarize.zip"
|
||||||
rm -f "$notarize_zip"
|
rm -f "$notarize_zip"
|
||||||
(cd "$stage_dir" && ditto -c -k --keepParent "$MAC_APP_NAME.app" "$notarize_zip")
|
(cd "$WORK" && ditto -c -k --keepParent "$APP_NAME.app" "$notarize_zip")
|
||||||
say "submitting to Apple notary service (this can take a few minutes)"
|
say "submitting to Apple notary service (this can take a few minutes)"
|
||||||
xcrun notarytool submit "$notarize_zip" --keychain-profile "$NOTARY_PROFILE" --wait
|
xcrun notarytool submit "$notarize_zip" --keychain-profile "$NOTARY_PROFILE" --wait
|
||||||
say "stapling notarization ticket"
|
say "stapling notarization ticket"
|
||||||
@@ -279,11 +221,9 @@ build_mac() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
strip_bundle_metadata "$out_app"
|
local zip_out="$DIST/mac/$APP_NAME-macos.zip"
|
||||||
|
|
||||||
local zip_out="$DIST/mac/$MAC_APP_NAME-macos.zip"
|
|
||||||
rm -f "$zip_out"
|
rm -f "$zip_out"
|
||||||
(cd "$stage_dir" && ditto -c -k --norsrc --keepParent "$MAC_APP_NAME.app" "$zip_out")
|
(cd "$WORK" && ditto -c -k --sequesterRsrc --keepParent "$APP_NAME.app" "$zip_out")
|
||||||
say "macOS build: $zip_out"
|
say "macOS build: $zip_out"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
||||||
MACOS_DIR="$ROOT/mobile/macos"
|
|
||||||
CACHE="$ROOT/.bazinga/love12"
|
|
||||||
SOURCE_DIR="${LOVE_SOURCE_DIR:-$CACHE/source}"
|
|
||||||
RUNTIME_APP="${LOVE_APP_OUTPUT:-$CACHE/love.app}"
|
|
||||||
BUILD_DIR="$CACHE/build"
|
|
||||||
LOVE_VERSION="$(tr -d '[:space:]' < "$MACOS_DIR/LOVE_VERSION")"
|
|
||||||
LOVE_SOURCE_REF="$(tr -d '[:space:]' < "$MACOS_DIR/LOVE_SOURCE_REF")"
|
|
||||||
APPLE_DEPENDENCIES_REF="$(tr -d '[:space:]' < "$MACOS_DIR/APPLE_DEPENDENCIES_REF")"
|
|
||||||
LOVE_SOURCE_REPO="${LOVE_SOURCE_REPO:-https://github.com/love2d/love.git}"
|
|
||||||
APPLE_DEPENDENCIES_REPO="${APPLE_DEPENDENCIES_REPO:-https://github.com/love2d/love-apple-dependencies.git}"
|
|
||||||
|
|
||||||
FETCH=false
|
|
||||||
CLEAN=false
|
|
||||||
|
|
||||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
|
||||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
|
||||||
|
|
||||||
strip_bundle_metadata() {
|
|
||||||
local bundle="$1"
|
|
||||||
xattr -rc "$bundle"
|
|
||||||
xattr -rd com.apple.FinderInfo "$bundle" 2>/dev/null || true
|
|
||||||
xattr -rd 'com.apple.fileprovider.fpfs#P' "$bundle" 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
--fetch) FETCH=true ;;
|
|
||||||
--clean) CLEAN=true ;;
|
|
||||||
-h|--help)
|
|
||||||
printf '%s\n' 'usage: scripts/build_love_macos.sh [--fetch] [--clean]'
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*) fail "unknown argument: $1" ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
[ "$(uname -s)" = "Darwin" ] || fail "macOS LÖVE builds require Darwin"
|
|
||||||
command -v git >/dev/null 2>&1 || fail "git is required to fetch LÖVE sources"
|
|
||||||
command -v xcodebuild >/dev/null 2>&1 || fail "xcodebuild is required to build LÖVE for macOS"
|
|
||||||
command -v xattr >/dev/null 2>&1 || fail "xattr is required to normalize the runtime bundle"
|
|
||||||
|
|
||||||
source_ready() {
|
|
||||||
[ -d "$SOURCE_DIR/platform/xcode/love.xcodeproj" ] \
|
|
||||||
&& [ -d "$SOURCE_DIR/platform/xcode/macosx/Frameworks/Lua.framework" ] \
|
|
||||||
&& [ -d "$SOURCE_DIR/platform/xcode/shared/Frameworks/SDL3.xcframework" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
source_is_pinned() {
|
|
||||||
[ "$(git -C "$SOURCE_DIR" rev-parse HEAD 2>/dev/null || true)" = "$LOVE_SOURCE_REF" ] \
|
|
||||||
&& [ -f "$SOURCE_DIR/.gen1recomp-apple-dependencies-ref" ] \
|
|
||||||
&& [ "$(tr -d '[:space:]' < "$SOURCE_DIR/.gen1recomp-apple-dependencies-ref")" = "$APPLE_DEPENDENCIES_REF" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_repo() {
|
|
||||||
local repo_url="$1"
|
|
||||||
local ref="$2"
|
|
||||||
local destination="$3"
|
|
||||||
mkdir -p "$destination"
|
|
||||||
git -C "$destination" init -q
|
|
||||||
git -C "$destination" remote add origin "$repo_url"
|
|
||||||
git -C "$destination" fetch --depth 1 origin "$ref"
|
|
||||||
git -C "$destination" checkout --detach -q FETCH_HEAD
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_sources() {
|
|
||||||
local tmp
|
|
||||||
mkdir -p "$CACHE"
|
|
||||||
tmp="$(mktemp -d "$CACHE/fetch.XXXXXX")"
|
|
||||||
say "fetching LÖVE source $LOVE_SOURCE_REF"
|
|
||||||
fetch_repo "$LOVE_SOURCE_REPO" "$LOVE_SOURCE_REF" "$tmp/love"
|
|
||||||
say "fetching Apple dependencies $APPLE_DEPENDENCIES_REF"
|
|
||||||
fetch_repo "$APPLE_DEPENDENCIES_REPO" "$APPLE_DEPENDENCIES_REF" "$tmp/dependencies"
|
|
||||||
mkdir -p "$tmp/love/platform/xcode/macosx/Frameworks" "$tmp/love/platform/xcode/shared"
|
|
||||||
cp -R "$tmp/dependencies/macOS/Frameworks/." "$tmp/love/platform/xcode/macosx/Frameworks/"
|
|
||||||
cp -R "$tmp/dependencies/shared/." "$tmp/love/platform/xcode/shared/"
|
|
||||||
rm -rf "$SOURCE_DIR"
|
|
||||||
mkdir -p "$(dirname "$SOURCE_DIR")"
|
|
||||||
mv "$tmp/love" "$SOURCE_DIR"
|
|
||||||
printf '%s\n' "$APPLE_DEPENDENCIES_REF" > "$SOURCE_DIR/.gen1recomp-apple-dependencies-ref"
|
|
||||||
rm -rf "$tmp"
|
|
||||||
say "LÖVE source ready at $SOURCE_DIR"
|
|
||||||
}
|
|
||||||
|
|
||||||
if $CLEAN; then
|
|
||||||
[ -z "${LOVE_SOURCE_DIR:-}" ] \
|
|
||||||
|| fail "--clean cannot be used with LOVE_SOURCE_DIR"
|
|
||||||
rm -rf "$SOURCE_DIR" "$BUILD_DIR" "$RUNTIME_APP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! source_ready || ! source_is_pinned; then
|
|
||||||
if ! $FETCH; then
|
|
||||||
fail "pinned LÖVE 12 sources are missing at $SOURCE_DIR; run scripts/build_love_macos.sh --fetch"
|
|
||||||
fi
|
|
||||||
[ -z "${LOVE_SOURCE_DIR:-}" ] \
|
|
||||||
|| fail "LOVE_SOURCE_DIR is not the pinned LÖVE commit $LOVE_SOURCE_REF"
|
|
||||||
fetch_sources
|
|
||||||
fi
|
|
||||||
|
|
||||||
PROJECT="$SOURCE_DIR/platform/xcode/love.xcodeproj"
|
|
||||||
rm -rf "$BUILD_DIR" "$RUNTIME_APP"
|
|
||||||
mkdir -p "$BUILD_DIR"
|
|
||||||
say "building LÖVE 12 macOS runtime"
|
|
||||||
xcodebuild \
|
|
||||||
-quiet \
|
|
||||||
-project "$PROJECT" \
|
|
||||||
-target love-macosx \
|
|
||||||
-configuration Release \
|
|
||||||
-sdk macosx \
|
|
||||||
SYMROOT="$BUILD_DIR" \
|
|
||||||
OBJROOT="$BUILD_DIR/Intermediates" \
|
|
||||||
ARCHS="arm64 x86_64" \
|
|
||||||
ONLY_ACTIVE_ARCH=NO \
|
|
||||||
MACOSX_DEPLOYMENT_TARGET=12.0 \
|
|
||||||
CODE_SIGNING_ALLOWED=NO \
|
|
||||||
CODE_SIGNING_REQUIRED=NO \
|
|
||||||
CODE_SIGN_IDENTITY=-
|
|
||||||
|
|
||||||
BUILT_APP="$BUILD_DIR/Release/love.app"
|
|
||||||
[ -d "$BUILT_APP" ] || fail "xcodebuild produced no LÖVE app at $BUILT_APP"
|
|
||||||
ditto --norsrc "$BUILT_APP" "$RUNTIME_APP"
|
|
||||||
strip_bundle_metadata "$RUNTIME_APP"
|
|
||||||
|
|
||||||
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$RUNTIME_APP/Contents/Info.plist" 2>/dev/null || true)"
|
|
||||||
version_re="$(printf '%s' "$LOVE_VERSION" | sed 's/\./\\./g')"
|
|
||||||
printf '%s' "$version" | grep -Eq "^${version_re}(\.|$)" \
|
|
||||||
|| fail "built runtime reports LÖVE version '$version'"
|
|
||||||
[ -x "$RUNTIME_APP/Contents/MacOS/love" ] \
|
|
||||||
|| fail "built runtime is missing Contents/MacOS/love"
|
|
||||||
[ -f "$RUNTIME_APP/Contents/Frameworks/love.framework/love" ] \
|
|
||||||
|| fail "built runtime is missing love.framework"
|
|
||||||
otool -L "$RUNTIME_APP/Contents/Frameworks/love.framework/love" \
|
|
||||||
| grep -q '/Metal.framework/' \
|
|
||||||
|| fail "built LÖVE runtime is not linked to Metal"
|
|
||||||
|
|
||||||
archs="$(lipo -archs "$RUNTIME_APP/Contents/MacOS/love")"
|
|
||||||
printf '%s' "$archs" | grep -qw arm64 \
|
|
||||||
|| fail "built LÖVE app is missing arm64"
|
|
||||||
printf '%s' "$archs" | grep -qw x86_64 \
|
|
||||||
|| fail "built LÖVE app is missing x86_64"
|
|
||||||
framework_archs="$(lipo -archs "$RUNTIME_APP/Contents/Frameworks/love.framework/love")"
|
|
||||||
printf '%s' "$framework_archs" | grep -qw arm64 \
|
|
||||||
|| fail "built LÖVE framework is missing arm64"
|
|
||||||
printf '%s' "$framework_archs" | grep -qw x86_64 \
|
|
||||||
|| fail "built LÖVE framework is missing x86_64"
|
|
||||||
|
|
||||||
say "LÖVE 12 macOS runtime: $RUNTIME_APP"
|
|
||||||
+2
-24
@@ -32,30 +32,8 @@ find_love() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
find_love12() {
|
LOVE_BIN="$(find_love)" \
|
||||||
local app version
|
|| fail "LÖVE not found, run scripts/setup.sh (or install from https://love2d.org)"
|
||||||
for app in "${LOVE_APP:-}" "$ROOT/.bazinga/love12/love.app" "/Applications/love12.app" "$HOME/Applications/love12.app" \
|
|
||||||
"/Applications/love.app" "$HOME/Applications/love.app"; do
|
|
||||||
[ -n "$app" ] || continue
|
|
||||||
if [ -x "$app/Contents/MacOS/love" ]; then
|
|
||||||
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$app/Contents/Info.plist" 2>/dev/null || true)"
|
|
||||||
if printf '%s' "$version" | grep -Eq '^12(\.|$)' \
|
|
||||||
&& otool -L "$app/Contents/Frameworks/love.framework/love" 2>/dev/null | grep -q '/Metal.framework/'; then
|
|
||||||
echo "$app/Contents/MacOS/love"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$(uname -s)" = "Darwin" ]; then
|
|
||||||
LOVE_BIN="$(find_love12)" \
|
|
||||||
|| fail "LÖVE 12 with Metal not found, run scripts/setup.sh or scripts/build_love_macos.sh --fetch"
|
|
||||||
else
|
|
||||||
LOVE_BIN="$(find_love)" \
|
|
||||||
|| fail "LÖVE not found, run scripts/setup.sh (or install from https://love2d.org)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# SDL2 on Wayland crashes during desktop drag-and-drop in certain compositors;
|
# SDL2 on Wayland crashes during desktop drag-and-drop in certain compositors;
|
||||||
# default to X11/XWayland when available to ensure rock-solid drag-drop stability.
|
# default to X11/XWayland when available to ensure rock-solid drag-drop stability.
|
||||||
|
|||||||
+4
-25
@@ -70,32 +70,11 @@ find_love() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
valid_love12_app() {
|
if LOVE_BIN="$(find_love)"; then
|
||||||
local app="$1" version
|
|
||||||
[ -x "$app/Contents/MacOS/love" ] || return 1
|
|
||||||
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$app/Contents/Info.plist" 2>/dev/null || true)"
|
|
||||||
printf '%s' "$version" | grep -Eq '^12(\.|$)' || return 1
|
|
||||||
otool -L "$app/Contents/Frameworks/love.framework/love" 2>/dev/null \
|
|
||||||
| grep -q '/Metal.framework/'
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$(uname -s)" = "Darwin" ]; then
|
|
||||||
if valid_love12_app "$ROOT/.bazinga/love12/love.app"; then
|
|
||||||
say "LÖVE 12 found: $ROOT/.bazinga/love12/love.app"
|
|
||||||
elif valid_love12_app "/Applications/love12.app"; then
|
|
||||||
say "LÖVE 12 found: /Applications/love12.app"
|
|
||||||
elif valid_love12_app "$HOME/Applications/love12.app"; then
|
|
||||||
say "LÖVE 12 found: $HOME/Applications/love12.app"
|
|
||||||
elif valid_love12_app "/Applications/love.app"; then
|
|
||||||
say "LÖVE 12 found: /Applications/love.app"
|
|
||||||
elif valid_love12_app "$HOME/Applications/love.app"; then
|
|
||||||
say "LÖVE 12 found: $HOME/Applications/love.app"
|
|
||||||
else
|
|
||||||
say "building LÖVE 12 for macOS"
|
|
||||||
"$ROOT/scripts/build_love_macos.sh" --fetch
|
|
||||||
fi
|
|
||||||
elif LOVE_BIN="$(find_love)"; then
|
|
||||||
say "LÖVE found: $LOVE_BIN"
|
say "LÖVE found: $LOVE_BIN"
|
||||||
|
elif [ "$(uname -s)" = "Darwin" ] && command -v brew >/dev/null 2>&1; then
|
||||||
|
say "installing LÖVE via Homebrew"
|
||||||
|
brew install --cask love
|
||||||
else
|
else
|
||||||
fail "LÖVE 11.x is not installed; install it from https://love2d.org"
|
fail "LÖVE 11.x is not installed; install it from https://love2d.org"
|
||||||
fi
|
fi
|
||||||
|
|||||||
+19
-6
@@ -140,7 +140,7 @@ function SaveData.gameFolders()
|
|||||||
local src = love.filesystem.getSource and love.filesystem.getSource()
|
local src = love.filesystem.getSource and love.filesystem.getSource()
|
||||||
local sbd = love.filesystem.getSourceBaseDirectory
|
local sbd = love.filesystem.getSourceBaseDirectory
|
||||||
and love.filesystem.getSourceBaseDirectory()
|
and love.filesystem.getSourceBaseDirectory()
|
||||||
-- A packaged macOS build nests the game inside gen1recomp++.app/Contents/
|
-- A packaged macOS build nests the game inside gen1recomp.app/Contents/
|
||||||
-- Resources, so getSource()/getSourceBaseDirectory() point INSIDE the
|
-- Resources, so getSource()/getSourceBaseDirectory() point INSIDE the
|
||||||
-- bundle -- not where the player drops portable.txt (next to the .app).
|
-- bundle -- not where the player drops portable.txt (next to the .app).
|
||||||
-- Recover the folder containing the .app so a packaged app finds its
|
-- Recover the folder containing the .app so a packaged app finds its
|
||||||
@@ -1279,13 +1279,26 @@ function SaveData.ensurePlaythroughId(save, injectedFs)
|
|||||||
local isFresh = save == freshPlaythrough
|
local isFresh = save == freshPlaythrough
|
||||||
if isFresh then freshPlaythrough = nil end
|
if isFresh then freshPlaythrough = nil end
|
||||||
local byVersion = opts.playthroughIds and opts.playthroughIds[version]
|
local byVersion = opts.playthroughIds and opts.playthroughIds[version]
|
||||||
id = not isFresh and byVersion and byVersion[scope] or nil
|
local existing = byVersion and byVersion[scope]
|
||||||
|
id = not isFresh and existing or nil
|
||||||
if type(id) ~= "string" or id == "" then
|
if type(id) ~= "string" or id == "" then
|
||||||
id = SaveData.newPlaythroughId()
|
id = SaveData.newPlaythroughId()
|
||||||
opts.playthroughIds = opts.playthroughIds or {}
|
-- A fresh skeleton still gets its own id (two unsaved New Games sharing a
|
||||||
opts.playthroughIds[version] = opts.playthroughIds[version] or {}
|
-- slot must stay distinct), and it is still persisted when the slot has no
|
||||||
opts.playthroughIds[version][scope] = id
|
-- binding yet -- that is the contract a tool relies on to resolve
|
||||||
SaveData.saveOptions(opts, injectedFs)
|
-- `selected` at the title after a restart, before any normal SAVE.
|
||||||
|
--
|
||||||
|
-- What it must NOT do is OVERWRITE a binding that already exists. newGame()
|
||||||
|
-- marks a skeleton on the boot frame, before any save is loaded, and mods
|
||||||
|
-- initialise inside that window -- so a mod touching storage at init
|
||||||
|
-- replaced the real save's id with a throwaway, stranding that save's mod
|
||||||
|
-- storage and repeating on every launch.
|
||||||
|
if not (isFresh and type(existing) == "string" and existing ~= "") then
|
||||||
|
opts.playthroughIds = opts.playthroughIds or {}
|
||||||
|
opts.playthroughIds[version] = opts.playthroughIds[version] or {}
|
||||||
|
opts.playthroughIds[version][scope] = id
|
||||||
|
SaveData.saveOptions(opts, injectedFs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
save.meta.playthroughId = id
|
save.meta.playthroughId = id
|
||||||
return id
|
return id
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ love = love or require("tests.love_stub")
|
|||||||
-- scripts/build.sh mac layout: the game is an archive inside the .app, the
|
-- scripts/build.sh mac layout: the game is an archive inside the .app, the
|
||||||
-- player's portable folder is the one holding the .app.
|
-- player's portable folder is the one holding the .app.
|
||||||
local PORTABLE = "/Users/p/Games"
|
local PORTABLE = "/Users/p/Games"
|
||||||
local APP = PORTABLE .. "/gen1recomp++.app"
|
local APP = PORTABLE .. "/gen1recomp.app"
|
||||||
local SOURCE = APP .. "/Contents/Resources/game.love"
|
local SOURCE = APP .. "/Contents/Resources/game.love"
|
||||||
local BASE = APP .. "/Contents/MacOS"
|
local BASE = APP .. "/Contents/MacOS"
|
||||||
|
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ end
|
|||||||
-- Also gates the NX runtime modules and the NX engine suites so an NX
|
-- Also gates the NX runtime modules and the NX engine suites so an NX
|
||||||
-- runtime regression cannot slip past switch-selftest / switch-build.
|
-- runtime regression cannot slip past switch-selftest / switch-build.
|
||||||
local SWITCH_PATH_REGEX =
|
local SWITCH_PATH_REGEX =
|
||||||
[[^(scripts/build_switch\.sh$|scripts/switch/|docs/switch-.*\.md$|tests/switch_ci_workflows_test\.lua$|tests/switch_transfer_docs_test\.lua$|\.github/workflows/(ci|release|platform-artifact-comment)\.yml$|src/core/(NxAssetOverlay|Platform|GameVersion)\.lua$|src/import/CacheFs\.lua$|tests/engine/(assets_version_fallback|nx_generated_guard|nx_yellow_boot|switch_diagnostics|cache_fs_gold_nx_load)_test\.lua$|tests/engine/platform_nx)]]
|
[[^(scripts/build_switch\.sh$|scripts/switch/|docs/switch-.*\.md$|tests/switch_ci_workflows_test\.lua$|tests/switch_transfer_docs_test\.lua$|\.github/workflows/(ci|release|switch-artifact-comment)\.yml$|src/core/(NxAssetOverlay|Platform|GameVersion)\.lua$|src/import/CacheFs\.lua$|tests/engine/(assets_version_fallback|nx_generated_guard|nx_yellow_boot|switch_diagnostics|cache_fs_gold_nx_load)_test\.lua$|tests/engine/platform_nx)]]
|
||||||
|
|
||||||
local ci = read(".github/workflows/ci.yml")
|
local ci = read(".github/workflows/ci.yml")
|
||||||
local release = read(".github/workflows/release.yml")
|
local release = read(".github/workflows/release.yml")
|
||||||
local comment_wf = read(".github/workflows/platform-artifact-comment.yml")
|
local comment_wf = read(".github/workflows/switch-artifact-comment.yml")
|
||||||
|
local ios_comment_wf = read(".github/workflows/ios-artifact-comment.yml")
|
||||||
|
|
||||||
-- --- SWCI-01: path detector ---
|
-- --- SWCI-01: path detector ---
|
||||||
mustContain(ci, "switch-changes:", "ci.yml")
|
mustContain(ci, "switch-changes:", "ci.yml")
|
||||||
@@ -128,26 +129,28 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- --- SWCI-06 / SWCI-07 / SWFIX-01: PR artifact comment (no delete-all clobber) ---
|
-- --- SWCI-06 / SWCI-07 / SWFIX-01: PR artifact comment (no delete-all clobber) ---
|
||||||
mustContain(comment_wf, "workflows: [ci]", "platform-artifact-comment")
|
mustContain(comment_wf, "workflows: [ci]", "switch-artifact-comment")
|
||||||
for _, artifact in ipairs({
|
mustContain(comment_wf, "gen1recomp-switch-nro", "switch-artifact-comment")
|
||||||
"gen1recomp++-macos",
|
mustContain(comment_wf, "comment-tag: switch-build-result", "switch-artifact-comment")
|
||||||
"gen1recomp++-ios-ipa",
|
mustContain(comment_wf, "pull_request", "switch-artifact-comment")
|
||||||
"gen1recomp-switch-nro",
|
mustContain(comment_wf, "conclusion == 'success'", "switch-artifact-comment")
|
||||||
"gen1recomp-xbox-uwp",
|
mustContain(comment_wf, 'exit 0', "switch-artifact-comment no-op")
|
||||||
"gen1recomp-linux-arm64",
|
mustContain(comment_wf, "**Commit**:", "switch-artifact-comment")
|
||||||
}) do
|
mustContain(comment_wf, "**Build Time**:", "switch-artifact-comment")
|
||||||
mustContain(comment_wf, artifact, "platform-artifact-comment")
|
mustContain(comment_wf, "View workflow run", "switch-artifact-comment")
|
||||||
end
|
mustContain(comment_wf, "thollander/actions-comment-pull-request@v3", "switch-artifact-comment")
|
||||||
mustContain(comment_wf, "comment-tag: platform-build-result", "platform-artifact-comment")
|
mustNotContain(comment_wf, "delete-comment", "switch-artifact-comment")
|
||||||
mustContain(comment_wf, "pull_request", "platform-artifact-comment")
|
mustNotContain(comment_wf, "izhangzhihao/delete-comment", "switch-artifact-comment")
|
||||||
mustContain(comment_wf, "conclusion == 'success'", "platform-artifact-comment")
|
|
||||||
mustContain(comment_wf, 'exit 0', "platform-artifact-comment no-op")
|
mustContain(ios_comment_wf, "comment-tag: ios-build-result", "ios-artifact-comment")
|
||||||
mustContain(comment_wf, "**Commit**:", "platform-artifact-comment")
|
mustContain(ios_comment_wf, "thollander/actions-comment-pull-request@v3", "ios-artifact-comment")
|
||||||
mustContain(comment_wf, "**Build Time**:", "platform-artifact-comment")
|
mustNotContain(ios_comment_wf, "delete-comment", "ios-artifact-comment")
|
||||||
mustContain(comment_wf, "View workflow run", "platform-artifact-comment")
|
mustNotContain(ios_comment_wf, "izhangzhihao/delete-comment", "ios-artifact-comment")
|
||||||
mustContain(comment_wf, "thollander/actions-comment-pull-request@v3", "platform-artifact-comment")
|
-- Distinct tags so both commenters can coexist on the same PR
|
||||||
mustNotContain(comment_wf, "delete-comment", "platform-artifact-comment")
|
check(comment_wf:find("comment-tag: switch-build-result", 1, true)
|
||||||
mustNotContain(comment_wf, "izhangzhihao/delete-comment", "platform-artifact-comment")
|
and ios_comment_wf:find("comment-tag: ios-build-result", 1, true)
|
||||||
|
and comment_wf:find("comment-tag: ios-build-result", 1, true) == nil,
|
||||||
|
"iOS and Switch comment-tags must be distinct and present")
|
||||||
|
|
||||||
-- --- SWCI-08 / SWCI-09: docs CI vs release ---
|
-- --- SWCI-08 / SWCI-09: docs CI vs release ---
|
||||||
local build_doc = read("docs/switch-build.md")
|
local build_doc = read("docs/switch-build.md")
|
||||||
@@ -158,7 +161,7 @@ mustContain(build_doc, "ubuntu-latest", "switch-build.md")
|
|||||||
mustContain(build_doc, "selftest_build_switch.sh", "switch-build.md")
|
mustContain(build_doc, "selftest_build_switch.sh", "switch-build.md")
|
||||||
mustContain(build_doc, "main repo", "switch-build.md")
|
mustContain(build_doc, "main repo", "switch-build.md")
|
||||||
mustContain(build_doc, "gen1recomp-switch-nro", "switch-build.md")
|
mustContain(build_doc, "gen1recomp-switch-nro", "switch-build.md")
|
||||||
mustContain(build_doc, "platform-build-result", "switch-build.md")
|
mustContain(build_doc, "switch-build-result", "switch-build.md")
|
||||||
mustContain(build_doc, "hard gate", "switch-build.md")
|
mustContain(build_doc, "hard gate", "switch-build.md")
|
||||||
mustContain(build_doc, "continue-on-error", "switch-build.md")
|
mustContain(build_doc, "continue-on-error", "switch-build.md")
|
||||||
mustContain(build_doc, "nacptool", "switch-build.md")
|
mustContain(build_doc, "nacptool", "switch-build.md")
|
||||||
|
|||||||
+15
-4
@@ -988,14 +988,25 @@ def cmd_add_release_workflow(args, repo):
|
|||||||
# ---------------------------------------------------------------- lint
|
# ---------------------------------------------------------------- lint
|
||||||
|
|
||||||
def ahash(image):
|
def ahash(image):
|
||||||
"""Ink-mask hash over the 8x8 downscale: background (the lightest GB
|
"""Ink-mask hash over the 8x8 downscale: background vs ink, split at
|
||||||
shade) vs ink. Swapping the three ink shades -- the classic recolor --
|
THIS image's own average brightness rather than a fixed shade. Swapping
|
||||||
leaves the mask intact, which is exactly what MK302 wants to catch."""
|
the three ink shades -- the classic recolor -- leaves the mask intact,
|
||||||
|
which is exactly what MK302 wants to catch.
|
||||||
|
|
||||||
|
A fixed cutoff (e.g. "<=200 is ink") only makes sense for sprites with a
|
||||||
|
light background to split against; a mostly-opaque 16x16 icon has almost
|
||||||
|
no pixel above that cutoff, so every such icon collapsed onto the same
|
||||||
|
"all ink" hash and was flagged as a near-duplicate of anything else that
|
||||||
|
also collapsed -- which was most of them, boulder.png included.
|
||||||
|
Thresholding against the image's own mean keeps the split meaningful
|
||||||
|
(and roughly balanced) no matter how light or dark the source is."""
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
small = image.convert("L").resize((8, 8), Image.LANCZOS)
|
small = image.convert("L").resize((8, 8), Image.LANCZOS)
|
||||||
raw = (small.get_flattened_data() if hasattr(small, "get_flattened_data")
|
raw = (small.get_flattened_data() if hasattr(small, "get_flattened_data")
|
||||||
else small.getdata())
|
else small.getdata())
|
||||||
return sum((1 << i) for i, p in enumerate(raw) if p <= 200)
|
raw = list(raw)
|
||||||
|
average = sum(raw) / len(raw)
|
||||||
|
return sum((1 << i) for i, p in enumerate(raw) if p <= average)
|
||||||
|
|
||||||
|
|
||||||
def hamming(a, b):
|
def hamming(a, b):
|
||||||
|
|||||||
Reference in New Issue
Block a user