@ugo-studio/jspp 0.1.7 → 0.1.9
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/package.json +3 -2
- package/scripts/precompile-headers.ts +110 -0
- package/scripts/setup-compiler.ts +63 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ugo-studio/jspp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
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",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
-
"src/prelude"
|
|
13
|
+
"src/prelude",
|
|
14
|
+
"scripts"
|
|
14
15
|
],
|
|
15
16
|
"scripts": {
|
|
16
17
|
"postinstall": "bun run scripts/setup-compiler.ts",
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
const PRELUDE_DIR = path.resolve(process.cwd(), "src", "prelude");
|
|
5
|
+
const PRECOMPILED_HEADER_BASE_DIR = path.resolve(process.cwd(), "prelude-build");
|
|
6
|
+
|
|
7
|
+
const MODES = [
|
|
8
|
+
{
|
|
9
|
+
name: "debug",
|
|
10
|
+
flags: ["-O0"],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: "release",
|
|
14
|
+
flags: ["-O3", "-DNDEBUG"],
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
if (process.platform === "win32") {
|
|
19
|
+
MODES[0].flags.push("-Wa,-mbig-obj");
|
|
20
|
+
MODES[1].flags.push("-Wa,-mbig-obj");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function getLatestMtime(dirPath: string): Promise<number> {
|
|
24
|
+
let maxMtime = 0;
|
|
25
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
28
|
+
if (entry.isDirectory()) {
|
|
29
|
+
const nestedMtime = await getLatestMtime(fullPath);
|
|
30
|
+
if (nestedMtime > maxMtime) maxMtime = nestedMtime;
|
|
31
|
+
} else {
|
|
32
|
+
const stats = await fs.stat(fullPath);
|
|
33
|
+
if (stats.mtimeMs > maxMtime) maxMtime = stats.mtimeMs;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return maxMtime;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function precompileHeaders() {
|
|
40
|
+
const force = process.argv.includes("--force");
|
|
41
|
+
try {
|
|
42
|
+
await fs.mkdir(PRECOMPILED_HEADER_BASE_DIR, { recursive: true });
|
|
43
|
+
const sourceMtime = await getLatestMtime(PRELUDE_DIR);
|
|
44
|
+
|
|
45
|
+
for (const mode of MODES) {
|
|
46
|
+
const modeDir = path.join(PRECOMPILED_HEADER_BASE_DIR, mode.name);
|
|
47
|
+
const headerPath = path.join(modeDir, "index.hpp");
|
|
48
|
+
const gchPath = path.join(modeDir, "index.hpp.gch");
|
|
49
|
+
|
|
50
|
+
if (!force) {
|
|
51
|
+
try {
|
|
52
|
+
const gchStats = await fs.stat(gchPath);
|
|
53
|
+
if (gchStats.mtimeMs >= sourceMtime) {
|
|
54
|
+
console.log(`[${mode.name.toUpperCase()}] Headers are up-to-date. Skipping.`);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
} catch (e) {
|
|
58
|
+
// PCH doesn't exist, proceed to compile
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(`\n[${mode.name.toUpperCase()}] Setting up...`);
|
|
63
|
+
await fs.mkdir(modeDir, { recursive: true });
|
|
64
|
+
|
|
65
|
+
// Copy index.hpp
|
|
66
|
+
await fs.copyFile(path.join(PRELUDE_DIR, "index.hpp"), headerPath);
|
|
67
|
+
|
|
68
|
+
// Remove existing gch if it exists
|
|
69
|
+
if (
|
|
70
|
+
await fs.stat(gchPath).then(
|
|
71
|
+
() => true,
|
|
72
|
+
() => false,
|
|
73
|
+
)
|
|
74
|
+
) {
|
|
75
|
+
await fs.unlink(gchPath);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(`[${mode.name.toUpperCase()}] Compiling header...`);
|
|
79
|
+
const compile = Bun.spawnSync({
|
|
80
|
+
cmd: [
|
|
81
|
+
"g++",
|
|
82
|
+
"-x",
|
|
83
|
+
"c++-header",
|
|
84
|
+
"-std=c++23",
|
|
85
|
+
...mode.flags,
|
|
86
|
+
headerPath,
|
|
87
|
+
"-o",
|
|
88
|
+
gchPath,
|
|
89
|
+
"-I",
|
|
90
|
+
PRELUDE_DIR,
|
|
91
|
+
],
|
|
92
|
+
stdout: "inherit",
|
|
93
|
+
stderr: "inherit",
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (compile.exitCode !== 0) {
|
|
97
|
+
console.error(
|
|
98
|
+
`[${mode.name.toUpperCase()}] Failed to precompile headers.`,
|
|
99
|
+
);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
console.log(`[${mode.name.toUpperCase()}] Success.`);
|
|
103
|
+
}
|
|
104
|
+
} catch (error: any) {
|
|
105
|
+
console.error(`Error: ${error.message}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
precompileHeaders();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import { platform } from "os";
|
|
3
|
+
|
|
4
|
+
const COLORS = {
|
|
5
|
+
reset: "\x1b[0m",
|
|
6
|
+
green: "\x1b[32m",
|
|
7
|
+
yellow: "\x1b[33m",
|
|
8
|
+
red: "\x1b[31m",
|
|
9
|
+
cyan: "\x1b[36m",
|
|
10
|
+
bold: "\x1b[1m",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function checkGpp(): boolean {
|
|
14
|
+
try {
|
|
15
|
+
const result = spawnSync("g++", ["--version"], { encoding: "utf8" });
|
|
16
|
+
return result.status === 0;
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function setup() {
|
|
23
|
+
console.log(`${COLORS.bold}${COLORS.cyan}JSPP: Checking for C++ compiler...${COLORS.reset}`);
|
|
24
|
+
|
|
25
|
+
if (checkGpp()) {
|
|
26
|
+
console.log(`${COLORS.green}✔ g++ found.${COLORS.reset}`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log(`${COLORS.yellow}⚠ g++ (GCC) not found in PATH. JSPP requires a C++23 compatible compiler.${COLORS.reset}`);
|
|
31
|
+
|
|
32
|
+
const os = platform();
|
|
33
|
+
|
|
34
|
+
if (os === "win32") {
|
|
35
|
+
console.log(`\n${COLORS.bold}To install GCC on Windows:${COLORS.reset}`);
|
|
36
|
+
console.log(`1. Install MinGW-w64 via MSYS2: ${COLORS.cyan}https://www.msys2.org/${COLORS.reset}`);
|
|
37
|
+
console.log(`2. Or use winget: ${COLORS.cyan}winget install MSYS2.MSYS2${COLORS.reset}`);
|
|
38
|
+
console.log(` Then run: ${COLORS.bold}pacman -S mingw-w64-x86_64-gcc${COLORS.reset}`);
|
|
39
|
+
} else if (os === "linux") {
|
|
40
|
+
console.log(`\n${COLORS.bold}To install GCC on Linux (Ubuntu/Debian):${COLORS.reset}`);
|
|
41
|
+
console.log(`${COLORS.cyan}sudo apt update && sudo apt install g++-14 -y${COLORS.reset}`);
|
|
42
|
+
console.log(`\nAttempting to install now (may require password)...`);
|
|
43
|
+
|
|
44
|
+
// Try to install automatically on Linux if apt is found
|
|
45
|
+
try {
|
|
46
|
+
const install = spawnSync("sudo", ["apt-get", "install", "-y", "g++-14"], { stdio: "inherit" });
|
|
47
|
+
if (install.status === 0) {
|
|
48
|
+
console.log(`${COLORS.green}✔ g++-14 installed successfully.${COLORS.reset}`);
|
|
49
|
+
// Try to set up symlink if needed or just inform user
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error(`${COLORS.red}Automatic installation failed. Please install manually.${COLORS.reset}`);
|
|
54
|
+
}
|
|
55
|
+
} else if (os === "darwin") {
|
|
56
|
+
console.log(`\n${COLORS.bold}To install GCC on macOS:${COLORS.reset}`);
|
|
57
|
+
console.log(`${COLORS.cyan}brew install gcc${COLORS.reset}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(`\n${COLORS.bold}After installation, please ensure 'g++' is in your PATH and restart your terminal.${COLORS.reset}\n`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
setup();
|