quickjs-zig 1.0.1 → 1.0.2
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/build.mjs +91 -21
- package/package.json +1 -1
package/build.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
|
-
import { writeFileSync, mkdirSync, unlinkSync, existsSync, readdirSync, cpSync, readFileSync, renameSync } from 'fs';
|
|
2
|
+
import { writeFileSync, mkdirSync, unlinkSync, existsSync, readdirSync, cpSync, readFileSync, renameSync, statSync, rmSync } from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import os from 'os';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
@@ -7,6 +7,13 @@ import { fileURLToPath } from 'url';
|
|
|
7
7
|
// --- PATH CONFIGURATION ---
|
|
8
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
const USER_CWD = process.cwd();
|
|
10
|
+
const PLATFORM = os.platform();
|
|
11
|
+
|
|
12
|
+
// Clean global build directory at the very beginning
|
|
13
|
+
const GLOBAL_BUILD_DIR = path.join(USER_CWD, 'build');
|
|
14
|
+
if (existsSync(GLOBAL_BUILD_DIR)) {
|
|
15
|
+
rmSync(GLOBAL_BUILD_DIR, { recursive: true });
|
|
16
|
+
}
|
|
10
17
|
|
|
11
18
|
// Load the user project's package.json
|
|
12
19
|
const USER_PKG_PATH = path.join(USER_CWD, 'package.json');
|
|
@@ -21,11 +28,62 @@ const APP_NAME = userPackageJson.name || 'app';
|
|
|
21
28
|
|
|
22
29
|
// Input file from package.json or default to app/index.mjs
|
|
23
30
|
const INPUT_FILE_RELATIVE = userPackageJson.quickJs?.input || 'app/index.mjs';
|
|
24
|
-
const INPUT_FILE_ABS = path.resolve(USER_CWD, INPUT_FILE_RELATIVE);
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Recursively scan and transform imports to platform-specific ones.
|
|
34
|
+
* Filters out files from other platforms and prevents duplicates.
|
|
35
|
+
*/
|
|
36
|
+
function processDirectory(currentDir, targetDir, targetPlat) {
|
|
37
|
+
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
|
|
38
|
+
|
|
39
|
+
readdirSync(currentDir).forEach(file => {
|
|
40
|
+
const fullPath = path.join(currentDir, file);
|
|
41
|
+
const destPath = path.join(targetDir, file);
|
|
42
|
+
|
|
43
|
+
if (statSync(fullPath).isDirectory()) {
|
|
44
|
+
return processDirectory(fullPath, destPath, targetPlat);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const isMjs = file.endsWith('.mjs') || file.endsWith('.js');
|
|
48
|
+
const knownPlats = ['win32', 'darwin', 'linux'];
|
|
49
|
+
|
|
50
|
+
if (isMjs) {
|
|
51
|
+
const parts = file.split('.');
|
|
52
|
+
const filePlat = parts.length > 2 ? parts[parts.length - 2] : null;
|
|
53
|
+
|
|
54
|
+
// 1. Skip files belonging to OTHER platforms
|
|
55
|
+
if (filePlat && knownPlats.includes(filePlat) && filePlat !== targetPlat) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 2. If it's a generic file, skip it if a platform-specific version exists in the same folder
|
|
60
|
+
if (!filePlat || !knownPlats.includes(filePlat)) {
|
|
61
|
+
const specFile = file.replace(/\.mjs$/, `.${targetPlat}.mjs`);
|
|
62
|
+
if (readdirSync(currentDir).includes(specFile)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let content = readFileSync(fullPath, 'utf8');
|
|
68
|
+
|
|
69
|
+
// 3. Transform generic imports to platform-specific ones if they exist
|
|
70
|
+
content = content.replace(/(import\s+.+?\s+from\s+['"])(.+?)\.mjs(['"])/g, (match, before, importPath, after) => {
|
|
71
|
+
const platFile = `${importPath}.${targetPlat}.mjs`;
|
|
72
|
+
const platformFullPath = path.resolve(currentDir, platFile);
|
|
73
|
+
|
|
74
|
+
if (existsSync(platformFullPath)) {
|
|
75
|
+
console.log(`✨ [${targetPlat}] Swapping import: ${importPath}.mjs -> ${platFile}`);
|
|
76
|
+
return `${before}${importPath}.${targetPlat}.mjs${after}`;
|
|
77
|
+
}
|
|
78
|
+
return match;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
writeFileSync(destPath, content);
|
|
82
|
+
} else {
|
|
83
|
+
// Copy assets and other files as is
|
|
84
|
+
cpSync(fullPath, destPath);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
29
87
|
}
|
|
30
88
|
|
|
31
89
|
const QUICKJS_DIR = path.resolve(__dirname, 'quickjs');
|
|
@@ -46,13 +104,11 @@ if (!existsSync(BIN_DIR)) mkdirSync(BIN_DIR, { recursive: true });
|
|
|
46
104
|
if (!existsSync(DIST_DIR)) mkdirSync(DIST_DIR, { recursive: true });
|
|
47
105
|
|
|
48
106
|
// Detect the host architecture to find the correct qjsc binary
|
|
49
|
-
const platform = os.platform();
|
|
50
107
|
const arch = os.arch();
|
|
51
108
|
let hostQjscName = '';
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
else if (
|
|
55
|
-
else if (platform === 'win32') hostQjscName = 'qjsc_win64.exe';
|
|
109
|
+
if (PLATFORM === 'darwin') hostQjscName = (arch === 'arm64') ? 'qjsc_mac_arm' : 'qjsc_mac_intel';
|
|
110
|
+
else if (PLATFORM === 'linux') hostQjscName = (arch === 'arm64' || arch === 'aarch64') ? 'qjsc_linux_arm' : 'qjsc_linux64';
|
|
111
|
+
else if (PLATFORM === 'win32') hostQjscName = 'qjsc_win64.exe';
|
|
56
112
|
|
|
57
113
|
const hostQjscPath = path.join(BIN_DIR, hostQjscName);
|
|
58
114
|
|
|
@@ -114,13 +170,13 @@ const baseSources = ['quickjs.c', 'libregexp.c', 'libunicode.c', 'cutils.c', 'qu
|
|
|
114
170
|
.join(' ');
|
|
115
171
|
|
|
116
172
|
const targets = [
|
|
117
|
-
{ id: 'x86_64-windows-gnu', qjs: 'qjs_win64.exe', qjsc: 'qjsc_win64.exe', app: `${APP_NAME}_win64.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE' },
|
|
118
|
-
{ id: 'x86-windows-gnu', qjs: 'qjs_win32.exe', qjsc: 'qjsc_win32.exe', app: `${APP_NAME}_win32.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE' },
|
|
119
|
-
{ id: 'x86_64-linux-gnu', qjs: 'qjs_linux64', qjsc: 'qjsc_linux64', app: `${APP_NAME}_linux64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
|
|
120
|
-
{ id: 'x86-linux-gnu',
|
|
121
|
-
{ id: 'aarch64-linux-gnu', qjs: 'qjs_linux_arm64', qjsc: 'qjsc_linux_arm64', app: `${APP_NAME}_linux_arm64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
|
|
122
|
-
{ id: 'aarch64-macos', qjs: 'qjs_mac_arm', qjsc: 'qjsc_mac_arm', app: `${APP_NAME}_mac_arm`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
|
|
123
|
-
{ id: 'x86_64-macos', qjs: 'qjs_mac_intel', qjsc: 'qjsc_mac_intel', app: `${APP_NAME}_mac_intel`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' }
|
|
173
|
+
{ id: 'x86_64-windows-gnu', qjs: 'qjs_win64.exe', qjsc: 'qjsc_win64.exe', app: `${APP_NAME}_win64.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE', plat: 'win32' },
|
|
174
|
+
{ id: 'x86-windows-gnu', qjs: 'qjs_win32.exe', qjsc: 'qjsc_win32.exe', app: `${APP_NAME}_win32.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE', plat: 'win32' },
|
|
175
|
+
{ id: 'x86_64-linux-gnu', qjs: 'qjs_linux64', qjsc: 'qjsc_linux64', app: `${APP_NAME}_linux64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'linux' },
|
|
176
|
+
{ id: 'x86-linux-gnu', qjs: 'qjs_linux32', qjsc: 'qjsc_linux32', app: `${APP_NAME}_linux32`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'linux' },
|
|
177
|
+
{ id: 'aarch64-linux-gnu', qjs: 'qjs_linux_arm64', qjsc: 'qjsc_linux_arm64', app: `${APP_NAME}_linux_arm64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'linux' },
|
|
178
|
+
{ id: 'aarch64-macos', qjs: 'qjs_mac_arm', qjsc: 'qjsc_mac_arm', app: `${APP_NAME}_mac_arm`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'darwin' },
|
|
179
|
+
{ id: 'x86_64-macos', qjs: 'qjs_mac_intel', qjsc: 'qjsc_mac_intel', app: `${APP_NAME}_mac_intel`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'darwin' }
|
|
124
180
|
];
|
|
125
181
|
|
|
126
182
|
// ==========================================================
|
|
@@ -130,7 +186,20 @@ const stubPath = path.join(QUICKJS_DIR, 'repl_stub.c');
|
|
|
130
186
|
writeFileSync(stubPath, `const unsigned char qjsc_repl[] = {0}; const unsigned int qjsc_repl_size = 0;`);
|
|
131
187
|
|
|
132
188
|
targets.forEach(t => {
|
|
133
|
-
console.log(`\n--- Compiling for: ${t.id} ---`);
|
|
189
|
+
console.log(`\n--- Compiling for: ${t.id} (Suffix: ${t.plat}) ---`);
|
|
190
|
+
|
|
191
|
+
// --- PLATFORM SPECIFIC BUILD RESOLUTION ---
|
|
192
|
+
const PLATFORM_BUILD_DIR = path.join(USER_CWD, 'build', t.id);
|
|
193
|
+
const inputBaseDir = path.dirname(path.resolve(USER_CWD, INPUT_FILE_RELATIVE));
|
|
194
|
+
|
|
195
|
+
if (existsSync(PLATFORM_BUILD_DIR)) {
|
|
196
|
+
rmSync(PLATFORM_BUILD_DIR, { recursive: true });
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
processDirectory(inputBaseDir, PLATFORM_BUILD_DIR, t.plat);
|
|
200
|
+
|
|
201
|
+
const TARGET_INPUT_ABS = path.join(PLATFORM_BUILD_DIR, path.basename(INPUT_FILE_RELATIVE));
|
|
202
|
+
|
|
134
203
|
const cmdBase = `${ZIG_PATH} cc -target ${t.id} -I${QUICKJS_DIR} -O2 ${t.cflags} -Wno-ignored-attributes -DCONFIG_VERSION=\\"${VERSION}\\" ${t.libs} -s`;
|
|
135
204
|
|
|
136
205
|
try {
|
|
@@ -139,9 +208,9 @@ targets.forEach(t => {
|
|
|
139
208
|
console.log(`✅ Build tools generated.`);
|
|
140
209
|
|
|
141
210
|
const tempC = path.join(BIN_DIR, `${t.id}_app.c`);
|
|
142
|
-
const relativeInput = path.relative(USER_CWD, INPUT_FILE_ABS);
|
|
143
211
|
|
|
144
|
-
|
|
212
|
+
// Use host qjsc to compile the platform-specific source
|
|
213
|
+
execSync(`"${hostQjscPath}" -e -o "${tempC}" "${TARGET_INPUT_ABS}"`, { cwd: USER_CWD });
|
|
145
214
|
|
|
146
215
|
execSync(`${cmdBase} -o "${path.join(DIST_DIR, t.app)}" "${tempC}" ${baseSources} -I${QUICKJS_DIR}`);
|
|
147
216
|
console.log(`✅ Binary built: ${t.app}`);
|
|
@@ -172,4 +241,5 @@ binFiles.forEach(file => {
|
|
|
172
241
|
}
|
|
173
242
|
});
|
|
174
243
|
if (existsSync(stubPath)) unlinkSync(stubPath);
|
|
175
|
-
|
|
244
|
+
|
|
245
|
+
console.log("🚀 Build process complete. Platform sources kept in build/ subfolders.");
|
package/package.json
CHANGED