xbintsc 0.3.69 → 0.3.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -4
- package/README.zh-CN.md +52 -2
- package/dist/tests/e2e/gui-advanced.test.d.ts +6 -0
- package/dist/tests/e2e/gui-advanced.test.js +261 -0
- package/dist/tests/e2e/gui-advanced.test.js.map +1 -0
- package/dist/tests/e2e/gui-canvas.test.d.ts +9 -0
- package/dist/tests/e2e/gui-canvas.test.js +233 -0
- package/dist/tests/e2e/gui-canvas.test.js.map +1 -0
- package/dist/tests/e2e/gui-example.test.d.ts +1 -1
- package/dist/tests/e2e/gui-example.test.js +2 -2
- package/dist/tests/e2e/gui-helpers.d.ts +3 -0
- package/dist/tests/e2e/gui-helpers.js +5 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +73 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.d.ts +8 -0
- package/dist/tests/e2e/gui-media.test.js +119 -0
- package/dist/tests/e2e/gui-media.test.js.map +1 -0
- package/dist/tests/e2e/gui-paint.test.js +40 -0
- package/dist/tests/e2e/gui-paint.test.js.map +1 -1
- package/doc/ai/extensions.md +16 -3
- package/doc/ai/zh-CN/extensions.md +10 -3
- package/doc/gui/animation.md +46 -0
- package/doc/gui/api.md +92 -0
- package/doc/gui/build.md +91 -0
- package/doc/gui/canvas.md +98 -0
- package/doc/gui/dom.md +123 -0
- package/doc/gui/input.md +22 -0
- package/doc/gui/known-issues.md +66 -0
- package/doc/gui/layout.md +72 -0
- package/doc/gui/media.md +87 -0
- package/doc/gui/rendering.md +98 -0
- package/doc/gui/runtime.md +88 -0
- package/doc/gui-scripts.md +7 -3
- package/doc/gui.md +80 -612
- package/doc/implemented.md +1 -0
- package/doc/zh-CN/gui/animation.md +46 -0
- package/doc/zh-CN/gui/api.md +88 -0
- package/doc/zh-CN/gui/build.md +84 -0
- package/doc/zh-CN/gui/canvas.md +80 -0
- package/doc/zh-CN/gui/dom.md +114 -0
- package/doc/zh-CN/gui/input.md +21 -0
- package/doc/zh-CN/gui/known-issues.md +50 -0
- package/doc/zh-CN/gui/layout.md +60 -0
- package/doc/zh-CN/gui/media.md +71 -0
- package/doc/zh-CN/gui/rendering.md +81 -0
- package/doc/zh-CN/gui/runtime.md +76 -0
- package/doc/zh-CN/gui-scripts.md +6 -2
- package/doc/zh-CN/gui.md +64 -532
- package/doc/zh-CN/implemented.md +1 -0
- package/llms.txt +15 -2
- package/package.json +1 -1
- package/runtime/ext_gui/canvas.cpp +580 -0
- package/runtime/ext_gui/canvas.h +170 -0
- package/runtime/ext_gui/canvas_internal.h +59 -0
- package/runtime/ext_gui/canvas_raster.cpp +254 -0
- package/runtime/ext_gui/document.cpp +24 -1
- package/runtime/ext_gui/document.h +11 -0
- package/runtime/ext_gui/dom_api.cpp +3 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +548 -0
- package/runtime/ext_gui/dom_api_internal.h +73 -0
- package/runtime/ext_gui/dom_api_media.cpp +274 -0
- package/runtime/ext_gui/dom_api_proto.cpp +80 -0
- package/runtime/ext_gui/gui.cpp +6 -0
- package/runtime/ext_gui/gui_canvas.cpp +95 -0
- package/runtime/ext_gui/gui_engine.h +49 -0
- package/runtime/ext_gui/gui_events.cpp +21 -5
- package/runtime/ext_gui/gui_media.cpp +193 -0
- package/runtime/ext_gui/image.cpp +31 -12
- package/runtime/ext_gui/image.h +20 -7
- package/runtime/ext_gui/layout.cpp +52 -5
- package/runtime/ext_gui/layout.h +33 -1
- package/runtime/ext_gui/layout_flex.cpp +263 -99
- package/runtime/ext_gui/layout_flow.cpp +85 -9
- package/runtime/ext_gui/layout_flow_internal.h +84 -5
- package/runtime/ext_gui/layout_inline.cpp +54 -37
- package/runtime/ext_gui/media.cpp +514 -0
- package/runtime/ext_gui/media.h +104 -0
- package/runtime/ext_gui/nanosvg.h +3278 -0
- package/runtime/ext_gui/nanosvgrast.h +1472 -0
- package/runtime/ext_gui/paint.cpp +123 -38
- package/runtime/ext_gui/paint.h +36 -6
- package/runtime/ext_gui/renderer.cpp +113 -10
- package/runtime/ext_gui/renderer.h +49 -9
- package/runtime/ext_gui/renderer_image.cpp +203 -77
- package/runtime/ext_gui/renderer_internal.h +6 -8
- package/runtime/ext_gui/renderer_text.cpp +11 -26
- package/runtime/ext_gui/style.h +11 -0
- package/runtime/ext_gui/style_print.cpp +11 -0
- package/runtime/ext_gui/style_ua.cpp +7 -0
- package/runtime/ext_gui/style_values.cpp +40 -1
- package/runtime/ext_gui/svg.cpp +182 -0
- package/runtime/ext_gui/svg.h +46 -0
- package/runtime/ext_gui/text.cpp +156 -25
- package/runtime/ext_gui/text.h +11 -2
- package/runtime/ext_gui/window.cpp +4 -1
- package/scripts/build-gui.ts +148 -6
- package/scripts/check-file-length.ts +5 -1
- package/scripts/install-gui-deps.sh +28 -0
package/scripts/build-gui.ts
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* 1. fetch the pinned SDL3 source into `vendor/SDL` (gitignored),
|
|
14
14
|
* 2. build `libSDL3.a` with CMake,
|
|
15
15
|
* 2b. fetch + build static FreeType and HarfBuzz for text,
|
|
16
|
+
* 2c. fetch + build a minimal static FFmpeg for `<video>`/`<audio>`
|
|
17
|
+
* (skipped on Windows, where media support is compiled out),
|
|
16
18
|
* 3. compile the engine translation units,
|
|
17
19
|
* 4. merge everything into `gui.a` (libtool on macOS, `ar -M` elsewhere;
|
|
18
20
|
* `gui.lib` on Windows, built from MSVC-compatible COFF objects).
|
|
@@ -31,6 +33,7 @@
|
|
|
31
33
|
*/
|
|
32
34
|
|
|
33
35
|
import { existsSync, mkdirSync, readdirSync, renameSync, rmSync } from "node:fs";
|
|
36
|
+
import { availableParallelism } from "node:os";
|
|
34
37
|
import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
35
38
|
import { dirname, join, resolve } from "node:path";
|
|
36
39
|
import { fileURLToPath } from "node:url";
|
|
@@ -41,11 +44,23 @@ const runtimeDir = join(root, "runtime");
|
|
|
41
44
|
const engineDir = join(runtimeDir, "ext_gui");
|
|
42
45
|
const vendorDir = join(root, "vendor");
|
|
43
46
|
const sdlSrc = join(vendorDir, "SDL");
|
|
44
|
-
|
|
47
|
+
/* SDL's build tree is a *sibling* of its source, like FreeType's and HarfBuzz's,
|
|
48
|
+
* never inside it: the CI cache keyed on a vendored library ships the whole
|
|
49
|
+
* `vendor/SDL` tree, and a CMake build tree is not relocatable across machines
|
|
50
|
+
* or platforms. `CMakeCache.txt` records the host's compiler and probes, and
|
|
51
|
+
* SDL's video options are `option()`s — the first configure to run wins, so a
|
|
52
|
+
* cached `SDL_X11=OFF` (e.g. from a Windows configure, where the option's
|
|
53
|
+
* default is OFF) survives into a Linux configure and SDL then aborts with
|
|
54
|
+
* "SDL could not find X11 or Wayland development libraries". Keeping the build
|
|
55
|
+
* tree out of the cached source path makes each machine configure its own. */
|
|
56
|
+
const sdlBuild = join(vendorDir, "sdl-build");
|
|
45
57
|
const freetypeSrc = join(vendorDir, "freetype");
|
|
46
58
|
const freetypeBuild = join(vendorDir, "freetype-build");
|
|
47
59
|
const harfbuzzSrc = join(vendorDir, "harfbuzz");
|
|
48
60
|
const harfbuzzBuild = join(vendorDir, "harfbuzz-build");
|
|
61
|
+
const ffmpegSrc = join(vendorDir, "ffmpeg");
|
|
62
|
+
const ffmpegBuild = join(vendorDir, "ffmpeg-build");
|
|
63
|
+
const ffmpegInstall = join(ffmpegBuild, "dist");
|
|
49
64
|
const objDir = join(root, "build", "gui-obj");
|
|
50
65
|
const outDir = join(runtimeDir, "lib", platformSlug());
|
|
51
66
|
|
|
@@ -82,8 +97,24 @@ const cmakeGeneratorArgs: readonly string[] = isWindows
|
|
|
82
97
|
const SDL_TAG = process.env.SDL3_TAG || "release-3.2.10";
|
|
83
98
|
const FREETYPE_VERSION = process.env.FREETYPE_VERSION || "2.13.3";
|
|
84
99
|
const HARFBUZZ_VERSION = process.env.HARFBUZZ_VERSION || "10.1.0";
|
|
100
|
+
const FFMPEG_VERSION = process.env.FFMPEG_VERSION || "7.1";
|
|
85
101
|
const FREETYPE_URL = `https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.xz`;
|
|
86
102
|
const HARFBUZZ_URL = `https://github.com/harfbuzz/harfbuzz/releases/download/${HARFBUZZ_VERSION}/harfbuzz-${HARFBUZZ_VERSION}.tar.xz`;
|
|
103
|
+
const FFMPEG_URL = `https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz`;
|
|
104
|
+
|
|
105
|
+
/* A deliberately minimal FFmpeg: containers and decoders for the common web
|
|
106
|
+
* media formats, file access only, no network, no encoder, no filter graph.
|
|
107
|
+
* Disabling everything first keeps the static libraries small and the build
|
|
108
|
+
* short. `--disable-x86asm` drops the nasm/yasm build dependency (the C
|
|
109
|
+
* fallbacks are plenty for playback). This configuration is LGPL-only, so the
|
|
110
|
+
* resulting `gui.a` stays redistributable under the engine's terms. */
|
|
111
|
+
const FFMPEG_COMPONENTS: readonly string[] = [
|
|
112
|
+
"--enable-protocol=file",
|
|
113
|
+
"--enable-demuxer=mov,matroska,avi,flv,mpegts,mp3,ogg,wav,flac,aac,m4v,asf,mpeg,mpegvideo,h264,hevc,vc1",
|
|
114
|
+
"--enable-decoder=h264,hevc,vp8,vp9,av1,aac,aac_latm,mp3,mp3float,opus,vorbis,flac,alac,pcm_s16le,pcm_s24le,pcm_s32le,pcm_u8,pcm_f32le,pcm_alaw,pcm_mulaw,ac3,eac3,wmav2,mjpeg",
|
|
115
|
+
"--enable-parser=h264,hevc,vp8,vp9,av1,aac,aac_latm,mpegaudio,opus,vorbis,mpeg4video,mjpeg,flac",
|
|
116
|
+
"--enable-bsf=h264_mp4toannexb,hevc_mp4toannexb,aac_adtstoasc,vp9_superframe,vp9_superframe_split,extract_extradata",
|
|
117
|
+
];
|
|
87
118
|
|
|
88
119
|
function fail(message: string): never {
|
|
89
120
|
console.error(`xbintsc: ${message}`);
|
|
@@ -93,13 +124,14 @@ function fail(message: string): never {
|
|
|
93
124
|
function run(
|
|
94
125
|
command: string,
|
|
95
126
|
args: readonly string[],
|
|
96
|
-
options: { input?: string; quietStderr?: boolean } = {},
|
|
127
|
+
options: { input?: string; quietStderr?: boolean; cwd?: string } = {},
|
|
97
128
|
): SpawnSyncReturns<string> {
|
|
98
129
|
const quiet = options.quietStderr === true;
|
|
99
130
|
const result = spawnSync(command, args, {
|
|
100
131
|
stdio: options.input !== undefined ? ["pipe", "inherit", "inherit"] : quiet ? ["ignore", "inherit", "pipe"] : "inherit",
|
|
101
132
|
encoding: "utf8",
|
|
102
133
|
input: options.input,
|
|
134
|
+
cwd: options.cwd,
|
|
103
135
|
});
|
|
104
136
|
if (result.status !== 0) {
|
|
105
137
|
if (quiet && result.stderr) process.stderr.write(result.stderr);
|
|
@@ -142,12 +174,49 @@ function findCxx(): string {
|
|
|
142
174
|
return cxx;
|
|
143
175
|
}
|
|
144
176
|
|
|
177
|
+
function findCc(): string {
|
|
178
|
+
const cc = firstAvailable([process.env.xbintsc_CC, process.env.CC, "clang", "cc", "gcc"]);
|
|
179
|
+
if (!cc) fail("no C compiler found; install clang or set xbintsc_CC");
|
|
180
|
+
return cc;
|
|
181
|
+
}
|
|
182
|
+
|
|
145
183
|
function findArchiver(): string {
|
|
146
184
|
const ar = firstAvailable([process.env.xbintsc_AR, "llvm-ar", "ar"]);
|
|
147
185
|
if (!ar) fail("no archiver found; set xbintsc_AR to llvm-ar or ar");
|
|
148
186
|
return ar;
|
|
149
187
|
}
|
|
150
188
|
|
|
189
|
+
/** Directories a CMake `find_path` would search, relative to the filesystem
|
|
190
|
+
* root, used to check that a development package is installed. */
|
|
191
|
+
const HEADER_PREFIXES = ["/usr/include", "/usr/local/include", "/opt/homebrew/include"];
|
|
192
|
+
|
|
193
|
+
/** True on Debian and its derivatives, where the message below can name the
|
|
194
|
+
* packages to install. Anywhere else the headers may well live under a prefix
|
|
195
|
+
* this check does not know (`/usr/pkg`, `/nix/store`, …), so it stays quiet
|
|
196
|
+
* instead of failing a build that would have worked. */
|
|
197
|
+
function isDebianLike(): boolean {
|
|
198
|
+
return existsSync("/etc/debian_version");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Fail with the package names to install when a header SDL needs is missing,
|
|
202
|
+
* rather than letting SDL configure itself without a window backend and then
|
|
203
|
+
* abort with a summary that does not say which package is missing. */
|
|
204
|
+
function requireHeaders(feature: string, headers: readonly string[], packages: string): void {
|
|
205
|
+
if (isWindows || !isDebianLike()) return;
|
|
206
|
+
const missing = headers.filter(
|
|
207
|
+
(header) => !HEADER_PREFIXES.some((prefix) => existsSync(join(prefix, header))),
|
|
208
|
+
);
|
|
209
|
+
if (missing.length === 0) return;
|
|
210
|
+
const hint =
|
|
211
|
+
process.env.xbintsc_SKIP_HEADER_CHECK === "1"
|
|
212
|
+
? ""
|
|
213
|
+
: " (set xbintsc_SKIP_HEADER_CHECK=1 if they are installed under a prefix this check does not know)";
|
|
214
|
+
fail(
|
|
215
|
+
`${feature} needs ${missing.join(", ")}, which is not installed; ` +
|
|
216
|
+
`install its development package first (Debian/Ubuntu: ${packages})${hint}`,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
151
220
|
/** First of `candidates` that exists on disk (CMake generators place static
|
|
152
221
|
* libraries either at the build root or under `Release/`). */
|
|
153
222
|
function firstExisting(candidates: readonly string[]): string | undefined {
|
|
@@ -187,6 +256,16 @@ function harfbuzzArchive(): string | undefined {
|
|
|
187
256
|
return builtLibrary(harfbuzzBuild, ["libharfbuzz.a", "harfbuzz.lib"], /^harfbuzz[-\d.]*\.lib$/);
|
|
188
257
|
}
|
|
189
258
|
|
|
259
|
+
/* FFmpeg's release tarball has no CMake build, so it uses its own configure +
|
|
260
|
+
* make. It also installs its headers under a prefix (rather than in the source
|
|
261
|
+
* tree) because the *source* root contains a file literally named `version`
|
|
262
|
+
* that would shadow the C++ standard header for any `.cpp` that includes it. */
|
|
263
|
+
const FFMPEG_LIBRARY_NAMES = ["libavformat.a", "libavcodec.a", "libswscale.a", "libswresample.a", "libavutil.a"];
|
|
264
|
+
function ffmpegStaticLibraries(): string[] | undefined {
|
|
265
|
+
const libraries = FFMPEG_LIBRARY_NAMES.map((name) => join(ffmpegInstall, "lib", name));
|
|
266
|
+
return libraries.every((library) => existsSync(library)) ? libraries : undefined;
|
|
267
|
+
}
|
|
268
|
+
|
|
190
269
|
/* -- 1. SDL3 source ------------------------------------------------------- */
|
|
191
270
|
|
|
192
271
|
if (!existsSync(join(sdlSrc, "CMakeLists.txt"))) {
|
|
@@ -199,6 +278,28 @@ if (!existsSync(join(sdlSrc, "CMakeLists.txt"))) {
|
|
|
199
278
|
|
|
200
279
|
const existingSdlArchive = sdlArchive();
|
|
201
280
|
if (!existingSdlArchive) {
|
|
281
|
+
/* Older trees configured SDL inside its source (`vendor/SDL/build`) and a
|
|
282
|
+
* cache from one of those would be reused by the next configure — the exact
|
|
283
|
+
* failure `sdlBuild` above exists to prevent. */
|
|
284
|
+
const legacyBuild = join(sdlSrc, "build");
|
|
285
|
+
if (existsSync(join(legacyBuild, "CMakeCache.txt"))) {
|
|
286
|
+
console.log("xbintsc: discarding the legacy in-source SDL build tree");
|
|
287
|
+
rmSync(legacyBuild, { recursive: true, force: true });
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* SDL enables a window backend from the headers it finds, and aborts when it
|
|
291
|
+
* finds neither X11 nor Wayland, so say which package is missing instead of
|
|
292
|
+
* relaying its summary. */
|
|
293
|
+
requireHeaders(
|
|
294
|
+
"SDL3's X11 video driver",
|
|
295
|
+
/* `Xlib.h` comes from libx11-dev; `Xext.h` is the header SDL gates HAVE_X11
|
|
296
|
+
* on as well, and it comes from libxext-dev. */
|
|
297
|
+
["X11/Xlib.h", "X11/extensions/Xext.h"],
|
|
298
|
+
"libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxinerama-dev libxfixes-dev",
|
|
299
|
+
);
|
|
300
|
+
requireHeaders("SDL3's Wayland video driver", ["wayland-client-core.h"],
|
|
301
|
+
"libwayland-dev libxkbcommon-dev libdecor-0-dev");
|
|
302
|
+
|
|
202
303
|
const cmake = findCmake();
|
|
203
304
|
console.log(`xbintsc: building static SDL3 with ${cmake}`);
|
|
204
305
|
const configureArgs = [
|
|
@@ -221,10 +322,12 @@ if (!existingSdlArchive) {
|
|
|
221
322
|
|
|
222
323
|
/** Download a release tarball into `vendor/` and extract it under `name`.
|
|
223
324
|
* Release tarballs are used (not git clones) because they ship generated
|
|
224
|
-
* sources, so no ragel/autotools step is needed.
|
|
225
|
-
|
|
325
|
+
* sources, so no ragel/autotools step is needed. `marker` is a file that only
|
|
326
|
+
* exists once the tarball has been extracted (CMake projects ship
|
|
327
|
+
* `CMakeLists.txt`; FFmpeg ships `configure`). */
|
|
328
|
+
function ensureTarballSource(name: string, url: string, extractedName: string, marker = "CMakeLists.txt"): string {
|
|
226
329
|
const destination = join(vendorDir, name);
|
|
227
|
-
if (existsSync(join(destination,
|
|
330
|
+
if (existsSync(join(destination, marker))) return destination;
|
|
228
331
|
const tarball = join(vendorDir, `${name}.tar.xz`);
|
|
229
332
|
console.log(`xbintsc: fetching ${name} from ${url}`);
|
|
230
333
|
mkdirSync(vendorDir, { recursive: true });
|
|
@@ -284,6 +387,43 @@ if (!existsSync(harfbuzzArchive() ?? "")) {
|
|
|
284
387
|
console.log(`xbintsc: reusing existing ${harfbuzzArchive()}`);
|
|
285
388
|
}
|
|
286
389
|
|
|
390
|
+
/* -- 2c. FFmpeg (media decoding) ------------------------------------------ */
|
|
391
|
+
|
|
392
|
+
/* Windows builds have no `configure`/`make`, so media support is compiled out
|
|
393
|
+
* there; the element still works and reports an `error` event. */
|
|
394
|
+
let ffmpegLibraries: string[] | undefined;
|
|
395
|
+
if (isWindows) {
|
|
396
|
+
console.log("xbintsc: skipping FFmpeg on Windows; <video>/<audio> will report an error");
|
|
397
|
+
} else {
|
|
398
|
+
ensureTarballSource("ffmpeg", FFMPEG_URL, `ffmpeg-${FFMPEG_VERSION}`, "configure");
|
|
399
|
+
ffmpegLibraries = ffmpegStaticLibraries();
|
|
400
|
+
if (!ffmpegLibraries) {
|
|
401
|
+
const cc = findCc();
|
|
402
|
+
const ccxx = findCxx();
|
|
403
|
+
console.log(`xbintsc: building minimal static FFmpeg ${FFMPEG_VERSION} with ${cc}`);
|
|
404
|
+
mkdirSync(ffmpegBuild, { recursive: true });
|
|
405
|
+
run(join(ffmpegSrc, "configure"), [
|
|
406
|
+
`--prefix=${ffmpegInstall}`,
|
|
407
|
+
"--enable-static", "--disable-shared",
|
|
408
|
+
"--disable-programs", "--disable-doc",
|
|
409
|
+
"--disable-htmlpages", "--disable-manpages", "--disable-podpages", "--disable-txtpages",
|
|
410
|
+
"--disable-avdevice", "--disable-avfilter", "--disable-postproc",
|
|
411
|
+
"--disable-everything",
|
|
412
|
+
"--enable-avformat", "--enable-avcodec", "--enable-avutil", "--enable-swscale", "--enable-swresample",
|
|
413
|
+
"--disable-network", "--disable-autodetect", "--disable-x86asm", "--disable-debug", "--enable-pic",
|
|
414
|
+
`--cc=${cc}`,
|
|
415
|
+
`--cxx=${ccxx}`,
|
|
416
|
+
...FFMPEG_COMPONENTS,
|
|
417
|
+
], { cwd: ffmpegBuild });
|
|
418
|
+
run("make", ["-j", String(availableParallelism())], { cwd: ffmpegBuild });
|
|
419
|
+
run("make", ["install"], { cwd: ffmpegBuild });
|
|
420
|
+
ffmpegLibraries = ffmpegStaticLibraries();
|
|
421
|
+
} else {
|
|
422
|
+
console.log(`xbintsc: reusing existing ${ffmpegInstall}/lib`);
|
|
423
|
+
}
|
|
424
|
+
if (!ffmpegLibraries) fail("FFmpeg build did not produce the expected static libraries");
|
|
425
|
+
}
|
|
426
|
+
|
|
287
427
|
/* -- 3. engine objects ---------------------------------------------------- */
|
|
288
428
|
|
|
289
429
|
const cxx = findCxx();
|
|
@@ -295,12 +435,14 @@ const includeFlags = [
|
|
|
295
435
|
"-I", join(freetypeBuild, "include"),
|
|
296
436
|
"-I", join(harfbuzzSrc, "src"),
|
|
297
437
|
];
|
|
438
|
+
if (ffmpegLibraries) includeFlags.push("-I", join(ffmpegInstall, "include"));
|
|
298
439
|
const sources = readdirSync(engineDir)
|
|
299
440
|
.filter((entry) => entry.endsWith(".cpp"))
|
|
300
441
|
.sort();
|
|
301
442
|
|
|
302
443
|
const objects: string[] = [];
|
|
303
444
|
const cxxFlags = ["-std=c++17", "-O2", "-Wall", "-Wextra", ...includeFlags];
|
|
445
|
+
if (ffmpegLibraries) cxxFlags.push("-DXT_GUI_WITH_FFMPEG=1");
|
|
304
446
|
/* The engine is C++ and the MSVC C++ runtime must match the static C CRT that
|
|
305
447
|
* clang links by default, so let every engine object record `libcpmt` as a
|
|
306
448
|
* default library. The extension itself only contributes the DLL import library
|
|
@@ -324,7 +466,7 @@ const harfbuzz = harfbuzzArchive();
|
|
|
324
466
|
if (!sdl || !freetype || !harfbuzz) {
|
|
325
467
|
fail("one of the SDL3/FreeType/HarfBuzz archives was not found after building");
|
|
326
468
|
}
|
|
327
|
-
const libraries = [sdl, freetype, harfbuzz];
|
|
469
|
+
const libraries = [sdl, freetype, harfbuzz, ...(ffmpegLibraries ?? [])];
|
|
328
470
|
|
|
329
471
|
mkdirSync(outDir, { recursive: true });
|
|
330
472
|
rmSync(output, { force: true });
|
|
@@ -36,7 +36,11 @@ const IGNORED_DIRECTORIES = new Set([
|
|
|
36
36
|
]);
|
|
37
37
|
|
|
38
38
|
/** Vendored third-party sources that ship verbatim and are not ours to split. */
|
|
39
|
-
const VENDORED_FILES = new Set([
|
|
39
|
+
const VENDORED_FILES = new Set([
|
|
40
|
+
join("runtime", "ext_gui", "stb_image.h"),
|
|
41
|
+
join("runtime", "ext_gui", "nanosvg.h"),
|
|
42
|
+
join("runtime", "ext_gui", "nanosvgrast.h"),
|
|
43
|
+
]);
|
|
40
44
|
|
|
41
45
|
/** Machine-generated files: they are reproduced from their sources by a script,
|
|
42
46
|
* so their size is not a sign of a module that needs splitting. */
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
# Install everything Linux needs to build and exercise the GUI archive.
|
|
4
|
+
#
|
|
5
|
+
# `npm run gui` compiles SDL3 from source, so SDL3 needs to *find* the window
|
|
6
|
+
# system it will use: without the X11/Wayland development headers it either
|
|
7
|
+
# configures itself without a window backend and then aborts ("SDL could not
|
|
8
|
+
# find X11 or Wayland development libraries"), or -- now -- `scripts/build-gui.ts`
|
|
9
|
+
# says which package is missing. `cmake` configures the vendored libraries,
|
|
10
|
+
# `clang` compiles the runtime and the emitted LLVM IR, `libvulkan-dev` plus a
|
|
11
|
+
# driver gives SDL_GPU the Vulkan backend it selects on Linux, and `xvfb` lets
|
|
12
|
+
# the example and the e2e suites run headlessly.
|
|
13
|
+
#
|
|
14
|
+
# One list, one place: every Linux job that runs `npm run gui` (or a GUI
|
|
15
|
+
# example) sources this, so a job cannot quietly miss a package the others
|
|
16
|
+
# install. Requires sudo and a Debian/Ubuntu host.
|
|
17
|
+
#
|
|
18
|
+
# Usage: sudo sh scripts/install-gui-deps.sh
|
|
19
|
+
set -eu
|
|
20
|
+
|
|
21
|
+
apt-get update
|
|
22
|
+
apt-get install -y \
|
|
23
|
+
clang cmake \
|
|
24
|
+
libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev \
|
|
25
|
+
libxinerama-dev libxfixes-dev libxkbcommon-dev libwayland-dev \
|
|
26
|
+
wayland-protocols libdecor-0-dev libasound2-dev libpulse-dev \
|
|
27
|
+
libdbus-1-dev libudev-dev libdrm-dev libgbm-dev libgl1-mesa-dev \
|
|
28
|
+
libegl1-mesa-dev libvulkan-dev mesa-vulkan-drivers xvfb
|