xbintsc 0.5.52 → 0.6.8
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 +8 -2
- package/README.zh-CN.md +9 -3
- package/dist/scripts/fetch-tarball.d.ts +28 -0
- package/dist/scripts/fetch-tarball.js +57 -0
- package/dist/scripts/fetch-tarball.js.map +1 -0
- package/dist/scripts/gui-build-options.d.ts +77 -0
- package/dist/scripts/gui-build-options.js +134 -0
- package/dist/scripts/gui-build-options.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/hints.d.ts +6 -2
- package/dist/src/cli/hints.js +16 -2
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +9 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/driver/app-artifacts.d.ts +2 -0
- package/dist/src/driver/app-artifacts.js +3 -3
- package/dist/src/driver/app-artifacts.js.map +1 -1
- package/dist/src/driver/compiler.js +147 -52
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/icon.d.ts +1 -1
- package/dist/src/driver/icon.js +3 -3
- package/dist/src/driver/icon.js.map +1 -1
- package/dist/src/driver/macos-sdk.d.ts +32 -0
- package/dist/src/driver/macos-sdk.js +50 -0
- package/dist/src/driver/macos-sdk.js.map +1 -0
- package/dist/src/driver/options.d.ts +6 -0
- package/dist/src/driver/platform-support.d.ts +45 -0
- package/dist/src/driver/platform-support.js +66 -0
- package/dist/src/driver/platform-support.js.map +1 -0
- package/dist/src/driver/prebuilt.d.ts +26 -0
- package/dist/src/driver/prebuilt.js +58 -0
- package/dist/src/driver/prebuilt.js.map +1 -0
- package/dist/src/driver/runtime-objects.d.ts +11 -0
- package/dist/src/driver/runtime-objects.js +14 -5
- package/dist/src/driver/runtime-objects.js.map +1 -1
- package/dist/src/driver/toolchain-provider.d.ts +8 -0
- package/dist/src/driver/toolchain-provider.js +8 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -1
- package/dist/src/driver/toolchain.d.ts +20 -1
- package/dist/src/driver/toolchain.js +19 -0
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/driver/version.js.map +1 -1
- package/dist/src/driver/win-entry.d.ts +1 -1
- package/dist/src/driver/win-entry.js +4 -4
- package/dist/src/driver/win-entry.js.map +1 -1
- package/dist/src/extensions/gui/html.d.ts +10 -7
- package/dist/src/extensions/gui/html.js +53 -29
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/node/child_process/index.d.ts +4 -3
- package/dist/src/extensions/node/child_process/index.js +4 -3
- package/dist/src/extensions/node/child_process/index.js.map +1 -1
- package/dist/tests/cli/hints.test.js +9 -1
- package/dist/tests/cli/hints.test.js.map +1 -1
- package/dist/tests/cli/main.test.js +9 -0
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/driver/compiler.test.js +107 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/cxx-compile-flags.test.d.ts +1 -0
- package/dist/tests/driver/cxx-compile-flags.test.js +24 -0
- package/dist/tests/driver/cxx-compile-flags.test.js.map +1 -0
- package/dist/tests/driver/macos-sdk.test.d.ts +1 -0
- package/dist/tests/driver/macos-sdk.test.js +83 -0
- package/dist/tests/driver/macos-sdk.test.js.map +1 -0
- package/dist/tests/driver/platform-support.test.d.ts +1 -0
- package/dist/tests/driver/platform-support.test.js +41 -0
- package/dist/tests/driver/platform-support.test.js.map +1 -0
- package/dist/tests/driver/prebuilt.test.d.ts +1 -0
- package/dist/tests/driver/prebuilt.test.js +44 -0
- package/dist/tests/driver/prebuilt.test.js.map +1 -0
- package/dist/tests/driver/toolchain-provider.test.js +24 -0
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
- package/dist/tests/driver/toolchain.test.js +23 -0
- package/dist/tests/driver/toolchain.test.js.map +1 -1
- package/dist/tests/e2e/async-await.test.js +4 -2
- package/dist/tests/e2e/async-await.test.js.map +1 -1
- package/dist/tests/e2e/compile-node.test.js +21 -0
- package/dist/tests/e2e/compile-node.test.js.map +1 -1
- package/dist/tests/e2e/fetch.test.js +34 -6
- package/dist/tests/e2e/fetch.test.js.map +1 -1
- package/dist/tests/e2e/gui-example-pelican3d.test.d.ts +10 -0
- package/dist/tests/e2e/gui-example-pelican3d.test.js +94 -0
- package/dist/tests/e2e/gui-example-pelican3d.test.js.map +1 -0
- package/dist/tests/e2e/gui-script.test.js +48 -0
- package/dist/tests/e2e/gui-script.test.js.map +1 -1
- package/dist/tests/e2e/unhandled-rejection.test.d.ts +14 -0
- package/dist/tests/e2e/unhandled-rejection.test.js +107 -0
- package/dist/tests/e2e/unhandled-rejection.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +44 -0
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/dist/tests/scripts/fetch-tarball.test.d.ts +1 -0
- package/dist/tests/scripts/fetch-tarball.test.js +70 -0
- package/dist/tests/scripts/fetch-tarball.test.js.map +1 -0
- package/doc/ai/cli.md +6 -0
- package/doc/ai/language-support.md +1 -0
- package/doc/ai/troubleshooting.md +32 -2
- package/doc/ai/zh-CN/cli.md +5 -0
- package/doc/ai/zh-CN/language-support.md +1 -0
- package/doc/ai/zh-CN/troubleshooting.md +27 -2
- package/doc/gui/build.md +7 -3
- package/doc/gui/dom.md +3 -1
- package/doc/gui/webgl.md +4 -0
- package/doc/gui-scripts.md +33 -17
- package/doc/gui.md +17 -1
- package/doc/implemented/async.md +1 -0
- package/doc/implemented/modules.md +9 -6
- package/doc/implemented/node/child-process.md +12 -4
- package/doc/implemented/runtime-core.md +1 -1
- package/doc/npm-package.md +23 -2
- package/doc/post/make-js-great-again.md +30 -0
- package/doc/requirements.md +31 -0
- package/doc/unimplemented/deviations.md +1 -0
- package/doc/zh-CN/gui/build.md +4 -2
- package/doc/zh-CN/gui/dom.md +3 -1
- package/doc/zh-CN/gui/webgl.md +1 -0
- package/doc/zh-CN/gui-scripts.md +23 -11
- package/doc/zh-CN/gui.md +11 -1
- package/doc/zh-CN/implemented/async.md +1 -0
- package/doc/zh-CN/implemented/modules.md +8 -4
- package/doc/zh-CN/implemented/node/child-process.md +10 -3
- package/doc/zh-CN/implemented/runtime-core.md +1 -1
- package/doc/zh-CN/npm-package.md +18 -1
- package/doc/zh-CN/post/make-js-great-again.md +32 -0
- package/doc/zh-CN/requirements.md +25 -0
- package/doc/zh-CN/unimplemented/deviations.md +1 -0
- package/package.json +7 -7
- package/runtime/ext_node/child_process/child_process.c +149 -7
- package/runtime/rt.h +4 -0
- package/runtime/xt_async.c +4 -0
- package/runtime/xt_generator.c +2 -0
- package/runtime/xt_loop.c +8 -4
- package/runtime/xt_promise.c +103 -0
- package/scripts/build-gui.ts +17 -5
- package/scripts/build-media.ts +89 -10
- package/scripts/build-runtime.ts +7 -2
- package/scripts/fetch-tarball.ts +71 -0
- package/scripts/gui-build-cache.ts +28 -0
- package/scripts/gui-build-options.ts +26 -2
- package/scripts/package-release.ts +8 -0
- package/src/cli/hints.ts +19 -2
- package/src/cli/main.ts +11 -0
- package/src/driver/app-artifacts.ts +5 -3
- package/src/driver/compiler.ts +167 -56
- package/src/driver/icon.ts +3 -2
- package/src/driver/macos-sdk.ts +52 -0
- package/src/driver/options.ts +6 -0
- package/src/driver/platform-support.ts +69 -0
- package/src/driver/prebuilt.ts +61 -0
- package/src/driver/runtime-objects.ts +26 -5
- package/src/driver/toolchain-provider.ts +11 -0
- package/src/driver/toolchain.ts +26 -1
- package/src/driver/version.ts +1 -1
- package/src/driver/win-entry.ts +4 -3
- package/src/extensions/gui/html.ts +61 -31
- package/src/extensions/node/child_process/index.ts +4 -3
package/scripts/build-gui.ts
CHANGED
|
@@ -49,15 +49,18 @@ import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
|
49
49
|
import { dirname, join, resolve } from "node:path";
|
|
50
50
|
import { fileURLToPath } from "node:url";
|
|
51
51
|
import { platformSlug } from "../src/driver/paths.js";
|
|
52
|
+
import { applyMacosDeploymentTarget } from "../src/driver/platform-support.js";
|
|
52
53
|
import { isMsvcTarget, probeClang, realRunner } from "../src/driver/toolchain.js";
|
|
53
54
|
import { resolveToolchain } from "../src/driver/toolchain-provider.js";
|
|
54
55
|
import {
|
|
55
56
|
cmakeToolchainArgs,
|
|
57
|
+
cxxCompileFlags,
|
|
56
58
|
HB_LEAN_DEFINES,
|
|
57
59
|
LEAN_SDL_OPTIONS,
|
|
58
60
|
SECTION_CMAKE_FLAGS,
|
|
59
61
|
SECTION_FLAGS,
|
|
60
62
|
} from "./gui-build-options.js";
|
|
63
|
+
import { ensureDeploymentTarget } from "./gui-build-cache.js";
|
|
61
64
|
|
|
62
65
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
63
66
|
const runtimeDir = join(root, "runtime");
|
|
@@ -99,6 +102,10 @@ const isWindows = process.platform === "win32";
|
|
|
99
102
|
const objectSuffix = isWindows ? ".obj" : ".o";
|
|
100
103
|
const output = join(outDir, isWindows ? "gui.lib" : "gui.a");
|
|
101
104
|
|
|
105
|
+
/* The vendored CMake builds and the direct engine compiles must target the
|
|
106
|
+
* oldest supported macOS, not the build machine's version. */
|
|
107
|
+
applyMacosDeploymentTarget();
|
|
108
|
+
|
|
102
109
|
const SDL_TAG = process.env.SDL3_TAG || "release-3.2.10";
|
|
103
110
|
const FREETYPE_VERSION = process.env.FREETYPE_VERSION || "2.13.3";
|
|
104
111
|
const HARFBUZZ_VERSION = process.env.HARFBUZZ_VERSION || "10.1.0";
|
|
@@ -204,19 +211,19 @@ function findArchiver(clangPath: string): string {
|
|
|
204
211
|
* sibling clang++, and the matching llvm-ar. No `gcc`/`g++` fallbacks, and
|
|
205
212
|
* Windows never falls back to a non-LLVM archiver — mixing another C++ runtime
|
|
206
213
|
* or object format would break the final link. */
|
|
207
|
-
function
|
|
214
|
+
function driverToolchain(): ReturnType<typeof resolveToolchain> {
|
|
208
215
|
try {
|
|
209
|
-
return resolveToolchain()
|
|
216
|
+
return resolveToolchain();
|
|
210
217
|
} catch (error) {
|
|
211
218
|
fail(error instanceof Error ? error.message : String(error));
|
|
212
219
|
}
|
|
213
220
|
}
|
|
214
221
|
|
|
215
|
-
const
|
|
222
|
+
const toolchain = driverToolchain();
|
|
223
|
+
const clang = toolchain.clang;
|
|
216
224
|
const clangxx = findClangxx(clang);
|
|
217
225
|
const llvmAr = findArchiver(clang);
|
|
218
226
|
|
|
219
|
-
|
|
220
227
|
/** The compiler a previous CMake configure recorded for `buildDir`. */
|
|
221
228
|
function cachedCompiler(buildDir: string, variable: string): string | undefined {
|
|
222
229
|
const cache = join(buildDir, "CMakeCache.txt");
|
|
@@ -348,6 +355,7 @@ if (!existsSync(join(sdlSrc, "CMakeLists.txt"))) {
|
|
|
348
355
|
|
|
349
356
|
/* -- 2. static SDL3 ------------------------------------------------------- */
|
|
350
357
|
|
|
358
|
+
ensureDeploymentTarget("SDL3", sdlBuild);
|
|
351
359
|
const existingSdlArchive = sdlArchive();
|
|
352
360
|
if (!existingSdlArchive) {
|
|
353
361
|
/* Older trees configured SDL inside its source (`vendor/SDL/build`) and a
|
|
@@ -392,6 +400,7 @@ if (!existingSdlArchive) {
|
|
|
392
400
|
ensureTarballSource("freetype", FREETYPE_URL, `freetype-${FREETYPE_VERSION}`);
|
|
393
401
|
ensureTarballSource("harfbuzz", HARFBUZZ_URL, `harfbuzz-${HARFBUZZ_VERSION}`);
|
|
394
402
|
|
|
403
|
+
ensureDeploymentTarget("FreeType", freetypeBuild);
|
|
395
404
|
if (!existsSync(freetypeArchive() ?? "")) {
|
|
396
405
|
const cmake = configureCmake("FreeType", freetypeSrc, freetypeBuild, [
|
|
397
406
|
"-DCMAKE_BUILD_TYPE=Release",
|
|
@@ -410,6 +419,7 @@ if (!existsSync(freetypeArchive() ?? "")) {
|
|
|
410
419
|
console.log(`xbintsc: reusing existing ${freetypeArchive()}`);
|
|
411
420
|
}
|
|
412
421
|
|
|
422
|
+
ensureDeploymentTarget("HarfBuzz", harfbuzzBuild);
|
|
413
423
|
if (!existsSync(harfbuzzArchive() ?? "")) {
|
|
414
424
|
const cmake = configureCmake("HarfBuzz", harfbuzzSrc, harfbuzzBuild, [
|
|
415
425
|
"-DCMAKE_BUILD_TYPE=Release",
|
|
@@ -456,6 +466,7 @@ ensureTarballSource("glslang", GLSLANG_URL, `glslang-${GLSLANG_VERSION}`);
|
|
|
456
466
|
ensureTarballSource(join("glslang", "External", "spirv-headers"), SPIRV_HEADERS_URL,
|
|
457
467
|
`SPIRV-Headers-${SPIRV_HEADERS_VERSION}`);
|
|
458
468
|
|
|
469
|
+
ensureDeploymentTarget("glslang", glslangBuild);
|
|
459
470
|
if (!existsSync(glslangArchive() ?? "")) {
|
|
460
471
|
const cmake = configureCmake("glslang", glslangSrc, glslangBuild, [
|
|
461
472
|
"-DCMAKE_BUILD_TYPE=Release",
|
|
@@ -484,6 +495,7 @@ const metalBackend = process.platform === "darwin";
|
|
|
484
495
|
if (metalBackend) {
|
|
485
496
|
ensureTarballSource("spirv-cross", SPIRV_CROSS_URL, `SPIRV-Cross-${SPIRV_CROSS_VERSION}`);
|
|
486
497
|
|
|
498
|
+
ensureDeploymentTarget("SPIRV-Cross", spirvCrossBuild);
|
|
487
499
|
if (!existsSync(spirvCrossArchive("spirv-cross-msl") ?? "")) {
|
|
488
500
|
const cmake = configureCmake("SPIRV-Cross", spirvCrossSrc, spirvCrossBuild, [
|
|
489
501
|
"-DCMAKE_BUILD_TYPE=Release",
|
|
@@ -523,7 +535,7 @@ const sources = readdirSync(engineDir)
|
|
|
523
535
|
.sort();
|
|
524
536
|
|
|
525
537
|
const objects: string[] = [];
|
|
526
|
-
const cxxFlags =
|
|
538
|
+
const cxxFlags = cxxCompileFlags(toolchain.sdkRoot, includeFlags);
|
|
527
539
|
/* The engine is C++ and the MSVC C++ runtime must match the static C CRT that
|
|
528
540
|
* clang links by default, so let every engine object record `libcpmt` as a
|
|
529
541
|
* default library. The extension itself only contributes the DLL import library
|
package/scripts/build-media.ts
CHANGED
|
@@ -48,8 +48,11 @@ import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
|
48
48
|
import { dirname, join, resolve } from "node:path";
|
|
49
49
|
import { fileURLToPath } from "node:url";
|
|
50
50
|
import { platformSlug } from "../src/driver/paths.js";
|
|
51
|
+
import { applyMacosDeploymentTarget } from "../src/driver/platform-support.js";
|
|
51
52
|
import { isMsvcTarget, probeClang, realRunner } from "../src/driver/toolchain.js";
|
|
52
53
|
import { resolveToolchain } from "../src/driver/toolchain-provider.js";
|
|
54
|
+
import { downloadTarball } from "./fetch-tarball.js";
|
|
55
|
+
import { cxxCompileFlags } from "./gui-build-options.js";
|
|
53
56
|
|
|
54
57
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
55
58
|
const runtimeDir = join(root, "runtime");
|
|
@@ -66,6 +69,10 @@ const objDir = join(root, "build", "media-obj");
|
|
|
66
69
|
const outDir = join(runtimeDir, "lib", platformSlug());
|
|
67
70
|
const output = join(outDir, isWindows ? "media.lib" : "media.a");
|
|
68
71
|
|
|
72
|
+
/* FFmpeg and the player object must target the oldest supported macOS. Clang's
|
|
73
|
+
* Darwin driver and FFmpeg's configure both read the environment variable. */
|
|
74
|
+
applyMacosDeploymentTarget();
|
|
75
|
+
|
|
69
76
|
const FFMPEG_VERSION = process.env.FFMPEG_VERSION || "7.1";
|
|
70
77
|
const FFMPEG_URL = `https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz`;
|
|
71
78
|
|
|
@@ -161,27 +168,49 @@ function findArchiver(clangPath: string): string {
|
|
|
161
168
|
return archiver;
|
|
162
169
|
}
|
|
163
170
|
|
|
164
|
-
function
|
|
171
|
+
function driverToolchain(): ReturnType<typeof resolveToolchain> {
|
|
165
172
|
try {
|
|
166
|
-
return resolveToolchain()
|
|
173
|
+
return resolveToolchain();
|
|
167
174
|
} catch (error) {
|
|
168
175
|
fail(error instanceof Error ? error.message : String(error));
|
|
169
176
|
}
|
|
170
177
|
}
|
|
171
178
|
|
|
172
|
-
/**
|
|
179
|
+
/** Fetch and extract the FFmpeg release tarball under `vendor/ffmpeg`.
|
|
180
|
+
*
|
|
181
|
+
* The tarball is kept (`vendor/ffmpeg-<version>.tar.xz`) so CI can cache it by
|
|
182
|
+
* `FFMPEG_VERSION`, and `downloadTarball` retries the transient TLS failures the
|
|
183
|
+
* release host throws; the release marker re-extracts a tree of another release. */
|
|
173
184
|
function ensureFfmpegSource(): void {
|
|
174
|
-
if (existsSync(join(ffmpegSrc, "configure"))) return;
|
|
175
|
-
const tarball = join(vendorDir,
|
|
176
|
-
console.log(`xbintsc: fetching FFmpeg ${FFMPEG_VERSION} from ${FFMPEG_URL}`);
|
|
185
|
+
if (existsSync(join(ffmpegSrc, "configure")) && recordedRelease(ffmpegSrc) === FFMPEG_VERSION) return;
|
|
186
|
+
const tarball = join(vendorDir, `ffmpeg-${FFMPEG_VERSION}.tar.xz`);
|
|
177
187
|
mkdirSync(vendorDir, { recursive: true });
|
|
178
|
-
|
|
188
|
+
if (existsSync(tarball)) {
|
|
189
|
+
console.log(`xbintsc: extracting cached ${tarball}`);
|
|
190
|
+
} else {
|
|
191
|
+
try {
|
|
192
|
+
downloadTarball(tarball, FFMPEG_URL, `FFmpeg ${FFMPEG_VERSION}`);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
179
197
|
run("tar", ["-xf", tarball, "-C", vendorDir]);
|
|
180
198
|
const extracted = join(vendorDir, `ffmpeg-${FFMPEG_VERSION}`);
|
|
181
199
|
if (!existsSync(extracted)) fail(`expected ffmpeg-${FFMPEG_VERSION} after extracting`);
|
|
182
200
|
rmSync(ffmpegSrc, { recursive: true, force: true });
|
|
183
201
|
renameSync(extracted, ffmpegSrc);
|
|
184
|
-
|
|
202
|
+
writeFileSync(releaseStamp(ffmpegSrc), `${FFMPEG_VERSION}\n`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Marker recording the FFmpeg release a source tree or installed prefix holds. */
|
|
206
|
+
function releaseStamp(directory: string): string {
|
|
207
|
+
return join(directory, ".xbintsc-ffmpeg-version");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** The release recorded in `directory`, or "" when it predates the marker. */
|
|
211
|
+
function recordedRelease(directory: string): string {
|
|
212
|
+
const stamp = releaseStamp(directory);
|
|
213
|
+
return existsSync(stamp) ? readFileSync(stamp, "utf8").trim() : "";
|
|
185
214
|
}
|
|
186
215
|
|
|
187
216
|
function ffmpegStaticLibraries(): string[] | undefined {
|
|
@@ -194,6 +223,44 @@ function ffmpegInstalled(): boolean {
|
|
|
194
223
|
return ffmpegStaticLibraries() !== undefined && existsSync(join(ffmpegInstall, "include", "libavutil", "avutil.h"));
|
|
195
224
|
}
|
|
196
225
|
|
|
226
|
+
/** Marker recording the deployment target `dist` was built for (macOS). */
|
|
227
|
+
function deploymentStamp(): string {
|
|
228
|
+
return join(ffmpegInstall, ".xbintsc-deployment-target");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Drop a cached FFmpeg build tree that was configured for another macOS
|
|
233
|
+
* deployment target. `dist` is reused when it already holds the libraries, and
|
|
234
|
+
* FFmpeg's Makefile does not notice a changed `MACOSX_DEPLOYMENT_TARGET`; a
|
|
235
|
+
* tree from an earlier checkout would keep 15.5 objects in `media.a`. A tree
|
|
236
|
+
* without the marker predates this check and is rebuilt once.
|
|
237
|
+
*/
|
|
238
|
+
function ensureDeploymentTarget(): void {
|
|
239
|
+
if (process.platform !== "darwin") return;
|
|
240
|
+
const wanted = process.env.MACOSX_DEPLOYMENT_TARGET ?? "";
|
|
241
|
+
const stamp = deploymentStamp();
|
|
242
|
+
const recorded = existsSync(stamp) ? readFileSync(stamp, "utf8").trim() : "";
|
|
243
|
+
if (recorded === wanted) return;
|
|
244
|
+
if (existsSync(ffmpegBuild)) {
|
|
245
|
+
console.log(`xbintsc: FFmpeg was built for macOS '${recorded}'; rebuilding for '${wanted}'`);
|
|
246
|
+
rmSync(ffmpegBuild, { recursive: true, force: true });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Drop a cached FFmpeg build tree from another release: neither the Makefile nor
|
|
252
|
+
* `dist` is keyed by `FFMPEG_VERSION`, so reusing it would link the previous
|
|
253
|
+
* release's libraries. A `dist` without the marker predates this check and is
|
|
254
|
+
* rebuilt once.
|
|
255
|
+
*/
|
|
256
|
+
function ensureBuildRelease(): void {
|
|
257
|
+
if (!ffmpegInstalled()) return;
|
|
258
|
+
const recorded = recordedRelease(ffmpegInstall);
|
|
259
|
+
if (recorded === FFMPEG_VERSION) return;
|
|
260
|
+
console.log(`xbintsc: FFmpeg was built as '${recorded || "unknown"}'; rebuilding for '${FFMPEG_VERSION}'`);
|
|
261
|
+
rmSync(ffmpegBuild, { recursive: true, force: true });
|
|
262
|
+
}
|
|
263
|
+
|
|
197
264
|
/** Arguments shared by the POSIX and Windows FFmpeg configure runs. */
|
|
198
265
|
function ffmpegConfigureArgs(): string[] {
|
|
199
266
|
const prefix = isWindows ? ffmpegInstall.replace(/\\/g, "/") : ffmpegInstall;
|
|
@@ -443,7 +510,8 @@ ensureFfmpegSource();
|
|
|
443
510
|
/* One toolchain for the player and FFmpeg: the same clang the driver uses, its
|
|
444
511
|
* sibling clang++, and the matching llvm-ar. Mixing another C++ runtime or
|
|
445
512
|
* object format would break the final link. */
|
|
446
|
-
const
|
|
513
|
+
const toolchain = driverToolchain();
|
|
514
|
+
const clang = toolchain.clang;
|
|
447
515
|
const clangxx = findClangxx(clang);
|
|
448
516
|
const archiver = findArchiver(clang);
|
|
449
517
|
const windowsTools = isWindows
|
|
@@ -456,6 +524,8 @@ const windowsTools = isWindows
|
|
|
456
524
|
|
|
457
525
|
/* -- 2. minimal static FFmpeg --------------------------------------------- */
|
|
458
526
|
|
|
527
|
+
ensureDeploymentTarget();
|
|
528
|
+
ensureBuildRelease();
|
|
459
529
|
if (!ffmpegInstalled()) {
|
|
460
530
|
if (windowsTools) {
|
|
461
531
|
buildFfmpegWindows(windowsTools.shell, windowsTools.clangCl, windowsTools.msvcBin);
|
|
@@ -470,6 +540,12 @@ if (!ffmpegInstalled()) {
|
|
|
470
540
|
} else {
|
|
471
541
|
console.log(`xbintsc: reusing existing ${ffmpegInstall}/lib`);
|
|
472
542
|
}
|
|
543
|
+
/* Record the target and release for the next run, built or reused. */
|
|
544
|
+
if (process.platform === "darwin") {
|
|
545
|
+
mkdirSync(ffmpegInstall, { recursive: true });
|
|
546
|
+
writeFileSync(deploymentStamp(), process.env.MACOSX_DEPLOYMENT_TARGET ?? "");
|
|
547
|
+
}
|
|
548
|
+
writeFileSync(releaseStamp(ffmpegInstall), `${FFMPEG_VERSION}\n`);
|
|
473
549
|
|
|
474
550
|
/* -- 3. player object ------------------------------------------------------ */
|
|
475
551
|
|
|
@@ -482,7 +558,10 @@ mkdirSync(objDir, { recursive: true });
|
|
|
482
558
|
* references every entry point, so each member is extracted on demand. */
|
|
483
559
|
const playerSources = ["media.cpp", "decode_audio.cpp"];
|
|
484
560
|
const playerObjects: string[] = [];
|
|
485
|
-
const cxxFlags =
|
|
561
|
+
const cxxFlags = cxxCompileFlags(toolchain.sdkRoot, [
|
|
562
|
+
"-I", runtimeDir,
|
|
563
|
+
"-I", join(ffmpegInstall, "include"),
|
|
564
|
+
]);
|
|
486
565
|
/* The engine and the player are C++ with the static CRT (`libcpmt`), matching
|
|
487
566
|
* FFmpeg's clang-cl objects and the xbintsc runtime; see `scripts/build-gui.ts`. */
|
|
488
567
|
if (isWindows) cxxFlags.push("-Xclang", "--dependent-lib=libcpmt");
|
package/scripts/build-runtime.ts
CHANGED
|
@@ -26,8 +26,9 @@ import { basename, dirname, join, resolve } from "node:path";
|
|
|
26
26
|
import { fileURLToPath } from "node:url";
|
|
27
27
|
import { RUNTIME_SOURCES } from "../src/driver/compiler.js";
|
|
28
28
|
import { platformSlug } from "../src/driver/paths.js";
|
|
29
|
+
import { applyMacosDeploymentTarget } from "../src/driver/platform-support.js";
|
|
29
30
|
import { resolveToolchain } from "../src/driver/toolchain-provider.js";
|
|
30
|
-
import { RUNTIME_CFLAGS } from "../src/driver/toolchain.js";
|
|
31
|
+
import { RUNTIME_CFLAGS, sysrootFlags } from "../src/driver/toolchain.js";
|
|
31
32
|
import { nodeExtension } from "../src/extensions/node/index.js";
|
|
32
33
|
|
|
33
34
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -37,6 +38,10 @@ const objDir = join(root, "build", "runtime-obj");
|
|
|
37
38
|
const isWindows = process.platform === "win32";
|
|
38
39
|
const archiveSuffix = isWindows ? ".lib" : ".a";
|
|
39
40
|
|
|
41
|
+
/* Every archive targets the oldest supported macOS, not the build machine's
|
|
42
|
+
* version: a newer Xcode must not raise the deployment target of the objects. */
|
|
43
|
+
applyMacosDeploymentTarget();
|
|
44
|
+
|
|
40
45
|
// Use the same toolchain the driver will.
|
|
41
46
|
const toolchain = resolveToolchain();
|
|
42
47
|
const clang = toolchain.clang;
|
|
@@ -78,7 +83,7 @@ function compile(sources: readonly string[], extension: string): string[] {
|
|
|
78
83
|
const object = join(objDir, `${extension}_${index}_${basename(source, ".c")}.o`);
|
|
79
84
|
const result = spawnSync(
|
|
80
85
|
clang,
|
|
81
|
-
[...RUNTIME_CFLAGS, "-c", source, "-o", object, `-I${runtimeDir}`],
|
|
86
|
+
[...RUNTIME_CFLAGS, ...sysrootFlags(toolchain.sdkRoot), "-c", source, "-o", object, `-I${runtimeDir}`],
|
|
82
87
|
{ stdio: "inherit", env: childEnv },
|
|
83
88
|
);
|
|
84
89
|
if (result.status !== 0) {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Fetch a pinned release tarball for the vendored toolchain.
|
|
4
|
+
*
|
|
5
|
+
* `scripts/build-media.ts` (FFmpeg) and `scripts/build-gui.ts` (SDL3, FreeType,
|
|
6
|
+
* HarfBuzz, glslang, SPIRV-Cross) build from release tarballs downloaded at
|
|
7
|
+
* build time. A single `curl` is not reliable enough for that: hosted CI
|
|
8
|
+
* runners and some networks intermittently fail the TLS handshake with the
|
|
9
|
+
* release hosts — `curl: (35) SSL connect error` — and the next attempt
|
|
10
|
+
* usually succeeds. CI also caches the tarball by version, so with a retry here
|
|
11
|
+
* the download happens at most once per release rather than once per run.
|
|
12
|
+
*
|
|
13
|
+
* The bytes are written to `<destination>.part` and renamed only after curl
|
|
14
|
+
* reports success: an interrupted transfer can then never be mistaken for a
|
|
15
|
+
* complete tarball, neither by this run nor by a later one that restores the
|
|
16
|
+
* directory from `actions/cache`.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
|
+
import { renameSync, rmSync } from "node:fs";
|
|
21
|
+
|
|
22
|
+
/** curl exit codes of transfers that may succeed when repeated: name
|
|
23
|
+
* resolution (6), connect timeout (28), TLS handshake (35), empty reply (52),
|
|
24
|
+
* send failure (55) and connection reset (56). Everything else — a 404, a
|
|
25
|
+
* permission error — is reported immediately. */
|
|
26
|
+
const TRANSIENT_STATUSES = new Set([6, 28, 35, 52, 55, 56]);
|
|
27
|
+
|
|
28
|
+
export interface DownloadOptions {
|
|
29
|
+
/** Total attempts, including the first. */
|
|
30
|
+
attempts?: number;
|
|
31
|
+
/** Base backoff in milliseconds; attempt n waits `retryDelayMs * n`. */
|
|
32
|
+
retryDelayMs?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Block the single-threaded build long enough for a fresh TLS handshake. */
|
|
36
|
+
function pause(ms: number): void {
|
|
37
|
+
if (ms <= 0) return;
|
|
38
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Download `url` to `destination`, retrying the transient failures above.
|
|
43
|
+
* Throws when the transfer still fails, leaving no `.part` file behind.
|
|
44
|
+
*/
|
|
45
|
+
export function downloadTarball(
|
|
46
|
+
destination: string,
|
|
47
|
+
url: string,
|
|
48
|
+
label: string,
|
|
49
|
+
options: DownloadOptions = {},
|
|
50
|
+
): void {
|
|
51
|
+
const attempts = options.attempts ?? 6;
|
|
52
|
+
const retryDelayMs = options.retryDelayMs ?? 3_000;
|
|
53
|
+
const partial = `${destination}.part`;
|
|
54
|
+
rmSync(partial, { force: true });
|
|
55
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
56
|
+
const note = attempt === 1 ? "" : ` (attempt ${attempt}/${attempts})`;
|
|
57
|
+
console.log(`xbintsc: fetching ${label} from ${url}${note}`);
|
|
58
|
+
const { status } = spawnSync("curl", ["-sL", "--fail", "--connect-timeout", "30", "-o", partial, url], {
|
|
59
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
60
|
+
});
|
|
61
|
+
if (status === 0) {
|
|
62
|
+
renameSync(partial, destination);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (status === null || !TRANSIENT_STATUSES.has(status) || attempt >= attempts) {
|
|
66
|
+
rmSync(partial, { force: true });
|
|
67
|
+
throw new Error(`${label}: curl ${url} failed with status ${status ?? "?"}`);
|
|
68
|
+
}
|
|
69
|
+
pause(retryDelayMs * attempt);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache invalidation for the vendored GUI build trees.
|
|
3
|
+
*
|
|
4
|
+
* `build-gui.ts` reuses `vendor/*-build-lean` when the archive it produced is
|
|
5
|
+
* already there, which is what makes a second `npm run gui` fast. CMake records
|
|
6
|
+
* the compiler in its cache, but the macOS deployment target is only a cache
|
|
7
|
+
* entry: a tree configured by an earlier checkout (or before the baseline was
|
|
8
|
+
* pinned) keeps its old objects inside an archive that is supposed to target
|
|
9
|
+
* the oldest supported macOS. This drops such a tree once, so the next
|
|
10
|
+
* configure builds it for the current target.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
|
|
16
|
+
/** Remove `buildDir` when its CMake cache targets a different macOS version. */
|
|
17
|
+
export function ensureDeploymentTarget(name: string, buildDir: string): void {
|
|
18
|
+
if (process.platform !== "darwin") return;
|
|
19
|
+
const cache = join(buildDir, "CMakeCache.txt");
|
|
20
|
+
if (!existsSync(cache)) return;
|
|
21
|
+
const configured = /^CMAKE_OSX_DEPLOYMENT_TARGET:STRING=(.*)$/m.exec(readFileSync(cache, "utf8"))?.[1]?.trim();
|
|
22
|
+
const wanted = process.env.MACOSX_DEPLOYMENT_TARGET ?? "";
|
|
23
|
+
if ((configured ?? "") === wanted) return;
|
|
24
|
+
console.log(
|
|
25
|
+
`xbintsc: ${name} was built for macOS '${configured ?? ""}'; rebuilding for '${wanted}'`,
|
|
26
|
+
);
|
|
27
|
+
rmSync(buildDir, { recursive: true, force: true });
|
|
28
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Build options shared by the GUI and media archive builds.
|
|
3
3
|
*
|
|
4
4
|
* Kept apart from `build-gui.ts` so the orchestration stays under the
|
|
5
5
|
* repository's per-file line budget and the "what do we compile out?" policy is
|
|
6
6
|
* reviewable in one place.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { MACOS_MINIMUM_VERSION } from "../src/driver/platform-support.js";
|
|
10
|
+
import { sysrootFlags } from "../src/driver/toolchain.js";
|
|
11
|
+
|
|
9
12
|
/**
|
|
10
13
|
* CMake generator and ABI settings used for every vendored library. Ninja is
|
|
11
14
|
* selected on Windows because the Visual Studio generator imports the
|
|
@@ -22,6 +25,10 @@
|
|
|
22
25
|
* `cmake_minimum_required` below 3.15, which defaults the policy to OLD and
|
|
23
26
|
* silently ignores it — hence `CMAKE_POLICY_DEFAULT_CMP0091`.
|
|
24
27
|
*
|
|
28
|
+
* On macOS every vendored library targets the oldest supported deployment
|
|
29
|
+
* target (`MACOSX_DEPLOYMENT_TARGET`, default 11.0), so a newer SDK on the
|
|
30
|
+
* build machine cannot raise the floor of the archive.
|
|
31
|
+
*
|
|
25
32
|
* The tool paths are absolute and come from the same clang the driver resolves
|
|
26
33
|
* (on Windows, the LLVM bundled with Visual Studio when no newer one is on
|
|
27
34
|
* `PATH`), so every object merged into the archive shares one ABI and one
|
|
@@ -38,7 +45,11 @@ export function cmakeToolchainArgs(toolchain: {
|
|
|
38
45
|
`-DCMAKE_C_COMPILER=${toolchain.clang}`,
|
|
39
46
|
`-DCMAKE_CXX_COMPILER=${toolchain.clangxx}`,
|
|
40
47
|
];
|
|
41
|
-
|
|
48
|
+
const macos =
|
|
49
|
+
process.platform === "darwin"
|
|
50
|
+
? [`-DCMAKE_OSX_DEPLOYMENT_TARGET=${process.env.CMAKE_OSX_DEPLOYMENT_TARGET ?? MACOS_MINIMUM_VERSION}`]
|
|
51
|
+
: [];
|
|
52
|
+
if (!toolchain.isWindows) return [...compilers, ...macos];
|
|
42
53
|
return [
|
|
43
54
|
"-G", "Ninja",
|
|
44
55
|
"-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded",
|
|
@@ -52,6 +63,19 @@ export function cmakeToolchainArgs(toolchain: {
|
|
|
52
63
|
* never references (`--gc-sections`, `-dead_strip`, link.exe `/OPT:REF`). */
|
|
53
64
|
export const SECTION_FLAGS = ["-ffunction-sections", "-fdata-sections"] as const;
|
|
54
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Flags for the C++ translation units merged into the GUI and media archives.
|
|
68
|
+
*
|
|
69
|
+
* `sdkRoot` must be passed as `-isysroot`: an Apple clang invoked by absolute
|
|
70
|
+
* path never infers its sysroot, and macOS keeps every standard header —
|
|
71
|
+
* libc++'s `<string>` included — inside the SDK rather than in `/usr/include`
|
|
72
|
+
* or the toolchain. Without it the first translation unit fails with
|
|
73
|
+
* `'string' file not found`.
|
|
74
|
+
*/
|
|
75
|
+
export function cxxCompileFlags(sdkRoot: string | undefined, includeFlags: readonly string[]): string[] {
|
|
76
|
+
return ["-std=c++17", "-O2", "-Wall", "-Wextra", ...SECTION_FLAGS, ...sysrootFlags(sdkRoot), ...includeFlags];
|
|
77
|
+
}
|
|
78
|
+
|
|
55
79
|
/** The same flags as CMake cache entries. */
|
|
56
80
|
export const SECTION_CMAKE_FLAGS = [
|
|
57
81
|
`-DCMAKE_C_FLAGS=${SECTION_FLAGS.join(" ")}`,
|
|
@@ -101,6 +101,10 @@ if (process.platform !== "win32") chmodSync(stagedBinary, 0o755);
|
|
|
101
101
|
console.log(`xbintsc: packaged binary ${basename(binary)} (${statSync(binary).size} bytes)`);
|
|
102
102
|
|
|
103
103
|
// 2. The C runtime (sources fallback + prebuilt archives) next to the binary.
|
|
104
|
+
// The copy is bracketed with its own messages so a stalled packaging step can be
|
|
105
|
+
// attributed: this tree carries the freshly built gui/media archives, and a copy
|
|
106
|
+
// blocked on one of them looks exactly like a hang in the `tar` call below.
|
|
107
|
+
console.log("xbintsc: copying runtime/ into the staging tree");
|
|
104
108
|
cpSync(findRuntimeDir(), join(stage, "runtime"), { recursive: true });
|
|
105
109
|
console.log("xbintsc: packaged runtime/");
|
|
106
110
|
|
|
@@ -116,6 +120,10 @@ const extension = releaseArchiveExtension(hasZstd);
|
|
|
116
120
|
const archive = join(releaseRoot, `${archiveBase}${extension}`);
|
|
117
121
|
rmSync(archive, { force: true });
|
|
118
122
|
const tarArgs = ["-c", hasZstd ? "--zstd" : "-z", "-f", archive, "-C", stageRoot, base];
|
|
123
|
+
// Log the exact command before running it: `tar` prints nothing on success, so
|
|
124
|
+
// this line is what tells a stuck step apart from a stuck filesystem copy above,
|
|
125
|
+
// and it records which compression filter this runner chose (`--zstd` vs `-z`).
|
|
126
|
+
console.log(`xbintsc: running tar ${tarArgs.join(" ")}`);
|
|
119
127
|
const tar = spawnSync("tar", tarArgs, { stdio: "inherit" });
|
|
120
128
|
if (tar.error) fail(`failed to run tar: ${tar.error.message}`);
|
|
121
129
|
if (tar.status !== 0) fail(`tar exited with ${tar.status}`);
|
package/src/cli/hints.ts
CHANGED
|
@@ -36,10 +36,27 @@ const REQUIREMENT_HINT: DocumentationPointer = {
|
|
|
36
36
|
path: DOC_REQUIREMENTS,
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Hint for a clang failure: a missing or too-old clang has a specific answer.
|
|
41
|
+
*
|
|
42
|
+
* `platform` is a parameter so the macOS branch can be tested from any host.
|
|
43
|
+
*/
|
|
44
|
+
export function toolchainPointer(
|
|
45
|
+
message: string,
|
|
46
|
+
platform: NodeJS.Platform = process.platform,
|
|
47
|
+
): DocumentationPointer {
|
|
41
48
|
const usesTypedPointers = /defined with type '\[.*i8\]\*' but expected 'i8\*'/.test(message);
|
|
42
49
|
if (usesTypedPointers || /No C compiler found/i.test(message)) return REQUIREMENT_HINT;
|
|
50
|
+
/* On macOS a C standard header lives in the SDK, so "'<header>' file not
|
|
51
|
+
* found" means the driver never got a sysroot — the header itself is fine.
|
|
52
|
+
* The driver resolves the SDK with `xcrun` and passes `-isysroot`, which
|
|
53
|
+
* makes the selected Xcode the thing to check. */
|
|
54
|
+
if (platform === "darwin" && /fatal error: '.+' file not found/.test(message)) {
|
|
55
|
+
return {
|
|
56
|
+
text: "clang cannot see the macOS SDK headers; `xcrun --show-sdk-path` must resolve for the selected Xcode, or set SDKROOT yourself",
|
|
57
|
+
path: DOC_TROUBLESHOOTING,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
43
60
|
return {
|
|
44
61
|
text: "read the clang output above, then the toolchain section of the troubleshooting guide",
|
|
45
62
|
path: DOC_TROUBLESHOOTING,
|
package/src/cli/main.ts
CHANGED
|
@@ -20,9 +20,11 @@ import { formatDiagnostic, type Diagnostic } from "../diagnostics/diagnostic.js"
|
|
|
20
20
|
import { SourceFile } from "../diagnostics/source.js";
|
|
21
21
|
import { build, compileEntry, COMPILER_VERSION, type EmitKind, type PhaseTiming } from "../driver/compiler.js";
|
|
22
22
|
import { findRuntimeDir, platformSlug } from "../driver/paths.js";
|
|
23
|
+
import { supportFloor } from "../driver/platform-support.js";
|
|
23
24
|
import { findRuntimeLibrary, runtimeLibDir } from "../driver/runtime-lib.js";
|
|
24
25
|
import { resolveToolchain, type ResolvedToolchain } from "../driver/toolchain-provider.js";
|
|
25
26
|
import { MINIMUM_CLANG_MAJOR, probeClang, realRunner, ToolchainError } from "../driver/toolchain.js";
|
|
27
|
+
import { macosSdkRoot } from "../driver/macos-sdk.js";
|
|
26
28
|
import {
|
|
27
29
|
DOC_CLI,
|
|
28
30
|
DOC_TROUBLESHOOTING,
|
|
@@ -277,6 +279,15 @@ function doctor(io: CliIo): number {
|
|
|
277
279
|
io.stdout("runtime lib: unavailable\n");
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
io.stdout(`support : ${supportFloor()} (release artifacts target this floor)\n`);
|
|
283
|
+
|
|
284
|
+
if (process.platform === "darwin") {
|
|
285
|
+
/* macOS keeps the C headers in the SDK; without one, no header the runtime
|
|
286
|
+
* includes resolves. Report the sysroot the driver hands to clang. */
|
|
287
|
+
const sdk = toolchain?.sdkRoot ?? process.env.SDKROOT ?? macosSdkRoot(realRunner);
|
|
288
|
+
io.stdout(`sdk : ${sdk ?? "unresolved (xcrun --show-sdk-path failed)"}\n`);
|
|
289
|
+
}
|
|
290
|
+
|
|
280
291
|
try {
|
|
281
292
|
if (!toolchain) throw new Error("no toolchain");
|
|
282
293
|
const resource = resolveResourceCompiler(realRunner, toolchain.clang);
|
|
@@ -22,6 +22,8 @@ export interface AppArtifactRequest {
|
|
|
22
22
|
readonly app: AppConfig;
|
|
23
23
|
readonly icon: IconInfo | undefined;
|
|
24
24
|
readonly env: Record<string, string>;
|
|
25
|
+
/** macOS SDK for `-isysroot`; see `sysrootFlags`. */
|
|
26
|
+
readonly sdkRoot?: string;
|
|
25
27
|
readonly verbose: boolean | undefined;
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -46,11 +48,11 @@ export interface AppArtifacts {
|
|
|
46
48
|
* no equivalent.
|
|
47
49
|
*/
|
|
48
50
|
export function ensureAppArtifacts(request: AppArtifactRequest): AppArtifacts {
|
|
49
|
-
const { runner, clang, cacheDir, registry, app, icon, env, verbose } = request;
|
|
51
|
+
const { runner, clang, cacheDir, registry, app, icon, env, sdkRoot, verbose } = request;
|
|
50
52
|
const windowsSubsystem = process.platform === "win32" && registry.has("gui") && app.console !== true;
|
|
51
53
|
const linkerFlags = windowsSubsystem ? ["-Wl,/SUBSYSTEM:WINDOWS"] : [];
|
|
52
54
|
const entryObject = windowsSubsystem
|
|
53
|
-
? ensureWindowsEntryObject(runner, clang, cacheDir, env)
|
|
55
|
+
? ensureWindowsEntryObject(runner, clang, cacheDir, env, sdkRoot)
|
|
54
56
|
: undefined;
|
|
55
57
|
|
|
56
58
|
const iconObjects: string[] = [];
|
|
@@ -58,7 +60,7 @@ export function ensureAppArtifacts(request: AppArtifactRequest): AppArtifacts {
|
|
|
58
60
|
// program gets an (empty) icon object even with no icon configured.
|
|
59
61
|
if (icon !== undefined || registry.has("gui")) {
|
|
60
62
|
try {
|
|
61
|
-
iconObjects.push(ensureIconObject(runner, clang, cacheDir, icon ?? EMPTY_ICON, env));
|
|
63
|
+
iconObjects.push(ensureIconObject(runner, clang, cacheDir, icon ?? EMPTY_ICON, env, sdkRoot));
|
|
62
64
|
if (icon && process.platform === "win32") {
|
|
63
65
|
const resourceCompiler = resolveResourceCompiler(runner, clang);
|
|
64
66
|
if (resourceCompiler) {
|