@ugo-studio/jspp 0.3.1 → 0.3.3
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/dist/cli/args.js +22 -0
- package/dist/cli/compiler.js +53 -0
- package/dist/cli/index.js +43 -117
- package/dist/cli/pch.js +71 -0
- package/dist/cli/runner.js +23 -0
- package/dist/cli/spinner.js +27 -11
- package/dist/cli/transpiler.js +20 -0
- package/dist/cli/utils.js +25 -27
- package/dist/cli/wasm.js +70 -0
- package/dist/index.js +17 -6
- package/dist/{analysis → interpreter/analysis}/scope.js +34 -1
- package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +542 -3
- package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
- package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +2 -2
- package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +21 -9
- package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +3 -3
- package/dist/{core → interpreter/core}/codegen/expression-handlers.js +136 -82
- package/dist/{core → interpreter/core}/codegen/function-handlers.js +108 -61
- package/dist/{core → interpreter/core}/codegen/helpers.js +79 -11
- package/dist/interpreter/core/codegen/index.js +156 -0
- package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
- package/dist/{core → interpreter/core}/codegen/statement-handlers.js +39 -1
- package/package.json +6 -4
- package/scripts/precompile-headers.ts +71 -19
- package/scripts/setup-emsdk.ts +114 -0
- package/src/prelude/any_value.cpp +851 -599
- package/src/prelude/any_value.hpp +28 -30
- package/src/prelude/jspp.hpp +3 -1
- package/src/prelude/library/boolean.cpp +30 -0
- package/src/prelude/library/boolean.hpp +14 -0
- package/src/prelude/library/error.cpp +2 -2
- package/src/prelude/library/global.cpp +2 -0
- package/src/prelude/library/math.cpp +46 -43
- package/src/prelude/library/math.hpp +2 -0
- package/src/prelude/library/object.cpp +1 -1
- package/src/prelude/types.hpp +10 -9
- package/src/prelude/utils/access.hpp +2 -36
- package/src/prelude/utils/assignment_operators.hpp +136 -20
- package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
- package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
- package/src/prelude/utils/operators.hpp +123 -88
- package/src/prelude/utils/operators_native.hpp +360 -0
- package/src/prelude/utils/well_known_symbols.hpp +13 -13
- package/src/prelude/values/array.cpp +3 -3
- package/src/prelude/values/boolean.cpp +64 -0
- package/src/prelude/values/iterator.cpp +262 -210
- package/src/prelude/values/number.cpp +137 -92
- package/src/prelude/values/object.cpp +163 -122
- package/src/prelude/values/prototypes/boolean.hpp +24 -0
- package/src/prelude/values/prototypes/number.hpp +8 -1
- package/dist/cli/file-utils.js +0 -20
- package/dist/cli-utils/args.js +0 -59
- package/dist/cli-utils/colors.js +0 -9
- package/dist/cli-utils/file-utils.js +0 -20
- package/dist/cli-utils/spinner.js +0 -55
- package/dist/cli.js +0 -153
- package/dist/core/codegen/index.js +0 -88
- package/src/prelude/utils/operators_primitive.hpp +0 -337
- /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
- /package/dist/{ast → interpreter/ast}/types.js +0 -0
- /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
- /package/dist/{core → interpreter/core}/constants.js +0 -0
- /package/dist/{core → interpreter/core}/error.js +0 -0
- /package/dist/{core → interpreter/core}/parser.js +0 -0
- /package/dist/{core → interpreter/core}/traverser.js +0 -0
|
@@ -52,6 +52,21 @@ export function visitSourceFile(node, context) {
|
|
|
52
52
|
// Mark before further visits
|
|
53
53
|
this.markSymbolAsInitialized(funcName, contextForFunctions.globalScopeSymbols, contextForFunctions.localScopeSymbols);
|
|
54
54
|
this.markSymbolAsInitialized(funcName, globalScopeSymbols, localScopeSymbols);
|
|
55
|
+
// Check for @export comment
|
|
56
|
+
let exported = false;
|
|
57
|
+
if (this.isWasm) {
|
|
58
|
+
const fullText = sourceFile.text;
|
|
59
|
+
const commentRanges = ts.getLeadingCommentRanges(fullText, stmt.pos);
|
|
60
|
+
if (commentRanges) {
|
|
61
|
+
for (const range of commentRanges) {
|
|
62
|
+
const comment = fullText.substring(range.pos, range.end);
|
|
63
|
+
if (comment.includes("@export")) {
|
|
64
|
+
exported = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
55
70
|
// Update features in the symbol registry
|
|
56
71
|
const nativeName = this.generateUniqueName(`__${funcName}_native_`, hoistedSymbols);
|
|
57
72
|
const argumentKeywordIsUsed = this.isVariableUsedWithoutDeclaration("arguments", stmt.body);
|
|
@@ -72,9 +87,18 @@ export function visitSourceFile(node, context) {
|
|
|
72
87
|
noTypeSignature: true,
|
|
73
88
|
});
|
|
74
89
|
// Generate native lambda
|
|
75
|
-
if (this.isDeclarationCalledAsFunction(stmt, node)) {
|
|
90
|
+
if (this.isDeclarationCalledAsFunction(stmt, node) || exported) {
|
|
76
91
|
const nativeLambda = this.generateNativeLambda(lambdaComps);
|
|
77
92
|
code += `${this.indent()}auto ${nativeName} = ${nativeLambda};\n`;
|
|
93
|
+
if (exported) {
|
|
94
|
+
this.wasmExports.push({
|
|
95
|
+
jsName: funcName,
|
|
96
|
+
nativeName,
|
|
97
|
+
params: Array.from(stmt.parameters),
|
|
98
|
+
});
|
|
99
|
+
code +=
|
|
100
|
+
`${this.indent()}__wasm_export_ptr_${funcName} = ${nativeName};\n`;
|
|
101
|
+
}
|
|
78
102
|
}
|
|
79
103
|
// Generate AnyValue wrapped lamda
|
|
80
104
|
if (this.isDeclarationUsedAsValue(stmt, node) ||
|
|
@@ -799,6 +823,20 @@ export function visitReturnStatement(node, context) {
|
|
|
799
823
|
!typeInfo.isBuiltin) {
|
|
800
824
|
finalExpr = this.getDerefCode(exprText, this.getJsVarName(expr), context, typeInfo);
|
|
801
825
|
}
|
|
826
|
+
const exprReturnType = this.typeAnalyzer.inferNodeReturnType(expr);
|
|
827
|
+
if (exprReturnType === "number" &&
|
|
828
|
+
context.isInsideNativeLambda &&
|
|
829
|
+
context.isInsideFunction) {
|
|
830
|
+
const funcDecl = this
|
|
831
|
+
.findEnclosingFunctionDeclarationFromReturnStatement(expr);
|
|
832
|
+
if (funcDecl) {
|
|
833
|
+
const funcReturnType = this.typeAnalyzer
|
|
834
|
+
.inferFunctionReturnType(funcDecl);
|
|
835
|
+
if (funcReturnType === "number") {
|
|
836
|
+
finalExpr = `${finalExpr}.as_double()`;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
802
840
|
}
|
|
803
841
|
return `${this.indent()}${returnCmd} ${finalExpr};\n`;
|
|
804
842
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ugo-studio/jspp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "A modern transpiler that converts JavaScript code into high-performance, standard C++23.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
"scripts"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"postinstall": "bun run scripts/setup-compiler.ts && bun run scripts/precompile-headers.ts",
|
|
17
|
+
"postinstall": "bun run scripts/setup-compiler.ts && bun run scripts/setup-emsdk.ts && bun run scripts/precompile-headers.ts --mode debug",
|
|
18
18
|
"dev": "bun run src/cli/index.ts",
|
|
19
19
|
"typecheck": "tsc --noEmit",
|
|
20
|
-
"precompile": "bun run scripts/precompile-headers.ts",
|
|
21
20
|
"test": "bun test",
|
|
22
21
|
"build": "tsc",
|
|
23
22
|
"prepack": "bun run build",
|
|
24
|
-
"publish:npm": "npm publish --access=public"
|
|
23
|
+
"publish:npm": "npm publish --access=public",
|
|
24
|
+
"script:setup-compiler": "bun run scripts/setup-compiler.ts",
|
|
25
|
+
"script:setup-emsdk": "bun run scripts/setup-emsdk.ts",
|
|
26
|
+
"script:precompile-headers": "bun run scripts/precompile-headers.ts"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
29
|
"@types/bun": "latest"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
2
|
import fs from "fs/promises";
|
|
3
3
|
import path from "path";
|
|
4
4
|
|
|
@@ -87,10 +87,23 @@ const MODES = [
|
|
|
87
87
|
{
|
|
88
88
|
name: "debug",
|
|
89
89
|
flags: ["-Og"],
|
|
90
|
+
linkerFlags: [],
|
|
91
|
+
compiler: "g++",
|
|
92
|
+
archiver: "ar",
|
|
90
93
|
},
|
|
91
94
|
{
|
|
92
95
|
name: "release",
|
|
93
96
|
flags: ["-O3", "-DNDEBUG"],
|
|
97
|
+
linkerFlags: [],
|
|
98
|
+
compiler: "g++",
|
|
99
|
+
archiver: "ar",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "wasm",
|
|
103
|
+
flags: ["-O3", "-DNDEBUG"],
|
|
104
|
+
linkerFlags: ["-sASYNCIFY", "-sALLOW_MEMORY_GROWTH=1"],
|
|
105
|
+
compiler: "em++",
|
|
106
|
+
archiver: "emar",
|
|
94
107
|
},
|
|
95
108
|
];
|
|
96
109
|
|
|
@@ -99,6 +112,14 @@ if (process.platform === "win32") {
|
|
|
99
112
|
MODES[1].flags.push("-Wa,-mbig-obj");
|
|
100
113
|
}
|
|
101
114
|
|
|
115
|
+
const pkgDir = path.dirname(import.meta.dirname);
|
|
116
|
+
const emsdkEnv = {
|
|
117
|
+
...process.env,
|
|
118
|
+
PATH: `${path.join(pkgDir, ".emsdk")}${path.delimiter}${
|
|
119
|
+
path.join(pkgDir, ".emsdk", "upstream", "emscripten")
|
|
120
|
+
}${path.delimiter}${process.env.PATH}`,
|
|
121
|
+
};
|
|
122
|
+
|
|
102
123
|
async function getLatestMtime(
|
|
103
124
|
dirPath: string,
|
|
104
125
|
filter?: (name: string) => boolean,
|
|
@@ -134,17 +155,31 @@ async function findCppFiles(dir: string): Promise<string[]> {
|
|
|
134
155
|
|
|
135
156
|
async function runCommand(cmd: string, args: string[]): Promise<boolean> {
|
|
136
157
|
return new Promise((resolve) => {
|
|
137
|
-
const proc = spawn(cmd, args, {
|
|
158
|
+
const proc = spawn(cmd, args, {
|
|
159
|
+
stdio: "inherit",
|
|
160
|
+
shell: process.platform === "win32",
|
|
161
|
+
env: emsdkEnv,
|
|
162
|
+
});
|
|
138
163
|
proc.on("close", (code) => resolve(code === 0));
|
|
139
164
|
});
|
|
140
165
|
}
|
|
141
166
|
|
|
142
167
|
async function precompileHeaders() {
|
|
143
|
-
console.log(
|
|
144
|
-
`${COLORS.bold}${COLORS.cyan}JSPP: Precompiling headers and runtime...${COLORS.reset}\n`,
|
|
145
|
-
);
|
|
146
|
-
|
|
147
168
|
const force = process.argv.includes("--force");
|
|
169
|
+
const jsppCliIsParent = process.argv.includes("--jspp-cli-is-parent");
|
|
170
|
+
const silent = process.argv.includes("--silent");
|
|
171
|
+
|
|
172
|
+
const modeArgIdx = process.argv.indexOf("--mode");
|
|
173
|
+
const targetMode = modeArgIdx !== -1
|
|
174
|
+
? process.argv[modeArgIdx + 1]
|
|
175
|
+
: undefined;
|
|
176
|
+
|
|
177
|
+
if (!jsppCliIsParent && !silent) {
|
|
178
|
+
console.log(
|
|
179
|
+
`${COLORS.bold}${COLORS.cyan}JSPP: Precompiling headers and runtime...${COLORS.reset}\n`,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
148
183
|
try {
|
|
149
184
|
await fs.mkdir(PRECOMPILED_HEADER_BASE_DIR, { recursive: true });
|
|
150
185
|
|
|
@@ -154,13 +189,15 @@ async function precompileHeaders() {
|
|
|
154
189
|
);
|
|
155
190
|
|
|
156
191
|
for (const mode of MODES) {
|
|
192
|
+
if (targetMode && mode.name !== targetMode) continue;
|
|
193
|
+
|
|
157
194
|
const modeDir = path.join(PRECOMPILED_HEADER_BASE_DIR, mode.name);
|
|
158
195
|
const headerPath = path.join(modeDir, "jspp.hpp");
|
|
159
196
|
const gchPath = path.join(modeDir, "jspp.hpp.gch");
|
|
160
197
|
|
|
161
198
|
const modeLabel = `[${mode.name.toUpperCase()}]`;
|
|
162
199
|
const spinner = new Spinner(`${modeLabel} Checking headers...`);
|
|
163
|
-
spinner.start();
|
|
200
|
+
if (!silent) spinner.start();
|
|
164
201
|
|
|
165
202
|
await fs.mkdir(modeDir, { recursive: true });
|
|
166
203
|
|
|
@@ -179,6 +216,7 @@ async function precompileHeaders() {
|
|
|
179
216
|
}
|
|
180
217
|
|
|
181
218
|
if (shouldBuildGch) {
|
|
219
|
+
if (silent) spinner.start();
|
|
182
220
|
spinner.update(`${modeLabel} Compiling header...`);
|
|
183
221
|
await fs.copyFile(
|
|
184
222
|
path.join(PRELUDE_DIR, "jspp.hpp"),
|
|
@@ -186,7 +224,7 @@ async function precompileHeaders() {
|
|
|
186
224
|
);
|
|
187
225
|
|
|
188
226
|
const tempGchPath = `${gchPath}.tmp`;
|
|
189
|
-
const success = await runCommand(
|
|
227
|
+
const success = await runCommand(mode.compiler, [
|
|
190
228
|
"-x",
|
|
191
229
|
"c++-header",
|
|
192
230
|
"-std=c++23",
|
|
@@ -209,7 +247,9 @@ async function precompileHeaders() {
|
|
|
209
247
|
gchRebuilt = true;
|
|
210
248
|
spinner.succeed(`${modeLabel} PCH Success.`);
|
|
211
249
|
} else {
|
|
212
|
-
|
|
250
|
+
if (!silent) {
|
|
251
|
+
spinner.succeed(`${modeLabel} Headers are up-to-date.`);
|
|
252
|
+
}
|
|
213
253
|
}
|
|
214
254
|
|
|
215
255
|
// --- Incremental Compilation of .cpp files ---
|
|
@@ -217,12 +257,16 @@ async function precompileHeaders() {
|
|
|
217
257
|
const objFiles: string[] = [];
|
|
218
258
|
let anyObjRebuilt = false;
|
|
219
259
|
|
|
220
|
-
|
|
260
|
+
// We need gchPath to exist for next check, if it doesn't we probably have a problem or it's a first run
|
|
261
|
+
let gchMtime = 0;
|
|
262
|
+
try {
|
|
263
|
+
gchMtime = (await fs.stat(gchPath)).mtimeMs;
|
|
264
|
+
} catch (e) {}
|
|
221
265
|
|
|
222
266
|
const libSpinner = new Spinner(
|
|
223
267
|
`${modeLabel} Checking runtime library...`,
|
|
224
268
|
);
|
|
225
|
-
libSpinner.start();
|
|
269
|
+
if (!silent) libSpinner.start();
|
|
226
270
|
|
|
227
271
|
for (let idx = 0; idx < cppFiles.length; idx++) {
|
|
228
272
|
const cppFile = cppFiles[idx];
|
|
@@ -251,12 +295,13 @@ async function precompileHeaders() {
|
|
|
251
295
|
}
|
|
252
296
|
|
|
253
297
|
if (shouldCompile) {
|
|
298
|
+
if (silent && !libSpinner["interval"]) libSpinner.start();
|
|
254
299
|
libSpinner.update(
|
|
255
300
|
`${modeLabel} Compiling ${relativePath} ${COLORS.dim}[${
|
|
256
301
|
idx + 1
|
|
257
302
|
}/${cppFiles.length}]${COLORS.reset}`,
|
|
258
303
|
);
|
|
259
|
-
const success = await runCommand(
|
|
304
|
+
const success = await runCommand(mode.compiler, [
|
|
260
305
|
"-c",
|
|
261
306
|
"-std=c++23",
|
|
262
307
|
...mode.flags,
|
|
@@ -290,10 +335,11 @@ async function precompileHeaders() {
|
|
|
290
335
|
}
|
|
291
336
|
|
|
292
337
|
if (shouldArchive) {
|
|
338
|
+
if (silent && !libSpinner["interval"]) libSpinner.start();
|
|
293
339
|
libSpinner.update(`${modeLabel} Updating runtime library...`);
|
|
294
340
|
const tempLibPath = `${libPath}.tmp`;
|
|
295
341
|
|
|
296
|
-
const success = await runCommand(
|
|
342
|
+
const success = await runCommand(mode.archiver, [
|
|
297
343
|
"rcs",
|
|
298
344
|
tempLibPath,
|
|
299
345
|
...objFiles,
|
|
@@ -309,14 +355,20 @@ async function precompileHeaders() {
|
|
|
309
355
|
await fs.rename(tempLibPath, libPath);
|
|
310
356
|
libSpinner.succeed(`${modeLabel} Runtime Library Success.`);
|
|
311
357
|
} else {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
358
|
+
if (!silent) {
|
|
359
|
+
libSpinner.succeed(
|
|
360
|
+
`${modeLabel} Runtime library is up-to-date.`,
|
|
361
|
+
);
|
|
362
|
+
} else {
|
|
363
|
+
libSpinner.stop();
|
|
364
|
+
}
|
|
315
365
|
}
|
|
316
366
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
367
|
+
if (!jsppCliIsParent && !silent) {
|
|
368
|
+
console.log(
|
|
369
|
+
`\n${COLORS.bold}${COLORS.green}JSPP: Environment ready.${COLORS.reset}\n`,
|
|
370
|
+
);
|
|
371
|
+
}
|
|
320
372
|
} catch (error: any) {
|
|
321
373
|
console.error(`${COLORS.red}Error: ${error.message}${COLORS.reset}`);
|
|
322
374
|
process.exit(1);
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { platform } from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
const COLORS = {
|
|
7
|
+
reset: "\x1b[0m",
|
|
8
|
+
green: "\x1b[32m",
|
|
9
|
+
yellow: "\x1b[33m",
|
|
10
|
+
red: "\x1b[31m",
|
|
11
|
+
cyan: "\x1b[36m",
|
|
12
|
+
bold: "\x1b[1m",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const EMSDK_DIR = path.resolve(process.cwd(), ".emsdk");
|
|
16
|
+
const isWin = platform() === "win32";
|
|
17
|
+
const emsdkCmd = isWin ? "emsdk.bat" : "./emsdk";
|
|
18
|
+
|
|
19
|
+
function checkEmcc(): boolean {
|
|
20
|
+
try {
|
|
21
|
+
const result = spawnSync("emcc", ["--version"], { encoding: "utf8" });
|
|
22
|
+
return result.status === 0;
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function runCommand(
|
|
29
|
+
cmd: string,
|
|
30
|
+
args: string[],
|
|
31
|
+
cwd: string = process.cwd(),
|
|
32
|
+
): boolean {
|
|
33
|
+
console.log(`${COLORS.cyan}> ${cmd} ${args.join(" ")}${COLORS.reset}`);
|
|
34
|
+
const result = spawnSync(cmd, args, {
|
|
35
|
+
cwd,
|
|
36
|
+
stdio: "inherit",
|
|
37
|
+
shell: isWin,
|
|
38
|
+
});
|
|
39
|
+
return result.status === 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function setup() {
|
|
43
|
+
console.log(
|
|
44
|
+
`${COLORS.bold}${COLORS.cyan}JSPP: Setting up Emscripten SDK for Wasm support...${COLORS.reset}`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (checkEmcc()) {
|
|
48
|
+
console.log(
|
|
49
|
+
`${COLORS.green}✔ Emscripten (emcc) found in PATH.${COLORS.reset}`,
|
|
50
|
+
);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (fs.existsSync(path.join(EMSDK_DIR, emsdkCmd))) {
|
|
55
|
+
console.log(
|
|
56
|
+
`${COLORS.yellow}ℹ Local EMSDK found in .emsdk directory.${COLORS.reset}`,
|
|
57
|
+
);
|
|
58
|
+
} else {
|
|
59
|
+
console.log(
|
|
60
|
+
`${COLORS.yellow}ℹ EMSDK not found. Cloning from GitHub...${COLORS.reset}`,
|
|
61
|
+
);
|
|
62
|
+
if (
|
|
63
|
+
!runCommand("git", [
|
|
64
|
+
"clone",
|
|
65
|
+
"https://github.com/emscripten-core/emsdk.git",
|
|
66
|
+
".emsdk",
|
|
67
|
+
])
|
|
68
|
+
) {
|
|
69
|
+
console.error(
|
|
70
|
+
`${COLORS.red}Error: Failed to clone EMSDK repository. Make sure 'git' is installed.${COLORS.reset}`,
|
|
71
|
+
);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(
|
|
77
|
+
`${COLORS.cyan}Installing latest Emscripten SDK...${COLORS.reset}`,
|
|
78
|
+
);
|
|
79
|
+
if (!runCommand(emsdkCmd, ["install", "latest"], EMSDK_DIR)) {
|
|
80
|
+
console.error(
|
|
81
|
+
`${COLORS.red}Error: Failed to install Emscripten SDK.${COLORS.reset}`,
|
|
82
|
+
);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.log(
|
|
87
|
+
`${COLORS.cyan}Activating latest Emscripten SDK...${COLORS.reset}`,
|
|
88
|
+
);
|
|
89
|
+
if (
|
|
90
|
+
!runCommand(emsdkCmd, ["activate", "latest", "--permanent"], EMSDK_DIR)
|
|
91
|
+
) {
|
|
92
|
+
console.error(
|
|
93
|
+
`${COLORS.red}Error: Failed to activate Emscripten SDK.${COLORS.reset}`,
|
|
94
|
+
);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log(
|
|
99
|
+
`\n${COLORS.green}✔ Emscripten SDK setup complete.${COLORS.reset}`,
|
|
100
|
+
);
|
|
101
|
+
console.log(
|
|
102
|
+
`${COLORS.yellow}Note: To use emcc in your current terminal, you may need to run:${COLORS.reset}`,
|
|
103
|
+
);
|
|
104
|
+
if (isWin) {
|
|
105
|
+
console.log(`${COLORS.bold} .emsdk\\emsdk_env.bat${COLORS.reset}`);
|
|
106
|
+
} else {
|
|
107
|
+
console.log(
|
|
108
|
+
`${COLORS.bold} source .emsdk/emsdk_env.sh${COLORS.reset}`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
console.log("");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setup();
|