Repository navigation
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·234 lines (215 loc) · 11 KB
/
Copy pathsetup.sh
File metadata and controls
executable file
·234 lines (215 loc) · 11 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/bin/sh
# Bootstrap tinyjs from a source checkout: download the txiki.js runtime
# and compile the native launcher. Run once after cloning (the curl
# installer ships these prebuilt; this script is for developing tinyjs
# itself). Supports macOS and Linux (see README: Portability).
set -e
cd "$(dirname "$0")"
# One private scratch dir for downloads and builds (mktemp -d is 0700 with an
# unguessable name; /tmp/foo-$$ paths can be pre-planted by another local user).
TMPD="$(mktemp -d)"
trap 'rm -rf "$TMPD"' EXIT
TJS_VERSION="${TJS_VERSION:-v26.6.0}"
REPO="tarwin/tinyjsapp"
OS="$(uname -s)"
case "$(uname -m)" in
arm64|aarch64) TJS_ARCH=arm64 ;;
x86_64) TJS_ARCH=x86_64 ;;
*) echo "unsupported architecture: $(uname -m)" >&2; exit 1 ;;
esac
# ---------------------------------------------------------------- Linux ----
if [ "$OS" = "Linux" ]; then
# Build deps: a C++ toolchain + GTK3/WebKitGTK dev packages (AppIndicator
# optional — tray support). Package names differ per distro:
# Debian/Ubuntu: sudo apt install build-essential pkg-config libgtk-3-dev \
# libwebkit2gtk-4.1-dev libayatana-appindicator3-dev
# openSUSE: sudo zypper install gcc-c++ make pkgconf-pkg-config \
# gtk3-devel webkitgtk3-devel libayatana-appindicator3-devel
# (WebKitGTK 4.1's dev package is webkitgtk3-devel there —
# the "3" says GTK3, not an older WebKit; the runtime is
# libwebkit2gtk-4_1-0.)
DEPS_HINT="sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev"
CMAKE_HINT="sudo apt install cmake ninja-build"
if [ -r /etc/os-release ]; then
# shellcheck disable=SC1091
. /etc/os-release
case "${ID:-} ${ID_LIKE:-}" in
*suse*)
DEPS_HINT="sudo zypper install gcc-c++ make pkgconf-pkg-config gtk3-devel webkitgtk3-devel libayatana-appindicator3-devel"
CMAKE_HINT="sudo zypper install cmake ninja"
;;
esac
fi
for p in gtk+-3.0 webkit2gtk-4.1; do
pkg-config --exists "$p" 2>/dev/null || {
echo "missing dev package: $p" >&2
echo "install with: $DEPS_HINT" >&2
exit 1
}
done
if [ ! -x bin/tjs ]; then
# txiki.js publishes no Linux binaries — grab the one from our own
# releases (built by CI), or build from source (TJS_BUILD=1 forces it).
mkdir -p bin
GOT=""
if [ "${TJS_BUILD:-0}" != "1" ]; then
TJS_REL="${TINYJS_TJS_RELEASE:-latest}"
if [ "$TJS_REL" = "latest" ]; then
TJS_URL="https://github.com/$REPO/releases/latest/download/tjs-linux-$TJS_ARCH.gz"
else
TJS_URL="https://github.com/$REPO/releases/download/$TJS_REL/tjs-linux-$TJS_ARCH.gz"
fi
echo "==> downloading tjs (linux-$TJS_ARCH) from $REPO releases"
if curl -fsSL -o "$TMPD/tjs.gz" "$TJS_URL" 2>/dev/null; then
gunzip -c "$TMPD/tjs.gz" > bin/tjs && GOT=1
else
echo " (no prebuilt tjs in the latest release — building from source)"
fi
fi
if [ -z "$GOT" ]; then
command -v cmake >/dev/null || { echo "building txiki.js needs cmake ($CMAKE_HINT)" >&2; exit 1; }
echo "==> building txiki.js $TJS_VERSION from source (a few minutes)"
git clone --depth 1 --branch "$TJS_VERSION" --recurse-submodules --shallow-submodules -j4 \
https://github.com/saghul/txiki.js "$TMPD/txiki-src"
# txiki uses #pragma region folding markers and builds -Werror; GCC 12
# (Ubuntu 22.04's newest — release builds pin 22.04 for the glibc
# floor) doesn't know that pragma and errors out. They're editor
# decoration — stripping them changes nothing. Swept, not listed per
# file, so a new one upstream can't resurface the break. No-op for
# GCC 13+/clang, so it runs unconditionally.
grep -rl '#pragma region' "$TMPD/txiki-src" --include='*.c' --include='*.h' --include='*.cc' --include='*.cpp' 2>/dev/null \
| xargs -r sed -i 's/^[[:space:]]*#pragma[[:space:]]\{1,\}\(end\)\{0,1\}region.*$//'
GEN="Unix Makefiles"; command -v ninja >/dev/null && GEN=Ninja
cmake -S "$TMPD/txiki-src" -B "$TMPD/txiki-src/build" -DCMAKE_BUILD_TYPE=Release -G "$GEN"
# tjs-cli is the executable (OUTPUT_NAME tjs); the "tjs" target is
# only the core library.
cmake --build "$TMPD/txiki-src/build" --target tjs-cli -j"$(nproc)"
cp "$TMPD/txiki-src/build/tjs" bin/tjs
fi
chmod +x bin/tjs
fi
echo "==> compiling launcher"
./native/gen-client.sh
# Tray icons need an AppIndicator library (ayatana preferred); without one
# the launcher compiles fine and tiny.tray reports 'unsupported'.
IND_PKG=""
for p in ayatana-appindicator3-0.1 appindicator3-0.1; do
pkg-config --exists "$p" 2>/dev/null && { IND_PKG="$p"; break; }
done
EXTRA_DEFS=""
[ -n "$IND_PKG" ] && EXTRA_DEFS="-DTINYJS_APPINDICATOR"
[ -z "$IND_PKG" ] && echo " (no appindicator dev package — tray support disabled)"
# X11/XTest power global hotkeys + synthetic keystrokes on X11/XWayland
# sessions (no Wayland-native route yet; see TODO-linux.md).
XT_PKGS=""
pkg-config --exists x11 xtst 2>/dev/null && { XT_PKGS="x11 xtst"; EXTRA_DEFS="$EXTRA_DEFS -DTINYJS_X11"; }
# Opt-in outside-the-window mouse tracking on Wayland rides the ScreenCast
# portal's cursor metadata over PipeWire; without the dev package the
# launcher builds fine and mouseTracking.start() answers 'unsupported'.
PW_PKGS=""
pkg-config --exists libpipewire-0.3 2>/dev/null && { PW_PKGS="libpipewire-0.3"; EXTRA_DEFS="$EXTRA_DEFS -DTINYJS_PIPEWIRE"; }
[ -z "$PW_PKGS" ] && echo " (no libpipewire-0.3 dev package — Wayland mouseTracking disabled)"
# -isystem native/include: miniaudio.h (tiny.audio.sampler decoders) is
# vendored there; system-include keeps its warnings out of our build.
# shellcheck disable=SC2086
c++ -std=c++17 -O2 -isystem native/include native/launcher-linux.cc -o native/launcher-linux \
$EXTRA_DEFS \
$(pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.1 $IND_PKG $XT_PKGS $PW_PKGS) -ldl
echo "==> done"
./bin/tjs --version
echo "try: ./tinyjs new hello && cd hello && ../tinyjs dev"
exit 0
fi
# ---------------------------------------------------------------- macOS ----
if [ "$OS" != "Darwin" ]; then
echo "tinyjs supports macOS and Linux (see README: Portability)" >&2
exit 1
fi
if [ ! -x bin/tjs ]; then
echo "==> downloading txiki.js $TJS_VERSION ($TJS_ARCH)"
mkdir -p bin
curl -fsSL -o "$TMPD/txiki.zip" \
"https://github.com/saghul/txiki.js/releases/download/$TJS_VERSION/txiki-macos-$TJS_ARCH.zip"
unzip -q -o "$TMPD/txiki.zip" -d "$TMPD/txiki"
# Checked against the pin cli.js uses too (runtime/txiki.sha256, #26).
WANT="$(awk -v k="$TJS_VERSION/txiki-macos-$TJS_ARCH" '$2 == k { print $1 }' runtime/txiki.sha256)"
GOT="$(shasum -a 256 "$TMPD/txiki/txiki-macos-$TJS_ARCH/tjs" | cut -d' ' -f1)"
if [ -z "$WANT" ]; then
echo "no pinned sha256 for $TJS_VERSION/txiki-macos-$TJS_ARCH in runtime/txiki.sha256 (got $GOT) — add it first" >&2
exit 1
fi
if [ "$GOT" != "$WANT" ]; then
echo "txiki.js $TJS_VERSION ($TJS_ARCH) has sha256 $GOT, expected $WANT — refusing to install it" >&2
exit 1
fi
mv "$TMPD/txiki/txiki-macos-$TJS_ARCH/tjs" bin/tjs
chmod +x bin/tjs
fi
echo "==> compiling launcher"
./native/gen-client.sh
# Non-weak frameworks (shared); ScreenCaptureKit + FoundationModels are
# weak-linked per-linker below. macOS 14 floor throughout — weak-linked
# frameworks activate only on newer OSes via @available guards.
FW="-framework WebKit -framework AppKit -framework Carbon -framework UserNotifications -framework AVFoundation -framework ServiceManagement -framework IOKit -framework Quartz -framework Vision -framework QuickLookThumbnailing -framework Security -framework LocalAuthentication -framework MediaPlayer -framework CoreMedia -framework CoreWLAN -framework CoreLocation -framework CoreAudio -framework AudioToolbox -framework UniformTypeIdentifiers"
MIN_OS="-mmacosx-version-min=14.0"
# On-device AI (tiny.app.ai) via Apple's FoundationModels. Built automatically
# when the toolchain can — released binaries have it, so a source build should
# match rather than being quietly less capable than the download.
#
# Detected, not guessed at from the OS version: swiftc has to exist AND the
# SDK being compiled against has to carry the framework. Checking the SDK
# rather than the running system matters — a Mac can run macOS 26 while its
# Command Line Tools still ship an older SDK, and that combination compiles
# fine right up until the import.
#
# Set TINYJS_AI=0 to force it off (bisecting the Swift path, or reproducing
# what a machine without the SDK produces).
SDK_PATH="$(xcrun --show-sdk-path 2>/dev/null || true)"
AI_BUILD=0
if [ "${TINYJS_AI:-1}" != "0" ] && command -v swiftc >/dev/null 2>&1 \
&& [ -n "$SDK_PATH" ] \
&& [ -d "$SDK_PATH/System/Library/Frameworks/FoundationModels.framework" ]; then
AI_BUILD=1
fi
# TINYJS_UNIVERSAL=1 builds an arm64 + x86_64 launcher (what release.yml
# ships), which `tinyjs build --universal` needs for an .app that also opens
# on Intel. Default is this Mac's arch only. Each slice is built on its own
# and lipo'd, since swiftc takes a single -target (see below).
ARCHS="$TJS_ARCH"
[ "${TINYJS_UNIVERSAL:-0}" = "1" ] && ARCHS="arm64 x86_64"
BUILD_TMP="$TMPD/build"
mkdir "$BUILD_TMP"
if [ "$AI_BUILD" = "1" ]; then
echo "==> compiling with on-device AI (FoundationModels found in the SDK)"
else
echo "==> compiling without on-device AI (no FoundationModels in this SDK)"
fi
for ARCH in $ARCHS; do
OUT="$BUILD_TMP/launcher-$ARCH"
if [ "$AI_BUILD" = "1" ]; then
# The binary keeps the macOS 14 floor and weak-links FoundationModels, so it
# still launches on macOS 14+ — AI just reports 'unsupported' there.
# Two-step: compile each object, then link with swiftc so the Swift runtime
# is pulled in. swiftc takes the floor via -target (ONE target only — it
# accepts two and silently keeps the last) and needs -Xlinker to pass
# -weak_framework through to the linker.
SWIFT_TARGET="$ARCH-apple-macos14.0"
c++ -std=c++17 -c -x objective-c++ -DTINYJS_AI $MIN_OS -arch "$ARCH" -isystem native/include \
native/launcher-macos.cc -o "$OUT.o"
swiftc -parse-as-library -target "$SWIFT_TARGET" \
-c native/tiny_ai.swift -o "$BUILD_TMP/ai-$ARCH.o"
swiftc "$OUT.o" "$BUILD_TMP/ai-$ARCH.o" -o "$OUT" -lc++ \
-target "$SWIFT_TARGET" $FW \
-Xlinker -weak_framework -Xlinker ScreenCaptureKit \
-Xlinker -weak_framework -Xlinker FoundationModels -ldl
else
c++ -std=c++17 -x objective-c++ $MIN_OS -arch "$ARCH" -isystem native/include native/launcher-macos.cc \
-o "$OUT" $FW -weak_framework ScreenCaptureKit -ldl
fi
done
# shellcheck disable=SC2046
lipo -create $(for ARCH in $ARCHS; do echo "$BUILD_TMP/launcher-$ARCH"; done) -output native/launcher-macos
codesign --force --sign - native/launcher-macos 2>/dev/null || true
echo "==> done"
./bin/tjs --version
echo "try: ./tinyjs new hello && cd hello && ../tinyjs dev"