Repository navigation
Expand file tree
/
Copy pathbuild-macos-native-ref.sh
More file actions
executable file
·132 lines (116 loc) · 5.74 KB
/
Copy pathbuild-macos-native-ref.sh
File metadata and controls
executable file
·132 lines (116 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env bash
###
# Build and run the macOS (AppKit) native reference app.
#
# Same shape as scripts/build-ios-native-ref.sh: one Swift file compiled with `xcrun
# swiftc`, a hand-written Info.plist, no xcodeproj. Unsigned is fine -- a locally built
# bundle carries no quarantine xattr, so Gatekeeper never sees it.
#
# Runs on a hosted CI runner rather than the maintainer's Mac, because a working
# developer's Mac has a chosen accent colour, a chosen appearance and custom fonts, and a
# reference captured there would encode all three. See
# .github/workflows/fidelity-desktop-native-ref.yml.
#
# Honours NATIVEREF_MODE (probe|capture) and CN1SS_FIDELITY_GOLDEN_SET.
###
set -euo pipefail
log() { echo "[build-macos-native-ref] $1" >&2; }
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
cd "$REPO_ROOT"
SRC="$REPO_ROOT/scripts/fidelity-app/macos-native-ref/NativeRef.swift"
OUT_DIR="$REPO_ROOT/artifacts/desktop-native-ref/macos"
mkdir -p "$OUT_DIR"
BUILD="$(mktemp -d "${TMPDIR:-/tmp}/cn1-macos-ref-XXXXXX")"
APP="$BUILD/NativeRef.app"
mkdir -p "$APP/Contents/MacOS"
SDK="$(xcrun --sdk macosx --show-sdk-path)"
ARCH="$(uname -m)"
log "Compiling for $ARCH against $SDK"
xcrun -sdk macosx swiftc \
-target "${ARCH}-apple-macos13.0" \
-sdk "$SDK" \
-framework AppKit \
-parse-as-library \
"$SRC" -o "$APP/Contents/MacOS/NativeRef"
# LSUIElement is deliberately absent: the app must be .regular so it can become frontmost.
# An NSWindow that never becomes key draws every AppKit control in its inactive style.
cat > "$APP/Contents/Info.plist" <<'PLIST'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key><string>NativeRef</string>
<key>CFBundleIdentifier</key><string>com.codenameone.fidelity.nativeref</string>
<key>CFBundleExecutable</key><string>NativeRef</string>
<key>CFBundlePackageType</key><string>APPL</string>
<key>CFBundleShortVersionString</key><string>1.0</string>
<key>NSPrincipalClass</key><string>NSApplication</string>
<key>NSHighResolutionCapable</key><true/>
<key>LSMinimumSystemVersion</key><string>13.0</string>
</dict>
</plist>
PLIST
# Pin what must not drift between runs. The app reads all of these at launch, so writing
# them here and then launching a fresh process is enough -- the cfprefsd caching problem
# only affects processes that are already running.
defaults write -g NSAutomaticWindowAnimationsEnabled -bool false || true
defaults write -g AppleFontSmoothing -int 0 || true
defaults write -g AppleShowScrollBars -string Always || true
# The GitHub macOS runner ships with Reduce Transparency ON (measured: run 34936153808
# reported reduce_transparency true on macos-15). That flattens every vibrancy and material
# surface to an opaque fill, which is the macOS counterpart of Mica falling back on Windows
# Server -- capture under it and the reference silently encodes a design nobody sees.
# Turned off here; the app still asserts it afterwards, so if the write does not take the
# run fails rather than producing a flat reference.
defaults write com.apple.universalaccess reduceTransparency -bool false || true
defaults write com.apple.universalaccess increaseContrast -bool false || true
# Delete rather than set the accent: absent means "the system default", which is the
# reference we want. Setting a value would encode a choice no default Mac has made.
defaults delete -g AppleAccentColor 2>/dev/null || true
defaults delete -g AppleHighlightColor 2>/dev/null || true
export NATIVEREF_OUT="$OUT_DIR"
export NATIVEREF_MODE="${NATIVEREF_MODE:-probe}"
log "Running (mode=$NATIVEREF_MODE)"
# Launched through LaunchServices, not exec'd. Running the binary directly from a
# non-interactive shell -- which is what a CI runner gives you -- starts the app outside any
# Aqua session, so it never becomes active and every AppKit control renders in its
# inactive, greyed style. The first probe run measured exactly that: key=false main=false
# appActive=false. scripts/run-macos-ui-tests.sh already documents this for the macOS port
# and solves it the same way; `open -W -n` gets the app the session a user-launched Mac app
# would have.
#
# The cost is that stdout is no longer our pipe and `open` does not propagate the app's
# exit status, so the log is redirected to a file and the status is read back out of it.
TEST_LOG="$BUILD/nativeref.log"
: > "$TEST_LOG"
# caffeinate: a sleeping display makes every screen-capture API return black. It costs
# nothing when the display is already awake.
set +e
caffeinate -dimsu -w $$ &
CAFF=$!
open -W -n -F \
--stdout "$TEST_LOG" \
--stderr "$TEST_LOG" \
--env "NATIVEREF_OUT=$NATIVEREF_OUT" \
--env "NATIVEREF_MODE=$NATIVEREF_MODE" \
--env "CN1SS_FIDELITY_GOLDEN_SET=${CN1SS_FIDELITY_GOLDEN_SET:-macos-aqua}" \
-a "$APP"
kill "$CAFF" 2>/dev/null
set -e
cat "$TEST_LOG"
# `open -W` exits 0 whatever the app did, so the app reports its own verdict on the last
# line and it is read back here. A missing verdict means the app died before finishing,
# which must fail rather than pass quietly.
# Tolerant of extra fields before exit= (the capture run reports tiles= as well), but
# still anchored to the whole line so a half-written log cannot satisfy it.
rc=$(sed -n 's/^NATIVEREF:DONE .*exit=\([0-9][0-9]*\)$/\1/p' "$TEST_LOG" | tail -1)
if [ -z "$rc" ]; then
log "FAILED: the app never reported NATIVEREF:DONE -- it exited before finishing."
exit 22
fi
if [ "$rc" -ne 0 ]; then
log "FAILED: the reference app exited $rc; see the BLOCKER lines above."
log "A blocker means the capture would have been quietly wrong, not that it crashed."
exit "$rc"
fi
log "Wrote $(ls -1 "$OUT_DIR" | wc -l | tr -d ' ') file(s) to $OUT_DIR"