quickjs-zig 1.0.2 → 1.0.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/README.md +33 -6
- package/build.mjs +30 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,9 +5,10 @@ A high-performance build system for **QuickJS**, powered by the **Zig** compiler
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
* **Zero Config Cross-Compilation**: Build for Windows, Linux, and macOS from any host (Intel or Apple Silicon).
|
|
8
|
-
* **Zig-Powered**: Uses **Zig 0.15.2**
|
|
8
|
+
* **Zig-Powered Optimization**: Uses **Zig 0.15.2** with LTO (Link Time Optimization) to produce small binaries.
|
|
9
9
|
* **Custom C Modules**: Easily inject and register your own C modules into the QuickJS engine.
|
|
10
10
|
* **Native Windows Support**: Includes a custom `exec` implementation for Windows, bypassing typical QuickJS POSIX limitations.
|
|
11
|
+
* **Platform-Specific Swapping**: Automatically replaces generic JS files with platform-specific ones (e.g., `index.mjs` → `index.darwin.mjs`) during build.
|
|
11
12
|
* **Clean Source Management**: Automatically patches and restores QuickJS source files to keep the core library pristine.
|
|
12
13
|
|
|
13
14
|
---
|
|
@@ -35,17 +36,40 @@ npm link
|
|
|
35
36
|
|
|
36
37
|
```
|
|
37
38
|
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Platform-Specific File Swapping
|
|
42
|
+
|
|
43
|
+
The build system supports platform-specific file resolution. This is useful when you need different JS logic for different operating systems while maintaining a single development entry point for IDE completion.
|
|
44
|
+
|
|
45
|
+
### How it works
|
|
46
|
+
|
|
47
|
+
1. **Generic file**: Create a base file (e.g., `index.mjs` or `dialogs.mjs`). This is your reference for IDE completion and IntelliSense.
|
|
48
|
+
2. **Specific files**: Create files with the platform suffix:
|
|
49
|
+
* `filename.win32.mjs`
|
|
50
|
+
* `filename.darwin.mjs`
|
|
51
|
+
* `filename.linux.mjs`
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
3. **Build Logic**:
|
|
55
|
+
* The `build/` folder is cleaned at the start of each execution.
|
|
56
|
+
* If a platform-specific version exists, the generic version is **excluded** from the build folder to avoid duplicates.
|
|
57
|
+
* The script automatically rewrites `import` statements in your code to point to the correct suffix during the build process.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
38
61
|
---
|
|
39
62
|
|
|
40
63
|
## Configuration
|
|
41
64
|
|
|
42
|
-
Configure your entry point and custom C modules in your project's `package.json`:
|
|
65
|
+
Configure your entry point, optimization, and custom C modules in your project's `package.json`:
|
|
43
66
|
|
|
44
67
|
```json
|
|
45
68
|
{
|
|
46
69
|
"name": "my-app",
|
|
47
70
|
"quickJs": {
|
|
48
71
|
"input": "app/index.mjs",
|
|
72
|
+
"optimization": true,
|
|
49
73
|
"modules": {
|
|
50
74
|
"my_module": "src/my_module.c"
|
|
51
75
|
}
|
|
@@ -55,8 +79,11 @@ Configure your entry point and custom C modules in your project's `package.json`
|
|
|
55
79
|
```
|
|
56
80
|
|
|
57
81
|
* **`input`**: The entry point of your JavaScript application (defaults to `app/index.mjs`).
|
|
82
|
+
* **`optimization`**: When `true`, enables **LTO**, aggressive inlining (`-O3`), and strips unused features like `eval` or `Promises` via `qjsc` flags.
|
|
58
83
|
* **`modules`**: A key-value map of custom C modules (Module Name -> C Source Path).
|
|
59
84
|
|
|
85
|
+
**Note**: The system always applies `-s` (strip symbols) regardless of the optimization flag to ensure no `.pdb` or debug tables are generated.
|
|
86
|
+
|
|
60
87
|
---
|
|
61
88
|
|
|
62
89
|
## Example Usage
|
|
@@ -130,9 +157,9 @@ The build system generates binaries for the following platforms in the `dist/` f
|
|
|
130
157
|
|
|
131
158
|
Zig is not just a language; it's a powerful C/C++ toolchain. It allows `quickjs-zig` to:
|
|
132
159
|
|
|
133
|
-
* Cross-compile to Windows (MinGW)
|
|
134
|
-
*
|
|
135
|
-
*
|
|
160
|
+
* **Cross-compile** to Windows (MinGW) or Linux from any host without installing complex toolchains.
|
|
161
|
+
* **Size matters**: By using `-flto` and `-O3`, Zig can discard unused parts of the engine, bringing the footprint down by nearly 95% compared to Node.js standalone binaries.
|
|
162
|
+
* **macOS LTO Support**: On Apple targets, we automatically force `-fuse-ld=lld` when optimized to ensure the LLVM Linker handles the bitcode correctly.
|
|
136
163
|
|
|
137
164
|
### Windows Patching
|
|
138
165
|
|
|
@@ -144,4 +171,4 @@ QuickJS is designed for POSIX systems. This tool automatically patches `quickjs-
|
|
|
144
171
|
|
|
145
172
|
MIT - Created by **eid-app**.
|
|
146
173
|
|
|
147
|
-
---
|
|
174
|
+
---
|
package/build.mjs
CHANGED
|
@@ -26,17 +26,23 @@ const userPackageJson = JSON.parse(readFileSync(USER_PKG_PATH, 'utf8'));
|
|
|
26
26
|
const customModules = userPackageJson.quickJs?.modules || {};
|
|
27
27
|
const APP_NAME = userPackageJson.name || 'app';
|
|
28
28
|
|
|
29
|
+
// Optimization flag from package.json
|
|
30
|
+
const IS_OPTIMIZED = userPackageJson.quickJs?.optimization === true;
|
|
31
|
+
|
|
29
32
|
// Input file from package.json or default to app/index.mjs
|
|
30
33
|
const INPUT_FILE_RELATIVE = userPackageJson.quickJs?.input || 'app/index.mjs';
|
|
31
34
|
|
|
32
35
|
/**
|
|
33
36
|
* Recursively scan and transform imports to platform-specific ones.
|
|
34
|
-
* Filters out files from other platforms and
|
|
37
|
+
* Filters out files from other platforms and ensures specific versions
|
|
38
|
+
* replace generic ones (like index.mjs) in the build folder.
|
|
35
39
|
*/
|
|
36
40
|
function processDirectory(currentDir, targetDir, targetPlat) {
|
|
37
41
|
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
|
|
38
42
|
|
|
39
|
-
readdirSync(currentDir)
|
|
43
|
+
const filesInSource = readdirSync(currentDir);
|
|
44
|
+
|
|
45
|
+
filesInSource.forEach(file => {
|
|
40
46
|
const fullPath = path.join(currentDir, file);
|
|
41
47
|
const destPath = path.join(targetDir, file);
|
|
42
48
|
|
|
@@ -56,17 +62,18 @@ function processDirectory(currentDir, targetDir, targetPlat) {
|
|
|
56
62
|
return;
|
|
57
63
|
}
|
|
58
64
|
|
|
59
|
-
// 2.
|
|
65
|
+
// 2. Logic for generic files (like index.mjs):
|
|
66
|
+
// If a specific version (index.darwin.mjs) exists, we skip the generic one.
|
|
60
67
|
if (!filePlat || !knownPlats.includes(filePlat)) {
|
|
61
68
|
const specFile = file.replace(/\.mjs$/, `.${targetPlat}.mjs`);
|
|
62
|
-
if (
|
|
69
|
+
if (filesInSource.includes(specFile)) {
|
|
63
70
|
return;
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
let content = readFileSync(fullPath, 'utf8');
|
|
68
75
|
|
|
69
|
-
// 3. Transform generic imports to platform-specific ones if they exist
|
|
76
|
+
// 3. Transform generic imports to platform-specific ones if they exist physically
|
|
70
77
|
content = content.replace(/(import\s+.+?\s+from\s+['"])(.+?)\.mjs(['"])/g, (match, before, importPath, after) => {
|
|
71
78
|
const platFile = `${importPath}.${targetPlat}.mjs`;
|
|
72
79
|
const platformFullPath = path.resolve(currentDir, platFile);
|
|
@@ -185,8 +192,11 @@ const targets = [
|
|
|
185
192
|
const stubPath = path.join(QUICKJS_DIR, 'repl_stub.c');
|
|
186
193
|
writeFileSync(stubPath, `const unsigned char qjsc_repl[] = {0}; const unsigned int qjsc_repl_size = 0;`);
|
|
187
194
|
|
|
195
|
+
// Feature optimization flags for qjsc
|
|
196
|
+
const qjscFlags = IS_OPTIMIZED ? '-fno-eval -fno-regexp -fno-proxy -fno-map -fno-typedarray -fno-promise' : '';
|
|
197
|
+
|
|
188
198
|
targets.forEach(t => {
|
|
189
|
-
console.log(`\n--- Compiling for: ${t.id}
|
|
199
|
+
console.log(`\n--- Compiling for: ${t.id} ---`);
|
|
190
200
|
|
|
191
201
|
// --- PLATFORM SPECIFIC BUILD RESOLUTION ---
|
|
192
202
|
const PLATFORM_BUILD_DIR = path.join(USER_CWD, 'build', t.id);
|
|
@@ -200,7 +210,15 @@ targets.forEach(t => {
|
|
|
200
210
|
|
|
201
211
|
const TARGET_INPUT_ABS = path.join(PLATFORM_BUILD_DIR, path.basename(INPUT_FILE_RELATIVE));
|
|
202
212
|
|
|
203
|
-
|
|
213
|
+
// Dynamic Optimization Flags
|
|
214
|
+
let optFlags = IS_OPTIMIZED ? '-O3 -flto' : '-O2';
|
|
215
|
+
|
|
216
|
+
// -fuse-ld=lld is mandatory for macOS LTO, but causes warnings on other platforms
|
|
217
|
+
if (IS_OPTIMIZED && t.plat === 'darwin') {
|
|
218
|
+
optFlags += ' -fuse-ld=lld';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const cmdBase = `${ZIG_PATH} cc -target ${t.id} -I${QUICKJS_DIR} ${optFlags} ${t.cflags} -Wno-ignored-attributes -DCONFIG_VERSION=\\"${VERSION}\\" ${t.libs} -s`;
|
|
204
222
|
|
|
205
223
|
try {
|
|
206
224
|
execSync(`${cmdBase} -o "${path.join(BIN_DIR, t.qjs)}" ${baseSources} ${stubPath} "${path.join(QUICKJS_DIR, 'qjs.c')}"`);
|
|
@@ -209,11 +227,11 @@ targets.forEach(t => {
|
|
|
209
227
|
|
|
210
228
|
const tempC = path.join(BIN_DIR, `${t.id}_app.c`);
|
|
211
229
|
|
|
212
|
-
// Use host qjsc to compile the platform-
|
|
213
|
-
execSync(`"${hostQjscPath}" -e -o "${tempC}" "${TARGET_INPUT_ABS}"`, { cwd: USER_CWD });
|
|
230
|
+
// Use host qjsc to compile the platform-resolved source
|
|
231
|
+
execSync(`"${hostQjscPath}" ${qjscFlags} -e -o "${tempC}" "${TARGET_INPUT_ABS}"`, { cwd: USER_CWD });
|
|
214
232
|
|
|
215
233
|
execSync(`${cmdBase} -o "${path.join(DIST_DIR, t.app)}" "${tempC}" ${baseSources} -I${QUICKJS_DIR}`);
|
|
216
|
-
console.log(`✅ Binary built: ${t.app}`);
|
|
234
|
+
console.log(`✅ Binary built${IS_OPTIMIZED ? ' and optimized' : ''}: ${t.app}`);
|
|
217
235
|
} catch (e) {
|
|
218
236
|
console.error(`❌ Compilation failed for ${t.id}`);
|
|
219
237
|
console.error(e.stderr?.toString() || e.message);
|
|
@@ -242,4 +260,5 @@ binFiles.forEach(file => {
|
|
|
242
260
|
});
|
|
243
261
|
if (existsSync(stubPath)) unlinkSync(stubPath);
|
|
244
262
|
|
|
245
|
-
console.log(
|
|
263
|
+
console.log(`🚀 Build process complete. (Optimization: ${IS_OPTIMIZED ? 'ON' : 'OFF'})`);
|
|
264
|
+
console.log("Platform sources kept in build/ subfolders.");
|
package/package.json
CHANGED