Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/tools/compiler.mjs
6162 views
1
#!/usr/bin/env node
2
/**
3
* @license
4
* Copyright 2010 The Emscripten Authors
5
* SPDX-License-Identifier: MIT
6
*/
7
8
// JavaScript compiler, main entry point
9
10
import assert from 'node:assert';
11
import {parseArgs} from 'node:util';
12
import {
13
applySettings,
14
loadDefaultSettings,
15
printErr,
16
readFile,
17
timer,
18
} from '../src/utility.mjs';
19
20
timer.start('startup')
21
22
loadDefaultSettings();
23
24
const options = {
25
help: {type: 'boolean', short: 'h'},
26
'symbols-only': {type: 'boolean'},
27
output: {type: 'string', short: 'o'},
28
};
29
const {values, positionals} = parseArgs({options, allowPositionals: true});
30
31
if (values.help) {
32
console.log(`\
33
Main entry point for JS compiler
34
35
If no -o file is specified then the generated code is written to stdout.
36
37
Usage: compiler.mjs <settings.json> [-o out.js] [--symbols-only]`);
38
process.exit(0);
39
}
40
41
timer.start('read settings')
42
43
// Load settings from JSON passed on the command line
44
let settingsFile = positionals[0];
45
assert(settingsFile, 'settings file not specified');
46
if (settingsFile == '-') {
47
// Read settings json from stdin (FD 0)
48
settingsFile = 0;
49
}
50
const userSettings = JSON.parse(readFile(settingsFile));
51
applySettings(userSettings);
52
53
timer.stop('read settings')
54
55
export const symbolsOnly = values['symbols-only'];
56
57
// TODO(sbc): Remove EMCC_BUILD_DIR at some point. It used to be required
58
// back when ran the JS compiler with overridden CWD.
59
process.env['EMCC_BUILD_DIR'] = process.cwd();
60
61
// In case compiler.mjs is run directly (as in gen_sig_info)
62
// ALL_INCOMING_MODULE_JS_API might not be populated yet.
63
if (!ALL_INCOMING_MODULE_JS_API.length) {
64
ALL_INCOMING_MODULE_JS_API = INCOMING_MODULE_JS_API;
65
}
66
67
EXPORTED_FUNCTIONS = new Set(EXPORTED_FUNCTIONS);
68
WASM_EXPORTS = new Set(WASM_EXPORTS);
69
SIDE_MODULE_EXPORTS = new Set(SIDE_MODULE_EXPORTS);
70
INCOMING_MODULE_JS_API = new Set(INCOMING_MODULE_JS_API);
71
ALL_INCOMING_MODULE_JS_API = new Set(ALL_INCOMING_MODULE_JS_API);
72
EXPORTED_RUNTIME_METHODS = new Set(EXPORTED_RUNTIME_METHODS);
73
WEAK_IMPORTS = new Set(WEAK_IMPORTS);
74
if (symbolsOnly) {
75
INCLUDE_FULL_LIBRARY = 1;
76
}
77
78
// Side modules are pure wasm and have no JS
79
assert(
80
!SIDE_MODULE || (ASYNCIFY && symbolsOnly),
81
'JS compiler should only run on side modules if asyncify is used.',
82
);
83
84
// Load compiler code
85
86
timer.start('dynamic imports')
87
88
// We can't use static import statements here because several of these
89
// file depend on having the settings defined in the global scope (which
90
// we do dynamically above.
91
await import('../src/modules.mjs');
92
await import('../src/parseTools.mjs');
93
if (!STRICT) {
94
await import('../src/parseTools_legacy.mjs');
95
}
96
const jsifier = await import('../src/jsifier.mjs');
97
98
timer.stop('dynamic imports')
99
100
timer.stop('startup')
101
102
// ===============================
103
// Main
104
// ===============================
105
106
try {
107
timer.start('runJSify')
108
await jsifier.runJSify(values.output, symbolsOnly);
109
timer.stop('runJSify')
110
} catch (err) {
111
if (err.toString().includes('Aborting compilation due to previous errors')) {
112
// Compiler failed on user error, don't print the stacktrace in this case.
113
printErr(err);
114
} else {
115
// Compiler failed on internal compiler error!
116
printErr('Internal compiler error JS compiler');
117
printErr('Please create a bug report at https://github.com/emscripten-core/emscripten/issues/');
118
printErr(
119
'with a log of the build and the input files used to run. Exception message: "' +
120
(err.stack || err),
121
);
122
}
123
124
// Work around a node.js bug where stdout buffer is not flushed at process exit:
125
// Instead of process.exit() directly, wait for stdout flush event.
126
// See https://github.com/joyent/node/issues/1669 and https://github.com/emscripten-core/emscripten/issues/2582
127
// Workaround is based on https://github.com/RReverser/acorn/commit/50ab143cecc9ed71a2d66f78b4aec3bb2e9844f6
128
process.stdout.once('drain', () => process.exit(1));
129
// Make sure to print something to force the drain event to occur, in case the
130
// stdout buffer was empty.
131
console.log(' ');
132
// Work around another node bug where sometimes 'drain' is never fired - make
133
// another effort to emit the exit status, after a significant delay (if node
134
// hasn't fired drain by then, give up)
135
setTimeout(() => process.exit(1), 500);
136
}
137
138