koffi 2.16.1 → 3.0.0-alpha.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.
Files changed (84) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +8 -8
  3. package/build/koffi/darwin_arm64/koffi.node +0 -0
  4. package/build/koffi/darwin_x64/koffi.node +0 -0
  5. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  6. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  7. package/build/koffi/freebsd_x64/koffi.node +0 -0
  8. package/build/koffi/linux_arm64/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_x64/koffi.node +0 -0
  11. package/build/koffi/musl_arm64/koffi.node +0 -0
  12. package/build/koffi/musl_x64/koffi.node +0 -0
  13. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  14. package/build/koffi/openbsd_x64/koffi.node +0 -0
  15. package/build/koffi/win32_ia32/koffi.node +0 -0
  16. package/build/koffi/win32_x64/koffi.node +0 -0
  17. package/doc/benchmarks.md +33 -33
  18. package/doc/benchmarks.xlsx +0 -0
  19. package/doc/contribute.md +37 -25
  20. package/doc/index.md +8 -8
  21. package/doc/variables.md +1 -1
  22. package/index.d.ts +11 -9
  23. package/index.js +1 -634
  24. package/indirect.js +1 -533
  25. package/lib/native/base/base.cc +63 -85
  26. package/lib/native/base/base.hh +178 -151
  27. package/package.json +3 -4
  28. package/src/build.js +1178 -0
  29. package/src/koffi/CMakeLists.txt +97 -34
  30. package/src/koffi/index.js +359 -0
  31. package/src/koffi/indirect.js +216 -0
  32. package/src/koffi/src/{abi_arm32.cc → abi/arm32.cc} +279 -275
  33. package/src/koffi/src/{abi_arm32_asm.S → abi/arm32_asm.S} +2 -5
  34. package/src/koffi/src/abi/arm64.cc +1511 -0
  35. package/src/koffi/src/{abi_arm64_asm.S → abi/arm64_asm.S} +44 -23
  36. package/src/koffi/src/{abi_arm64_asm.asm → abi/arm64_asm.asm} +32 -25
  37. package/src/koffi/src/{abi_loong64_asm.S → abi/loong64_asm.S} +1 -5
  38. package/src/koffi/src/{abi_riscv64.cc → abi/riscv64.cc} +279 -273
  39. package/src/koffi/src/{abi_riscv64_asm.S → abi/riscv64_asm.S} +1 -4
  40. package/src/koffi/src/abi/x64sysv.cc +1456 -0
  41. package/src/koffi/src/{abi_x64_sysv_asm.S → abi/x64sysv_asm.S} +30 -33
  42. package/src/koffi/src/abi/x64win.cc +1121 -0
  43. package/src/koffi/src/{abi_x64_win_asm.S → abi/x64win_asm.S} +8 -12
  44. package/src/koffi/src/{abi_x64_win_asm.asm → abi/x64win_asm.asm} +11 -14
  45. package/src/koffi/src/abi/x86.cc +1233 -0
  46. package/src/koffi/src/{abi_x86_asm.S → abi/x86_asm.S} +49 -25
  47. package/src/koffi/src/{abi_x86_asm.asm → abi/x86_asm.asm} +11 -14
  48. package/src/koffi/src/call.cc +458 -598
  49. package/src/koffi/src/call.hh +61 -82
  50. package/src/koffi/src/ffi.cc +595 -309
  51. package/src/koffi/src/ffi.hh +103 -89
  52. package/src/koffi/src/parser.cc +0 -4
  53. package/src/koffi/src/primitives.inc +39 -0
  54. package/src/koffi/{tools/write_trampolines.js → src/trampolines.js} +1 -1
  55. package/src/koffi/src/util.cc +503 -446
  56. package/src/koffi/src/util.hh +269 -57
  57. package/src/koffi/src/uv.cc +2 -2
  58. package/src/koffi/src/uv.def +3 -0
  59. package/src/koffi/src/win32.hh +30 -1
  60. package/vendor/node-addon-api/napi-inl.h +4 -0
  61. package/vendor/node-addon-api/napi.h +1 -0
  62. package/build/koffi/linux_armhf/koffi.node +0 -0
  63. package/build/koffi/linux_loong64/koffi.node +0 -0
  64. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  65. package/build/koffi/win32_arm64/koffi.exp +0 -0
  66. package/build/koffi/win32_arm64/koffi.lib +0 -0
  67. package/build/koffi/win32_arm64/koffi.node +0 -0
  68. package/doc/platforms.md +0 -36
  69. package/src/cnoke/LICENSE.txt +0 -22
  70. package/src/cnoke/README.md +0 -99
  71. package/src/cnoke/assets/FindCNoke.cmake +0 -127
  72. package/src/cnoke/assets/toolchains.json +0 -126
  73. package/src/cnoke/assets/win_delay_hook.c +0 -36
  74. package/src/cnoke/cnoke.js +0 -170
  75. package/src/cnoke/package.json +0 -24
  76. package/src/cnoke/src/builder.js +0 -511
  77. package/src/cnoke/src/index.js +0 -10
  78. package/src/cnoke/src/tools.js +0 -407
  79. package/src/koffi/src/abi_arm64.cc +0 -1295
  80. package/src/koffi/src/abi_x64_sysv.cc +0 -939
  81. package/src/koffi/src/abi_x64_win.cc +0 -715
  82. package/src/koffi/src/abi_x86.cc +0 -860
  83. package/src/koffi/src/init.js +0 -105
  84. /package/src/koffi/src/{abi_loong64.cc → abi/loong64.cc} +0 -0
package/src/build.js ADDED
@@ -0,0 +1,1178 @@
1
+ #!/usr/bin/env -S node --no-warnings
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // ../cnoke/cnoke.js
26
+ var import_fs4 = __toESM(require("fs"), 1);
27
+
28
+ // ../cnoke/src/builder.js
29
+ var import_fs3 = __toESM(require("fs"), 1);
30
+ var import_os = __toESM(require("os"), 1);
31
+ var import_path2 = __toESM(require("path"), 1);
32
+ var import_child_process = require("child_process");
33
+
34
+ // ../cnoke/src/abi.js
35
+ var import_fs = __toESM(require("fs"), 1);
36
+ function determineAbi() {
37
+ let abi = process.arch;
38
+ if (abi == "riscv32" || abi == "riscv64") {
39
+ let buf = readFileHeader(process.execPath, 512);
40
+ let header = decodeElfHeader(buf);
41
+ let float_abi = header.e_flags & 6;
42
+ switch (float_abi) {
43
+ case 0:
44
+ {
45
+ }
46
+ break;
47
+ case 2:
48
+ {
49
+ abi += "f";
50
+ }
51
+ break;
52
+ case 4:
53
+ {
54
+ abi += "d";
55
+ }
56
+ break;
57
+ case 6:
58
+ {
59
+ abi += "q";
60
+ }
61
+ break;
62
+ }
63
+ } else if (abi == "arm") {
64
+ let buf = readFileHeader(process.execPath, 512);
65
+ let header = decodeElfHeader(buf);
66
+ if (header.e_flags & 1024) {
67
+ abi += "hf";
68
+ } else if (header.e_flags & 512) {
69
+ abi += "sf";
70
+ } else {
71
+ throw new Error("Unknown ARM floating-point ABI");
72
+ }
73
+ }
74
+ return abi;
75
+ }
76
+ function readFileHeader(filename, read) {
77
+ let fd = null;
78
+ try {
79
+ let fd2 = import_fs.default.openSync(filename);
80
+ let buf = Buffer.allocUnsafe(read);
81
+ let len = import_fs.default.readSync(fd2, buf);
82
+ return buf.subarray(0, len);
83
+ } finally {
84
+ if (fd != null)
85
+ import_fs.default.closeSync(fd);
86
+ }
87
+ }
88
+ function decodeElfHeader(buf) {
89
+ let header = {};
90
+ if (buf.length < 16)
91
+ throw new Error("Truncated header");
92
+ if (buf[0] != 127 || buf[1] != 69 || buf[2] != 76 || buf[3] != 70)
93
+ throw new Error("Invalid magic number");
94
+ if (buf[6] != 1)
95
+ throw new Error("Invalid ELF version");
96
+ if (buf[5] != 1)
97
+ throw new Error("Big-endian architectures are not supported");
98
+ header.e_machine = buf.readUInt16LE(18);
99
+ switch (buf[4]) {
100
+ case 1:
101
+ {
102
+ buf = buf.subarray(0, 68);
103
+ if (buf.length < 68)
104
+ throw new Error("Truncated ELF header");
105
+ header.ei_class = 32;
106
+ header.e_flags = buf.readUInt32LE(36);
107
+ }
108
+ break;
109
+ case 2:
110
+ {
111
+ buf = buf.subarray(0, 120);
112
+ if (buf.length < 120)
113
+ throw new Error("Truncated ELF header");
114
+ header.ei_class = 64;
115
+ header.e_flags = buf.readUInt32LE(48);
116
+ }
117
+ break;
118
+ default:
119
+ throw new Error("Invalid ELF class");
120
+ }
121
+ return header;
122
+ }
123
+
124
+ // ../cnoke/src/util.js
125
+ var import_crypto = __toESM(require("crypto"), 1);
126
+ var import_fs2 = __toESM(require("fs"), 1);
127
+ var import_https = __toESM(require("https"), 1);
128
+ var import_path = __toESM(require("path"), 1);
129
+ var import_zlib = __toESM(require("zlib"), 1);
130
+ async function downloadHttp(url, dest) {
131
+ console.log(">> Downloading " + url);
132
+ let [tmp_name, file] = openTemporaryStream(dest);
133
+ try {
134
+ await new Promise((resolve, reject) => {
135
+ let request = import_https.default.get(url, (response) => {
136
+ if (response.statusCode != 200) {
137
+ let err = new Error(`Download failed: ${response.statusMessage} [${response.statusCode}]`);
138
+ err.code = response.statusCode;
139
+ reject(err);
140
+ return;
141
+ }
142
+ response.pipe(file);
143
+ file.on("finish", () => file.close(() => {
144
+ try {
145
+ import_fs2.default.renameSync(file.path, dest);
146
+ } catch (err) {
147
+ if (!import_fs2.default.existsSync(dest))
148
+ reject(err);
149
+ }
150
+ resolve();
151
+ }));
152
+ });
153
+ request.on("error", reject);
154
+ file.on("error", reject);
155
+ });
156
+ } catch (err) {
157
+ file.close();
158
+ try {
159
+ import_fs2.default.unlinkSync(tmp_name);
160
+ } catch (err2) {
161
+ if (err2.code != "ENOENT")
162
+ throw err2;
163
+ }
164
+ throw err;
165
+ }
166
+ }
167
+ function openTemporaryStream(prefix) {
168
+ let buf = Buffer.allocUnsafe(4);
169
+ for (; ; ) {
170
+ try {
171
+ import_crypto.default.randomFillSync(buf);
172
+ let suffix = buf.toString("hex").padStart(8, "0");
173
+ let filename = `${prefix}.${suffix}`;
174
+ let file = import_fs2.default.createWriteStream(filename, { flags: "wx", mode: 420 });
175
+ return [filename, file];
176
+ } catch (err) {
177
+ if (err.code != "EEXIST")
178
+ throw err;
179
+ }
180
+ }
181
+ }
182
+ function extractTarGz(filename, dest_dir, strip = 0) {
183
+ let reader = import_fs2.default.createReadStream(filename).pipe(import_zlib.default.createGunzip());
184
+ return new Promise((resolve, reject) => {
185
+ let header = null;
186
+ let extended = {};
187
+ reader.on("readable", () => {
188
+ try {
189
+ for (; ; ) {
190
+ if (header == null) {
191
+ let buf = reader.read(512);
192
+ if (buf == null)
193
+ break;
194
+ if (!buf[0])
195
+ continue;
196
+ header = {
197
+ filename: buf.toString("utf-8", 0, 100).replace(/\0/g, ""),
198
+ mode: parseInt(buf.toString("ascii", 100, 109), 8),
199
+ size: parseInt(buf.toString("ascii", 124, 137), 8),
200
+ type: String.fromCharCode(buf[156])
201
+ };
202
+ Object.assign(header, extended);
203
+ extended = {};
204
+ header.filename = header.filename.replace(/\\/g, "/");
205
+ if (!header.filename.length)
206
+ throw new Error(`Insecure empty filename inside TAR archive`);
207
+ if (pathIsAbsolute(header.filename[0]))
208
+ throw new Error(`Insecure filename starting with / inside TAR archive`);
209
+ if (pathHasDotDot(header.filename))
210
+ throw new Error(`Insecure filename containing '..' inside TAR archive`);
211
+ for (let i = 0; i < strip; i++)
212
+ header.filename = header.filename.substr(header.filename.indexOf("/") + 1);
213
+ }
214
+ let aligned = Math.floor((header.size + 511) / 512) * 512;
215
+ let data = header.size ? reader.read(aligned) : null;
216
+ if (data == null) {
217
+ if (header.size)
218
+ break;
219
+ data = Buffer.alloc(0);
220
+ }
221
+ data = data.subarray(0, header.size);
222
+ if (header.type == "0" || header.type == "7") {
223
+ let filename2 = dest_dir + "/" + header.filename;
224
+ let dirname = import_path.default.dirname(filename2);
225
+ import_fs2.default.mkdirSync(dirname, { recursive: true, mode: 493 });
226
+ import_fs2.default.writeFileSync(filename2, data, { mode: header.mode });
227
+ } else if (header.type == "5") {
228
+ let filename2 = dest_dir + "/" + header.filename;
229
+ import_fs2.default.mkdirSync(filename2, { recursive: true, mode: header.mode });
230
+ } else if (header.type == "L") {
231
+ extended.filename = data.toString("utf-8").replace(/\0/g, "");
232
+ } else if (header.type == "x") {
233
+ let str = data.toString("utf-8");
234
+ try {
235
+ while (str.length) {
236
+ let matches = str.match(/^([0-9]+) ([a-zA-Z0-9\._]+)=(.*)\n/);
237
+ let skip = parseInt(matches[1], 10);
238
+ let key = matches[2];
239
+ let value = matches[3];
240
+ switch (key) {
241
+ case "path":
242
+ {
243
+ extended.filename = value;
244
+ }
245
+ break;
246
+ case "size":
247
+ {
248
+ extended.size = parseInt(value, 10);
249
+ }
250
+ break;
251
+ }
252
+ str = str.substr(skip).trimStart();
253
+ }
254
+ } catch (err) {
255
+ throw new Error("Malformed PAX entry");
256
+ }
257
+ }
258
+ header = null;
259
+ }
260
+ } catch (err) {
261
+ reject(err);
262
+ }
263
+ });
264
+ reader.on("error", reject);
265
+ reader.on("end", resolve);
266
+ });
267
+ }
268
+ function pathIsAbsolute(path3) {
269
+ if (process.platform == "win32" && path3.match(/^[a-zA-Z]:/))
270
+ path3 = path3.substr(2);
271
+ return isPathSeparator(path3[0]);
272
+ }
273
+ function pathHasDotDot(path3) {
274
+ let start = 0;
275
+ for (; ; ) {
276
+ let offset = path3.indexOf("..", start);
277
+ if (offset < 0)
278
+ break;
279
+ start = offset + 2;
280
+ if (offset && !isPathSeparator(path3[offset - 1]))
281
+ continue;
282
+ if (offset + 2 < path3.length && !isPathSeparator(path3[offset + 2]))
283
+ continue;
284
+ return true;
285
+ }
286
+ return false;
287
+ }
288
+ function isPathSeparator(c) {
289
+ if (c == "/")
290
+ return true;
291
+ if (process.platform == "win32" && c == "\\")
292
+ return true;
293
+ return false;
294
+ }
295
+ function syncFiles(src_dir, dest_dir) {
296
+ let keep = /* @__PURE__ */ new Set();
297
+ {
298
+ let entries = import_fs2.default.readdirSync(src_dir, { withFileTypes: true });
299
+ for (let entry of entries) {
300
+ if (!entry.isFile())
301
+ continue;
302
+ keep.add(entry.name);
303
+ import_fs2.default.copyFileSync(src_dir + `/${entry.name}`, dest_dir + `/${entry.name}`);
304
+ }
305
+ }
306
+ {
307
+ let entries = import_fs2.default.readdirSync(dest_dir, { withFileTypes: true });
308
+ for (let entry of entries) {
309
+ if (!entry.isFile())
310
+ continue;
311
+ if (keep.has(entry.name))
312
+ continue;
313
+ import_fs2.default.unlinkSync(dest_dir + `/${entry.name}`);
314
+ }
315
+ }
316
+ }
317
+ function unlinkRecursive(path3) {
318
+ try {
319
+ import_fs2.default.rmSync(path3, { recursive: true, maxRetries: process.platform == "win32" ? 3 : 0 });
320
+ } catch (err) {
321
+ if (err.code !== "ENOENT")
322
+ throw err;
323
+ }
324
+ }
325
+ function getNapiVersion(napi, major) {
326
+ if (napi > 8)
327
+ return null;
328
+ const support = {
329
+ 6: ["6.14.2", "6.14.2", "6.14.2"],
330
+ 8: ["8.6.0", "8.10.0", "8.11.2"],
331
+ 9: ["9.0.0", "9.3.0", "9.11.0"],
332
+ 10: ["10.0.0", "10.0.0", "10.0.0", "10.16.0", "10.17.0", "10.20.0", "10.23.0"],
333
+ 11: ["11.0.0", "11.0.0", "11.0.0", "11.8.0"],
334
+ 12: ["12.0.0", "12.0.0", "12.0.0", "12.0.0", "12.11.0", "12.17.0", "12.19.0", "12.22.0"],
335
+ 13: ["13.0.0", "13.0.0", "13.0.0", "13.0.0", "13.0.0"],
336
+ 14: ["14.0.0", "14.0.0", "14.0.0", "14.0.0", "14.0.0", "14.0.0", "14.12.0", "14.17.0"],
337
+ 15: ["15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.12.0"]
338
+ };
339
+ const max = Math.max(...Object.keys(support).map((k) => parseInt(k, 10)));
340
+ if (major > max)
341
+ return major + ".0.0";
342
+ if (support[major] == null)
343
+ return null;
344
+ let required = support[major][napi - 1] || null;
345
+ return required;
346
+ }
347
+ function compareVersions(ver1, ver2) {
348
+ ver1 = String(ver1).replace(/-.*$/, "").split(".").reduce((acc, v, idx) => acc + parseInt(v, 10) * Math.pow(10, 2 * (5 - idx)), 0);
349
+ ver2 = String(ver2).replace(/-.*$/, "").split(".").reduce((acc, v, idx) => acc + parseInt(v, 10) * Math.pow(10, 2 * (5 - idx)), 0);
350
+ let cmp = Math.min(Math.max(ver1 - ver2, -1), 1);
351
+ return cmp;
352
+ }
353
+
354
+ // ../cnoke/src/assets.js
355
+ var FIND_CNOKE_CMAKE = `# SPDX-License-Identifier: MIT
356
+ # SPDX-FileCopyrightText: 2025 Niels Martign\xE8ne <niels.martignene@protonmail.com>
357
+
358
+ if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR
359
+ CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
360
+ set(USE_UNITY_BUILDS ON CACHE BOOL "Use single-TU builds (aka. Unity builds)")
361
+ else()
362
+ set(USE_UNITY_BUILDS OFF CACHE BOOL "Use single-TU builds (aka. Unity builds)")
363
+ endif()
364
+
365
+ function(add_node_addon)
366
+ cmake_parse_arguments(ARG "" "NAME" "SOURCES" \${ARGN})
367
+ add_library(\${ARG_NAME} SHARED \${ARG_SOURCES} \${NODE_JS_SOURCES})
368
+ target_link_node(\${ARG_NAME})
369
+ set_target_properties(\${ARG_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
370
+ endfunction()
371
+
372
+ function(target_link_node TARGET)
373
+ target_include_directories(\${TARGET} PRIVATE \${NODE_JS_INCLUDE_DIRS})
374
+ if(NODE_JS_LINK_DEF)
375
+ target_sources(\${TARGET} PRIVATE node.lib)
376
+ endif()
377
+ if(NODE_JS_LINK_LIB)
378
+ target_link_libraries(\${TARGET} PRIVATE \${NODE_JS_LINK_LIB})
379
+ endif()
380
+ target_compile_options(\${TARGET} PRIVATE \${NODE_JS_COMPILE_FLAGS})
381
+ if(NODE_JS_LINK_FLAGS)
382
+ target_link_options(\${TARGET} PRIVATE \${NODE_JS_LINK_FLAGS})
383
+ endif()
384
+ endfunction()
385
+
386
+ if(WIN32)
387
+ function(create_import_lib OUTPUT SRC)
388
+ if (MSVC)
389
+ add_custom_command(OUTPUT \${OUTPUT}
390
+ COMMAND \${CMAKE_AR} \${CMAKE_STATIC_LINKER_FLAGS}
391
+ /def:\${SRC} /out:"\${CMAKE_CURRENT_BINARY_DIR}/\${OUTPUT}"
392
+ WORKING_DIRECTORY \${CMAKE_CURRENT_SOURCE_DIR}
393
+ MAIN_DEPENDENCY \${SRC})
394
+ elseif(DEFINED NODE_JS_DLLTOOL_MACHINE)
395
+ add_custom_command(OUTPUT \${OUTPUT}
396
+ COMMAND \${CMAKE_DLLTOOL} -d \${SRC} -l "\${CMAKE_CURRENT_BINARY_DIR}/\${OUTPUT}" -m \${NODE_JS_DLLTOOL_MACHINE}
397
+ WORKING_DIRECTORY \${CMAKE_CURRENT_SOURCE_DIR}
398
+ MAIN_DEPENDENCY \${SRC})
399
+ else()
400
+ add_custom_command(OUTPUT \${OUTPUT}
401
+ COMMAND \${CMAKE_DLLTOOL} -d \${SRC} -l "\${CMAKE_CURRENT_BINARY_DIR}/\${OUTPUT}"
402
+ WORKING_DIRECTORY \${CMAKE_CURRENT_SOURCE_DIR}
403
+ MAIN_DEPENDENCY \${SRC})
404
+ endif()
405
+ endfunction()
406
+ endif()
407
+
408
+ if(NODE_JS_LINK_DEF)
409
+ create_import_lib(node.lib \${NODE_JS_LINK_DEF})
410
+ set(NODE_JS_LINK_LIB "\${CMAKE_CURRENT_BINARY_DIR}/node.lib")
411
+ endif()
412
+
413
+ if(USE_UNITY_BUILDS)
414
+ function(enable_unity_build TARGET)
415
+ cmake_parse_arguments(ARG "" "" "EXCLUDE" \${ARGN})
416
+
417
+ get_target_property(sources \${TARGET} SOURCES)
418
+ string(GENEX_STRIP "\${sources}" sources)
419
+
420
+ set(unity_file_c "\${CMAKE_CURRENT_BINARY_DIR}/\${TARGET}_unity.c")
421
+ set(unity_file_cpp "\${CMAKE_CURRENT_BINARY_DIR}/\${TARGET}_unity.cpp")
422
+ file(REMOVE \${unity_file_c} \${unity_file_cpp})
423
+
424
+ set(c_definitions "")
425
+ set(cpp_definitions "")
426
+
427
+ foreach(src \${sources})
428
+ if (src IN_LIST ARG_EXCLUDE)
429
+ continue()
430
+ endif()
431
+
432
+ get_source_file_property(language \${src} LANGUAGE)
433
+ get_property(definitions SOURCE \${src} PROPERTY COMPILE_DEFINITIONS)
434
+ if(IS_ABSOLUTE \${src})
435
+ set(src_full \${src})
436
+ else()
437
+ set(src_full "\${CMAKE_CURRENT_SOURCE_DIR}/\${src}")
438
+ endif()
439
+ if(language STREQUAL "C")
440
+ set_source_files_properties(\${src} PROPERTIES HEADER_FILE_ONLY 1)
441
+ file(APPEND \${unity_file_c} "#include \\"\${src_full}\\"\\n")
442
+ if (definitions)
443
+ set(c_definitions "\${c_definitions} \${definitions}")
444
+ endif()
445
+ elseif(language STREQUAL "CXX")
446
+ set_source_files_properties(\${src} PROPERTIES HEADER_FILE_ONLY 1)
447
+ file(APPEND \${unity_file_cpp} "#include \\"\${src_full}\\"\\n")
448
+ if (definitions)
449
+ set(cpp_definitions "\${cpp_definitions} \${definitions}")
450
+ endif()
451
+ endif()
452
+ endforeach()
453
+
454
+ if(EXISTS \${unity_file_c})
455
+ target_sources(\${TARGET} PRIVATE \${unity_file_c})
456
+ if(c_definitions)
457
+ set_source_files_properties(\${unity_file_c} PROPERTIES COMPILE_DEFINITIONS \${c_definitions})
458
+ endif()
459
+ endif()
460
+ if(EXISTS \${unity_file_cpp})
461
+ target_sources(\${TARGET} PRIVATE \${unity_file_cpp})
462
+ if(cpp_definitions)
463
+ set_source_files_properties(\${unity_file_cpp} PROPERTIES COMPILE_DEFINITIONS \${cpp_definitions})
464
+ endif()
465
+ endif()
466
+
467
+ target_compile_definitions(\${TARGET} PRIVATE -DUNITY_BUILD=1)
468
+ endfunction()
469
+ else()
470
+ function(enable_unity_build TARGET)
471
+ endfunction()
472
+ endif()
473
+
474
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
475
+ if(CMAKE_SYSTEM_PROCESSOR MATCHES "(amd64|x86_64)")
476
+ foreach(lang C CXX)
477
+ set(CMAKE_\${lang}_FLAGS_RELEASE "\${CMAKE_\${lang}_FLAGS_RELEASE} -mpopcnt -msse4.1 -msse4.2 -mssse3 -mcx16")
478
+ set(CMAKE_\${lang}_FLAGS_RELWITHDEBINFO "\${CMAKE_\${lang}_FLAGS_RELWITHDEBINFO} -mpopcnt -msse4.1 -msse4.2 -mssse3 -mcx16")
479
+ endforeach()
480
+ endif()
481
+ endif()
482
+ `;
483
+ var WIN_DELAY_HOOK_C = `// SPDX-License-Identifier: MIT
484
+ // SPDX-FileCopyrightText: 2025 Niels Martign\xE8ne <niels.martignene@protonmail.com>
485
+
486
+ #include <stdlib.h>
487
+ #if !defined(NOMINMAX)
488
+ #define NOMINMAX
489
+ #endif
490
+ #if !defined(WIN32_LEAN_AND_MEAN)
491
+ #define WIN32_LEAN_AND_MEAN
492
+ #endif
493
+ #include <windows.h>
494
+ #include <delayimp.h>
495
+
496
+ static HMODULE node_dll;
497
+
498
+ static FARPROC WINAPI self_exe_hook(unsigned int event, DelayLoadInfo *info)
499
+ {
500
+ if (event == dliStartProcessing) {
501
+ node_dll = GetModuleHandleA("node.dll");
502
+ if (!node_dll) {
503
+ node_dll = GetModuleHandle(NULL);
504
+ }
505
+ return NULL;
506
+ }
507
+
508
+ if (event == dliNotePreLoadLibrary && !stricmp(info->szDll, "node.exe"))
509
+ return (FARPROC)node_dll;
510
+
511
+ return NULL;
512
+ }
513
+
514
+ #if defined(__MINGW32__)
515
+ PfnDliHook __pfnDliNotifyHook2 = self_exe_hook;
516
+ #else
517
+ const PfnDliHook __pfnDliNotifyHook2 = self_exe_hook;
518
+ #endif
519
+ `;
520
+
521
+ // ../cnoke/src/toolchains.json
522
+ var toolchains_default = {
523
+ linux_ia32: {
524
+ system: "Linux",
525
+ processor: "i386",
526
+ triplet: "i686-linux-gnu",
527
+ sysroot: "../../tools/cross/sysroots/debian_i386"
528
+ },
529
+ linux_x64: {
530
+ system: "Linux",
531
+ processor: "x86_64",
532
+ triplet: "x86_64-linux-gnu",
533
+ sysroot: "../../tools/cross/sysroots/debian_x64"
534
+ },
535
+ linux_armhf: {
536
+ system: "Linux",
537
+ processor: "arm",
538
+ triplet: "arm-linux-gnueabihf",
539
+ sysroot: "../../tools/cross/sysroots/debian_arm32"
540
+ },
541
+ linux_arm64: {
542
+ system: "Linux",
543
+ processor: "aarch64",
544
+ triplet: "aarch64-linux-gnu",
545
+ sysroot: "../../tools/cross/sysroots/debian_arm64"
546
+ },
547
+ linux_riscv64d: {
548
+ system: "Linux",
549
+ processor: "riscv64",
550
+ triplet: "riscv64-linux-gnu",
551
+ sysroot: "../../tools/cross/sysroots/debian_riscv64"
552
+ },
553
+ linux_loong64: {
554
+ system: "Linux",
555
+ processor: "loongarch64",
556
+ triplet: "loongarch64-linux-gnu",
557
+ sysroot: "../../tools/cross/sysroots/debian_loong64"
558
+ },
559
+ win32_ia32: {
560
+ system: "Windows",
561
+ processor: "X86",
562
+ lib: "win-x86",
563
+ flags: ["-DNODE_JS_LINK_FLAGS=/DELAYLOAD:node.exe;/SAFESEH:NO", "-A", "Win32"],
564
+ triplet: "i386-pc-windows-msvc",
565
+ linux: {
566
+ sysroot: "../../tools/cross/sysroots/windows_i386",
567
+ flags: ["-DNODE_JS_LINK_FLAGS=-Wl,/DELAYLOAD:node.exe,/SAFESEH:NO", "-DNODE_JS_DLLTOOL_MACHINE=i386"],
568
+ variables: {
569
+ CMAKE_DLLTOOL: "llvm-dlltool",
570
+ CMAKE_RC_COMPILER: "llvm-rc",
571
+ CMAKE_C_FLAGS: "-Xmicrosoft-windows-sys-root {{ sysroot }}",
572
+ CMAKE_CXX_FLAGS: "-Xmicrosoft-windows-sys-root {{ sysroot }}",
573
+ CMAKE_EXE_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/x86_64 -ldelayimp",
574
+ CMAKE_STATIC_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/x86_64 -ldelayimp",
575
+ CMAKE_SHARED_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/x86_64 -ldelayimp"
576
+ }
577
+ }
578
+ },
579
+ win32_x64: {
580
+ system: "Windows",
581
+ processor: "AMD64",
582
+ lib: "win-x64",
583
+ flags: ["-DNODE_JS_LINK_FLAGS=/DELAYLOAD:node.exe"],
584
+ triplet: "x86_64-pc-windows-msvc",
585
+ linux: {
586
+ sysroot: "../../tools/cross/sysroots/windows_x64",
587
+ flags: ["-DNODE_JS_LINK_FLAGS=-Wl,/DELAYLOAD:node.exe", "-DNODE_JS_DLLTOOL_MACHINE=i386:x86-64"],
588
+ variables: {
589
+ CMAKE_DLLTOOL: "llvm-dlltool",
590
+ CMAKE_RC_COMPILER: "llvm-rc",
591
+ CMAKE_C_FLAGS: "-Xmicrosoft-windows-sys-root {{ sysroot }}",
592
+ CMAKE_CXX_FLAGS: "-Xmicrosoft-windows-sys-root {{ sysroot }}",
593
+ CMAKE_EXE_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/x86_64 -ldelayimp",
594
+ CMAKE_STATIC_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/x86_64 -ldelayimp",
595
+ CMAKE_SHARED_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/x86_64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/x86_64 -ldelayimp"
596
+ }
597
+ }
598
+ },
599
+ win32_arm64: {
600
+ system: "Windows",
601
+ processor: "ARM64",
602
+ lib: "win-arm64",
603
+ flags: ["-DNODE_JS_LINK_FLAGS=/DELAYLOAD:node.exe;/SAFESEH:NO", "-A", "ARM64"],
604
+ triplet: "aarch64-pc-windows-msvc",
605
+ linux: {
606
+ sysroot: "../../tools/cross/sysroots/windows_arm64",
607
+ flags: ["-DNODE_JS_LINK_FLAGS=-Wl,/DELAYLOAD:node.exe,/SAFESEH:NO", "-DNODE_JS_DLLTOOL_MACHINE=arm64"],
608
+ variables: {
609
+ CMAKE_DLLTOOL: "llvm-dlltool",
610
+ CMAKE_RC_COMPILER: "llvm-rc",
611
+ CMAKE_C_FLAGS: "-Xmicrosoft-windows-sys-root {{ sysroot }}",
612
+ CMAKE_CXX_FLAGS: "-Xmicrosoft-windows-sys-root {{ sysroot }}",
613
+ CMAKE_EXE_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/aarch64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/aarch64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/aarch64 -ldelayimp",
614
+ CMAKE_STATIC_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/aarch64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/aarch64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/aarch64 -ldelayimp",
615
+ CMAKE_SHARED_LINKER_FLAGS: "-Wl,-libpath:{{ sysroot }}/VC/Tools/MSVC/Current/lib/aarch64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/ucrt/aarch64,-libpath:{{ sysroot }}/Kits/10/Lib/Current/um/aarch64 -ldelayimp"
616
+ }
617
+ }
618
+ },
619
+ darwin_x64: {
620
+ system: "Darwin",
621
+ processor: "x86_64",
622
+ flags: ["-DNODE_JS_LINK_FLAGS=-undefined;dynamic_lookup", "-DCMAKE_OSX_ARCHITECTURES=x86_64"]
623
+ },
624
+ darwin_arm64: {
625
+ system: "Darwin",
626
+ processor: "arm64",
627
+ flags: ["-DNODE_JS_LINK_FLAGS=-undefined;dynamic_lookup", "-DCMAKE_OSX_ARCHITECTURES=arm64"]
628
+ },
629
+ freebsd_x64: {
630
+ system: "FreeBSD",
631
+ processor: "amd64",
632
+ triplet: "x86_64-unknown-freebsd",
633
+ sysroot: "../../tools/cross/sysroots/freebsd_x64"
634
+ },
635
+ freebsd_arm64: {
636
+ system: "FreeBSD",
637
+ processor: "arm64",
638
+ triplet: "aarch64-unknown-freebsd",
639
+ sysroot: "../../tools/cross/sysroots/freebsd_arm64"
640
+ }
641
+ };
642
+
643
+ // ../cnoke/src/builder.js
644
+ var DefaultOptions = {
645
+ mode: "RelWithDebInfo"
646
+ };
647
+ function Builder(config = {}) {
648
+ let self = this;
649
+ let host = `${process.platform}_${determineAbi()}`;
650
+ let project_dir = config.project_dir;
651
+ let package_dir = config.package_dir;
652
+ if (project_dir == null)
653
+ project_dir = process.cwd();
654
+ project_dir = project_dir.replace(/\\/g, "/");
655
+ if (package_dir == null)
656
+ package_dir = findParentDirectory(project_dir, "package.json");
657
+ if (package_dir != null)
658
+ package_dir = package_dir.replace(/\\/g, "/");
659
+ let runtime_version = config.runtime_version;
660
+ let toolchain = config.toolchain || null;
661
+ let prefer_clang = config.prefer_clang || false;
662
+ let mode = config.mode || DefaultOptions.mode;
663
+ let targets = config.targets || [];
664
+ let verbose = config.verbose || false;
665
+ let prebuild = config.prebuild || false;
666
+ let defines = config.defines || [];
667
+ if (runtime_version == null)
668
+ runtime_version = process.version;
669
+ if (runtime_version.startsWith("v"))
670
+ runtime_version = runtime_version.substr(1);
671
+ UNSAFE: (() => {
672
+ if (toolchain != null && !Object.hasOwn(toolchains_default, toolchain))
673
+ throw new Error(`Unknown cross-compilation toolchain '${toolchain}'`);
674
+ })();
675
+ let options = null;
676
+ let cache_dir = getCacheDirectory();
677
+ let build_dir = config.build_dir;
678
+ let work_dir = null;
679
+ let output_dir = null;
680
+ if (build_dir == null) {
681
+ let options2 = readCNokeOptions();
682
+ if (options2.output != null) {
683
+ build_dir = expandPath(options2.output, options2.directory);
684
+ } else {
685
+ build_dir = project_dir + "/build";
686
+ }
687
+ }
688
+ build_dir = build_dir.replace(/\\/g, "/");
689
+ work_dir = build_dir + `/v${runtime_version}_${toolchain ?? "native"}/${mode}`;
690
+ output_dir = work_dir + "/Output";
691
+ let cmake_bin = null;
692
+ this.configure = async function(retry = true) {
693
+ let options2 = readCNokeOptions();
694
+ let args = [project_dir];
695
+ checkCMake();
696
+ checkCompatibility();
697
+ console.log(`>> Node: ${runtime_version}`);
698
+ console.log(`>> Toolchain: ${toolchain ?? "native"}`);
699
+ import_fs3.default.mkdirSync(build_dir, { recursive: true, mode: 493 });
700
+ import_fs3.default.mkdirSync(work_dir, { recursive: true, mode: 493 });
701
+ import_fs3.default.mkdirSync(output_dir, { recursive: true, mode: 493 });
702
+ retry &= import_fs3.default.existsSync(work_dir + "/CMakeCache.txt");
703
+ args.push(`-DNODE_JS_EXECPATH=${process.execPath}`);
704
+ if (options2.api == null) {
705
+ let downloaded = false;
706
+ UNSAFE: await (async () => {
707
+ let destname = `${cache_dir}/node-v${runtime_version}-headers.tar.gz`;
708
+ if (!import_fs3.default.existsSync(destname)) {
709
+ import_fs3.default.mkdirSync(cache_dir, { recursive: true, mode: 493 });
710
+ let url = `https://nodejs.org/dist/v${runtime_version}/node-v${runtime_version}-headers.tar.gz`;
711
+ await downloadHttp(url, destname);
712
+ }
713
+ await extractTarGz(destname, work_dir + "/headers", 1);
714
+ downloaded = true;
715
+ args.push(`-DNODE_JS_INCLUDE_DIRS=${work_dir}/headers/include/node`);
716
+ })();
717
+ if (!downloaded)
718
+ throw new Error("Cannot download API headers");
719
+ } else {
720
+ console.log(`>> Using local node-api headers`);
721
+ let api_dir = expandPath(options2.api, project_dir);
722
+ args.push(`-DNODE_JS_INCLUDE_DIRS=${api_dir}/include`);
723
+ }
724
+ import_fs3.default.writeFileSync(work_dir + "/FindCNoke.cmake", FIND_CNOKE_CMAKE);
725
+ args.push(`-DCMAKE_MODULE_PATH=${work_dir}`);
726
+ let win32 = (toolchain ?? host).startsWith("win32_");
727
+ let mingw = process.platform == "win32" && process.env.MSYSTEM != null;
728
+ if (win32) {
729
+ if (mingw) {
730
+ args.push(`-DNODE_JS_LINK_LIB=node.dll`);
731
+ } else {
732
+ if (options2.api == null) {
733
+ let downloaded = false;
734
+ UNSAFE: await (async () => {
735
+ let info = toolchains_default[toolchain ?? host];
736
+ let destname = `${cache_dir}/node_v${runtime_version}_${toolchain ?? host}.lib`;
737
+ if (!import_fs3.default.existsSync(destname)) {
738
+ import_fs3.default.mkdirSync(cache_dir, { recursive: true, mode: 493 });
739
+ let url = `https://nodejs.org/dist/v${runtime_version}/${info.lib}/node.lib`;
740
+ await downloadHttp(url, destname);
741
+ }
742
+ import_fs3.default.copyFileSync(destname, work_dir + "/node.lib");
743
+ args.push(`-DNODE_JS_LINK_LIB=${work_dir}/node.lib`);
744
+ downloaded = true;
745
+ })();
746
+ if (!downloaded)
747
+ throw new Error("Cannot download Node import library");
748
+ } else {
749
+ let api_dir = expandPath(options2.api, project_dir);
750
+ args.push(`-DNODE_JS_LINK_DEF=${api_dir}/def/node_api.def`);
751
+ }
752
+ }
753
+ import_fs3.default.writeFileSync(work_dir + "/win_delay_hook.c", WIN_DELAY_HOOK_C);
754
+ args.push(`-DNODE_JS_SOURCES=${work_dir}/win_delay_hook.c`);
755
+ }
756
+ if (process.platform != "win32" || mingw) {
757
+ if ((0, import_child_process.spawnSync)("ninja", ["--version"]).status === 0) {
758
+ args.push("-G", "Ninja");
759
+ } else if (process.platform == "win32") {
760
+ args.push("-G", "MinGW Makefiles");
761
+ }
762
+ if (config.ccache && (0, import_child_process.spawnSync)("ccache", ["--version"]).status === 0) {
763
+ args.push("-DCMAKE_C_COMPILER_LAUNCHER=ccache");
764
+ args.push("-DCMAKE_CXX_COMPILER_LAUNCHER=ccache");
765
+ }
766
+ }
767
+ UNSAFE: (() => {
768
+ let info = toolchains_default[toolchain ?? host];
769
+ if (info != null) {
770
+ if (Object.hasOwn(info, process.platform))
771
+ info = Object.assign({}, info, info[process.platform]);
772
+ if (info.flags != null)
773
+ args.push(...info.flags);
774
+ }
775
+ if (toolchain == null && process.arch == "ia32") {
776
+ let proc2 = (0, import_child_process.spawnSync)("uname", ["-m"]);
777
+ let machine = (proc2.stdout ?? "").toString("utf-8").trim();
778
+ if (machine == "x86_64") {
779
+ args.push("-DCMAKE_ASM_FLAGS=-m32", "-DCMAKE_C_FLAGS=-m32", "-DCMAKE_CXX_FLAGS=-m32");
780
+ }
781
+ }
782
+ if (toolchain != null && info.triplet != null) {
783
+ let values = [
784
+ ["CMAKE_SYSTEM_NAME", info.system],
785
+ ["CMAKE_SYSTEM_PROCESSOR", info.processor]
786
+ ];
787
+ let sysroot = null;
788
+ if (process.platform != "win32" && !prefer_clang) {
789
+ let binary = info.triplet + "-gcc";
790
+ if ((0, import_child_process.spawnSync)(binary, ["-v"]).status !== 0)
791
+ prefer_clang = true;
792
+ }
793
+ if (prefer_clang) {
794
+ values.push(["CMAKE_ASM_COMPILER_TARGET", info.triplet]);
795
+ values.push(["CMAKE_C_COMPILER_TARGET", info.triplet]);
796
+ values.push(["CMAKE_CXX_COMPILER_TARGET", info.triplet]);
797
+ values.push(["CMAKE_EXE_LINKER_FLAGS", "-fuse-ld=lld"]);
798
+ values.push(["CMAKE_SHARED_LINKER_FLAGS", "-fuse-ld=lld"]);
799
+ values.push(["CMAKE_STATIC_LINKER_FLAGS", "-fuse-ld=lld"]);
800
+ } else if (process.platform != "win32") {
801
+ values.push(["CMAKE_ASM_COMPILER", info.triplet + "-gcc"]);
802
+ values.push(["CMAKE_C_COMPILER", info.triplet + "-gcc"]);
803
+ values.push(["CMAKE_CXX_COMPILER", info.triplet + "-g++"]);
804
+ }
805
+ if (info.sysroot != null) {
806
+ sysroot = expandPath(info.sysroot, __dirname + "/..");
807
+ if (!import_fs3.default.existsSync(sysroot))
808
+ throw new Error(`Cross-compilation sysroot '${sysroot}' does not exist`);
809
+ values.push(["CMAKE_SYSROOT", sysroot]);
810
+ }
811
+ if (info.variables != null) {
812
+ for (let key in info.variables) {
813
+ let value = expandString(info.variables[key], { sysroot });
814
+ values.push([key, value]);
815
+ }
816
+ }
817
+ let filename = `${work_dir}/toolchain.cmake`;
818
+ let text = values.map((pair) => `set(${pair[0]} "${pair[1]}")`).join("\n");
819
+ import_fs3.default.writeFileSync(filename, text);
820
+ args.push(`-DCMAKE_TOOLCHAIN_FILE=${filename}`);
821
+ }
822
+ })();
823
+ if (prefer_clang) {
824
+ if (process.platform == "win32" && !mingw) {
825
+ args.push("-T", "ClangCL");
826
+ } else {
827
+ args.push("-DCMAKE_C_COMPILER=clang");
828
+ args.push("-DCMAKE_CXX_COMPILER=clang++");
829
+ }
830
+ }
831
+ args.push(`-DCMAKE_BUILD_TYPE=${mode}`);
832
+ for (let type of ["ARCHIVE", "RUNTIME", "LIBRARY"]) {
833
+ for (let suffix of ["", "_DEBUG", "_RELEASE", "_RELWITHDEBINFO"])
834
+ args.push(`-DCMAKE_${type}_OUTPUT_DIRECTORY${suffix}=${output_dir}`);
835
+ }
836
+ for (let define of defines)
837
+ args.push(`-D${define}`);
838
+ args.push("--no-warn-unused-cli");
839
+ console.log(">> Running configuration");
840
+ let proc = (0, import_child_process.spawnSync)(cmake_bin, args, { cwd: work_dir, stdio: "inherit" });
841
+ if (proc.status !== 0) {
842
+ unlinkRecursive(work_dir);
843
+ if (retry)
844
+ return self.configure(false);
845
+ throw new Error("Failed to run configure step");
846
+ }
847
+ };
848
+ this.build = async function() {
849
+ checkCompatibility();
850
+ if (prebuild) {
851
+ let valid = await checkPrebuild();
852
+ if (valid) {
853
+ return;
854
+ } else {
855
+ console.error("Failed to load prebuilt binary, rebuilding from source");
856
+ }
857
+ }
858
+ checkCMake();
859
+ if (!import_fs3.default.existsSync(work_dir + "/CMakeCache.txt"))
860
+ await self.configure();
861
+ if (process.env.MAKEFLAGS == null)
862
+ process.env.MAKEFLAGS = "-j" + (import_os.default.cpus().length || 1);
863
+ let args = [
864
+ "--build",
865
+ work_dir,
866
+ "--config",
867
+ mode
868
+ ];
869
+ if (verbose)
870
+ args.push("--verbose");
871
+ for (let target of targets)
872
+ args.push("--target", target);
873
+ console.log(">> Running build");
874
+ let proc = (0, import_child_process.spawnSync)(cmake_bin, args, { stdio: "inherit" });
875
+ if (proc.status !== 0)
876
+ throw new Error("Failed to run build step");
877
+ console.log(">> Copy target files");
878
+ syncFiles(output_dir, build_dir);
879
+ };
880
+ async function checkPrebuild() {
881
+ let proc = (0, import_child_process.spawnSync)(process.execPath, ["-e", "require(process.argv[1])", package_dir]);
882
+ return proc.status === 0;
883
+ }
884
+ this.clean = function() {
885
+ unlinkRecursive(build_dir);
886
+ };
887
+ function findParentDirectory(dirname, basename) {
888
+ if (process.platform == "win32")
889
+ dirname = dirname.replace(/\\/g, "/");
890
+ do {
891
+ if (import_fs3.default.existsSync(dirname + "/" + basename))
892
+ return dirname;
893
+ dirname = import_path2.default.dirname(dirname);
894
+ } while (!dirname.endsWith("/"));
895
+ return null;
896
+ }
897
+ function getCacheDirectory() {
898
+ if (process.platform == "win32") {
899
+ let cache_dir2 = process.env["LOCALAPPDATA"] || process.env["APPDATA"];
900
+ if (cache_dir2 == null)
901
+ throw new Error("Missing LOCALAPPDATA and APPDATA environment variable");
902
+ cache_dir2 = import_path2.default.join(cache_dir2, "cnoke");
903
+ return cache_dir2;
904
+ } else {
905
+ let cache_dir2 = process.env["XDG_CACHE_HOME"];
906
+ if (cache_dir2 == null) {
907
+ let home = process.env["HOME"];
908
+ if (home == null)
909
+ throw new Error("Missing HOME environment variable");
910
+ cache_dir2 = import_path2.default.join(home, ".cache");
911
+ }
912
+ cache_dir2 = import_path2.default.join(cache_dir2, "cnoke");
913
+ return cache_dir2;
914
+ }
915
+ }
916
+ function checkCMake() {
917
+ if (cmake_bin != null)
918
+ return;
919
+ if (!import_fs3.default.existsSync(project_dir + "/CMakeLists.txt"))
920
+ throw new Error("This directory does not appear to have a CMakeLists.txt file");
921
+ {
922
+ let proc = (0, import_child_process.spawnSync)("cmake", ["--version"]);
923
+ if (proc.status === 0) {
924
+ cmake_bin = "cmake";
925
+ } else {
926
+ if (process.platform == "win32") {
927
+ let proc2 = (0, import_child_process.spawnSync)("reg", ["query", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Kitware\\CMake", "/v", "InstallDir"]);
928
+ if (proc2.status === 0) {
929
+ let matches = proc2.stdout.toString("utf-8").match(/InstallDir[ \t]+REG_[A-Z_]+[ \t]+(.*)+/);
930
+ if (matches != null) {
931
+ let bin = import_path2.default.join(matches[1].trim(), "bin\\cmake.exe");
932
+ if (import_fs3.default.existsSync(bin))
933
+ cmake_bin = bin;
934
+ }
935
+ }
936
+ }
937
+ if (cmake_bin == null)
938
+ throw new Error("CMake does not seem to be available");
939
+ }
940
+ }
941
+ console.log(`>> Using CMake binary: ${cmake_bin}`);
942
+ }
943
+ function checkCompatibility() {
944
+ let options2 = readCNokeOptions();
945
+ if (options2.node != null && compareVersions(runtime_version, options2.node) < 0)
946
+ throw new Error(`Project ${options2.name} requires Node.js >= ${options2.node}`);
947
+ if (options2.napi != null) {
948
+ let major = parseInt(runtime_version, 10);
949
+ let required = getNapiVersion(options2.napi, major);
950
+ if (required == null)
951
+ throw new Error(`Project ${options2.name} does not support the Node ${major}.x branch (old or missing N-API)`);
952
+ if (compareVersions(runtime_version, required) < 0)
953
+ throw new Error(`Project ${options2.name} requires Node >= ${required} in the Node ${major}.x branch (with N-API >= ${options2.napi})`);
954
+ }
955
+ }
956
+ function readCNokeOptions() {
957
+ if (options != null)
958
+ return options;
959
+ let directory = project_dir;
960
+ let pkg = null;
961
+ let cnoke = null;
962
+ if (package_dir != null) {
963
+ try {
964
+ let json = import_fs3.default.readFileSync(package_dir + "/package.json", { encoding: "utf-8" });
965
+ pkg = JSON.parse(json);
966
+ directory = package_dir;
967
+ } catch (err) {
968
+ if (err.code != "ENOENT")
969
+ throw err;
970
+ }
971
+ }
972
+ if (cnoke == null)
973
+ cnoke = pkg?.cnoke ?? {};
974
+ options = {
975
+ name: pkg?.name ?? import_path2.default.basename(project_dir),
976
+ version: pkg?.version ?? null,
977
+ directory,
978
+ ...cnoke
979
+ };
980
+ return options;
981
+ }
982
+ function expandString(str, values = {}) {
983
+ let expanded = str.replace(/{{ *([a-zA-Z_][a-zA-Z_0-9]*) *}}/g, (match, p1) => {
984
+ switch (p1) {
985
+ case "version":
986
+ {
987
+ let options2 = readCNokeOptions();
988
+ return options2.version || "";
989
+ }
990
+ break;
991
+ case "toolchain":
992
+ return toolchain ?? host;
993
+ default:
994
+ {
995
+ if (Object.hasOwn(values, p1)) {
996
+ return values[p1];
997
+ } else {
998
+ return match;
999
+ }
1000
+ }
1001
+ break;
1002
+ }
1003
+ });
1004
+ return expanded;
1005
+ }
1006
+ function expandPath(str, root) {
1007
+ let expanded = expandString(str);
1008
+ if (!pathIsAbsolute(expanded))
1009
+ expanded = import_path2.default.join(root, expanded);
1010
+ expanded = import_path2.default.normalize(expanded);
1011
+ return expanded;
1012
+ }
1013
+ }
1014
+
1015
+ // ../cnoke/cnoke.js
1016
+ var VALID_COMMANDS = ["build", "configure", "clean"];
1017
+ main();
1018
+ async function main() {
1019
+ let config = {};
1020
+ let command = "build";
1021
+ {
1022
+ let i = 2;
1023
+ if (process.argv.length >= 3 && process.argv[2][0] != "-") {
1024
+ let cmd = process.argv[2];
1025
+ if (VALID_COMMANDS.includes(cmd)) {
1026
+ command = cmd;
1027
+ i++;
1028
+ }
1029
+ }
1030
+ for (; i < process.argv.length; i++) {
1031
+ let arg = process.argv[i];
1032
+ let value = null;
1033
+ if (arg[0] == "-") {
1034
+ if (arg.length > 2 && arg[1] != "-") {
1035
+ value = arg.substr(2);
1036
+ arg = arg.substr(0, 2);
1037
+ } else if (arg[1] == "-") {
1038
+ let offset = arg.indexOf("=");
1039
+ if (offset > 2 && arg.length > offset + 1) {
1040
+ value = arg.substr(offset + 1);
1041
+ arg = arg.substr(0, offset);
1042
+ }
1043
+ }
1044
+ if (value == null && process.argv[i + 1] != null && process.argv[i + 1][0] != "-") {
1045
+ value = process.argv[i + 1];
1046
+ i++;
1047
+ }
1048
+ }
1049
+ if (arg == "--help") {
1050
+ printUsage();
1051
+ return;
1052
+ } else if (arg == "-D" || arg == "--directory") {
1053
+ if (value == null)
1054
+ throw new Error(`Missing value for ${arg}`);
1055
+ config.project_dir = import_fs4.default.realpathSync(value);
1056
+ } else if (arg == "-P" || arg == "--package") {
1057
+ if (value == null)
1058
+ throw new Error(`Missing value for ${arg}`);
1059
+ config.package_dir = import_fs4.default.realpathSync(value);
1060
+ } else if (arg == "-O" || arg == "--output") {
1061
+ if (value == null)
1062
+ throw new Error(`Missing value for ${arg}`);
1063
+ config.output_directory = value;
1064
+ } else if ((command == "build" || command == "configure") && arg == "--runtime") {
1065
+ if (value == null)
1066
+ throw new Error(`Missing value for ${arg}`);
1067
+ if (!value.match(/^[0-9]+\.[0-9]+\.[0-9]+$/))
1068
+ throw new Error(`Malformed runtime version '${value}'`);
1069
+ config.runtime_version = value;
1070
+ } else if ((command == "build" || command == "configure") && arg == "--clang") {
1071
+ config.prefer_clang = true;
1072
+ } else if ((command == "build" || command == "configure") && (arg == "-t" || arg == "--toolchain")) {
1073
+ if (value == null)
1074
+ throw new Error(`Missing value for ${arg}`);
1075
+ config.toolchain = value;
1076
+ } else if (arg == "-c" || arg == "--config") {
1077
+ if (value == null)
1078
+ throw new Error(`Missing value for ${arg}`);
1079
+ switch (value.toLowerCase()) {
1080
+ case "relwithdebinfo":
1081
+ {
1082
+ config.mode = "RelWithDebInfo";
1083
+ }
1084
+ break;
1085
+ case "debug":
1086
+ {
1087
+ config.mode = "Debug";
1088
+ }
1089
+ break;
1090
+ case "release":
1091
+ {
1092
+ config.mode = "Release";
1093
+ }
1094
+ break;
1095
+ default:
1096
+ {
1097
+ throw new Error(`Unknown value '${value}' for ${arg}`);
1098
+ }
1099
+ break;
1100
+ }
1101
+ } else if (arg == "--debug") {
1102
+ config.mode = "Debug";
1103
+ } else if (arg == "--release") {
1104
+ config.mode = "Release";
1105
+ } else if ((command == "build" || command == "configure") && arg == "--ccache") {
1106
+ config.ccache = true;
1107
+ } else if ((command == "build" || command == "configure") && (arg == "-d" || arg == "--define")) {
1108
+ if (value == null)
1109
+ throw new Error(`Missing value for ${arg}`);
1110
+ config.defines ??= [];
1111
+ config.defines.push(value);
1112
+ } else if (command == "build" && arg == "--prebuild") {
1113
+ config.prebuild = true;
1114
+ } else if (command == "build" && arg == "--target") {
1115
+ if (value == null)
1116
+ throw new Error(`Missing value for ${arg}`);
1117
+ config.targets = [value];
1118
+ } else if (command == "build" && (arg == "-v" || arg == "--verbose")) {
1119
+ config.verbose = true;
1120
+ } else {
1121
+ if (arg[0] == "-") {
1122
+ throw new Error(`Unexpected argument '${arg}'`);
1123
+ } else {
1124
+ throw new Error(`Unexpected value '${arg}'`);
1125
+ }
1126
+ }
1127
+ }
1128
+ }
1129
+ try {
1130
+ let builder = new Builder(config);
1131
+ await builder[command]();
1132
+ } catch (err) {
1133
+ console.error(err);
1134
+ process.exit(1);
1135
+ }
1136
+ }
1137
+ function printUsage() {
1138
+ let help = `Usage: cnoke [command] [options...]
1139
+
1140
+ Commands:
1141
+
1142
+ configure Configure CMake build
1143
+ build Build project (configure if needed)
1144
+ clean Clean build files
1145
+
1146
+ Options:
1147
+
1148
+ -D, --directory <DIR> Change source directory
1149
+ (default: current working directory)
1150
+ -P, --package <DIR> Change package directory
1151
+ (default: current working directory)
1152
+ -O, --output <DIR> Set explicit output directory
1153
+ (default: ./build)
1154
+
1155
+ -c, --config <CONFIG> Change build type: RelWithDebInfo, Debug, Release
1156
+ (default: ${DefaultOptions.mode})
1157
+ --debug Shortcut for --config Debug
1158
+ --release Shortcut for --config Release
1159
+
1160
+ --ccache Use ccache if available
1161
+
1162
+ -t, --toolchain <TOOLCHAIN> Cross-compile for specific platform
1163
+ --runtime <VERSION> Change node version
1164
+ (default: ${process.version})
1165
+ --clang Use Clang instead of default CMake compiler
1166
+
1167
+ --prebuild Use prebuilt binary if available
1168
+ --target <TARGET> Only build the specified target
1169
+
1170
+ -v, --verbose Show build commands while building
1171
+
1172
+ The ARCH value is similar to process.arch, with the following differences:
1173
+
1174
+ - arm is changed to arm32hf or arm32sf depending on the floating-point ABI used (hard-float, soft-float)
1175
+ - riscv32 is changed to riscv32sf, riscv32hf32, riscv32hf64 or riscv32hf128 depending on the floating-point ABI
1176
+ - riscv64 is changed to riscv64sf, riscv64hf32, riscv64hf64 or riscv64hf128 depending on the floating-point ABI`;
1177
+ console.log(help);
1178
+ }