pro-cpp-cli-core 1.0.3 ā 1.0.4
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/index.js +85 -112
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* PRO C++ CLI Core (With C++20 Modules Topological Sorter)
|
|
5
|
+
* FIX: Kept .ifc files alive for IntelliSense!
|
|
6
|
+
*/
|
|
7
|
+
|
|
3
8
|
const { execSync, spawn } = require('child_process');
|
|
4
9
|
const fs = require('fs');
|
|
5
10
|
const path = require('path');
|
|
6
11
|
|
|
7
12
|
const [,, command, ...args] = process.argv;
|
|
8
|
-
|
|
9
13
|
let currentAppProcess = null;
|
|
10
14
|
let watchTimeout = null;
|
|
11
15
|
|
|
12
|
-
// Helper: Safely execute synchronous shell commands
|
|
13
16
|
function runSyncCommand(cmd) {
|
|
14
17
|
try {
|
|
15
18
|
execSync(cmd, { stdio: 'inherit' });
|
|
@@ -19,44 +22,79 @@ function runSyncCommand(cmd) {
|
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
// Helper: Clean up old build files to save disk space
|
|
23
25
|
function cleanupOldBuilds() {
|
|
24
26
|
const files = fs.readdirSync(process.cwd());
|
|
25
27
|
files.forEach(file => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} catch (err) {
|
|
30
|
-
// Ignore errors: file might be locked by OS or Antivirus. We will try next time!
|
|
31
|
-
}
|
|
28
|
+
// PRO FIX: Removed .ifc from deletion list. IntelliSense needs them to resolve imports!
|
|
29
|
+
const isArtifact = file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || (file.startsWith('app_build_') && file.endsWith('.exe'));
|
|
30
|
+
if (isArtifact) {
|
|
31
|
+
try { fs.unlinkSync(path.join(process.cwd(), file)); } catch (err) {}
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
function getSortedCppFiles() {
|
|
37
|
+
const fileList = [];
|
|
38
|
+
|
|
39
|
+
function scanDir(dir) {
|
|
40
|
+
const files = fs.readdirSync(dir);
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
const filePath = path.join(dir, file);
|
|
43
|
+
if (fs.statSync(filePath).isDirectory()) {
|
|
44
|
+
if (file !== 'node_modules' && file !== '.vscode' && file !== 'build') {
|
|
45
|
+
scanDir(filePath);
|
|
46
|
+
}
|
|
47
|
+
} else if (filePath.endsWith('.cpp') || filePath.endsWith('.ixx')) {
|
|
48
|
+
fileList.push(filePath);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
scanDir(process.cwd());
|
|
53
|
+
|
|
54
|
+
const fileData = fileList.map(file => {
|
|
55
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
56
|
+
const exportsMatch = content.match(/export\s+module\s+([a-zA-Z0-9_]+)\s*;/);
|
|
57
|
+
const importsMatches = [...content.matchAll(/import\s+([a-zA-Z0-9_]+)\s*;/g)].map(m => m[1]);
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
file,
|
|
61
|
+
exports: exportsMatch ? exportsMatch[1] : null,
|
|
62
|
+
imports: importsMatches
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const sortedFiles = [];
|
|
67
|
+
const visited = new Set();
|
|
68
|
+
const processing = new Set();
|
|
69
|
+
|
|
70
|
+
function visit(node) {
|
|
71
|
+
if (visited.has(node.file)) return;
|
|
72
|
+
if (processing.has(node.file)) return;
|
|
73
|
+
processing.add(node.file);
|
|
74
|
+
|
|
75
|
+
node.imports.forEach(imp => {
|
|
76
|
+
const dep = fileData.find(f => f.exports === imp);
|
|
77
|
+
if (dep) visit(dep);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
processing.delete(node.file);
|
|
81
|
+
visited.add(node.file);
|
|
82
|
+
sortedFiles.push(`"${node.file}"`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
fileData.forEach(visit);
|
|
86
|
+
return sortedFiles.join(' ');
|
|
40
87
|
}
|
|
41
88
|
|
|
42
|
-
// Command: procpp init
|
|
43
89
|
function initProject() {
|
|
44
|
-
console.log("š Initializing PRO C++ Project
|
|
45
|
-
|
|
90
|
+
console.log("š Initializing PRO C++ Project (C++20 Modules)...");
|
|
46
91
|
const vscodeDir = path.join(process.cwd(), '.vscode');
|
|
47
|
-
if (!fs.existsSync(vscodeDir))
|
|
48
|
-
fs.mkdirSync(vscodeDir);
|
|
49
|
-
}
|
|
92
|
+
if (!fs.existsSync(vscodeDir)) fs.mkdirSync(vscodeDir);
|
|
50
93
|
|
|
51
94
|
const mainCppPath = path.join(process.cwd(), 'main.cpp');
|
|
52
|
-
const mainCppContent =
|
|
95
|
+
const mainCppContent = `import std.core;\n// C++20 Modules ready!\nint main() { return 0; }`;
|
|
96
|
+
if (!fs.existsSync(mainCppPath)) fs.writeFileSync(mainCppPath, mainCppContent);
|
|
53
97
|
|
|
54
|
-
if (!fs.existsSync(mainCppPath)) {
|
|
55
|
-
fs.writeFileSync(mainCppPath, mainCppContent);
|
|
56
|
-
console.log("ā
Created main.cpp");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Generate tasks.json with C++20
|
|
60
98
|
const tasksContent = {
|
|
61
99
|
"version": "2.0.0",
|
|
62
100
|
"tasks": [
|
|
@@ -64,126 +102,61 @@ function initProject() {
|
|
|
64
102
|
"type": "cppbuild",
|
|
65
103
|
"label": "DEBUG-BUILD-MSVC",
|
|
66
104
|
"command": "cl.exe",
|
|
67
|
-
"args": [
|
|
68
|
-
"/std:c++20", "/Zi", "/EHsc", "/nologo",
|
|
69
|
-
"/Fe${fileDirname}\\debug_build_999.exe",
|
|
70
|
-
"${file}"
|
|
71
|
-
],
|
|
72
|
-
"options": { "cwd": "${fileDirname}" },
|
|
105
|
+
"args": ["/std:c++20", "/Zi", "/EHsc", "/nologo", "/Fe${fileDirname}\\debug_build.exe", "${file}"],
|
|
73
106
|
"problemMatcher": ["$msCompile"],
|
|
74
107
|
"group": "build"
|
|
75
108
|
}
|
|
76
109
|
]
|
|
77
110
|
};
|
|
78
111
|
fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(tasksContent, null, 4));
|
|
79
|
-
|
|
80
|
-
// Generate launch.json for bulletproof debugging
|
|
81
|
-
const launchContent = {
|
|
82
|
-
"version": "0.2.0",
|
|
83
|
-
"configurations": [
|
|
84
|
-
{
|
|
85
|
-
"name": "āļø PRO C++ Debug",
|
|
86
|
-
"type": "cppvsdbg",
|
|
87
|
-
"request": "launch",
|
|
88
|
-
"program": "${fileDirname}\\debug_build_999.exe",
|
|
89
|
-
"args": [],
|
|
90
|
-
"stopAtEntry": false,
|
|
91
|
-
"cwd": "${fileDirname}",
|
|
92
|
-
"environment": [],
|
|
93
|
-
"console": "integratedTerminal",
|
|
94
|
-
"preLaunchTask": "DEBUG-BUILD-MSVC"
|
|
95
|
-
}
|
|
96
|
-
]
|
|
97
|
-
};
|
|
98
|
-
fs.writeFileSync(path.join(vscodeDir, 'launch.json'), JSON.stringify(launchContent, null, 4));
|
|
99
|
-
|
|
100
|
-
console.log("ā
Created .vscode debugger configs (C++20 & F5 ready!)");
|
|
101
|
-
console.log("šÆ Project initialized! Run 'procpp watch' to start developing.");
|
|
112
|
+
console.log("ā
Ready! Standard set to C++20.");
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const cppFiles = getCppFiles();
|
|
107
|
-
|
|
115
|
+
function buildAndRun() {
|
|
116
|
+
const cppFiles = getSortedCppFiles();
|
|
108
117
|
if (!cppFiles) {
|
|
109
|
-
console.error("ā No .cpp files found
|
|
118
|
+
console.error("ā Error: No .cpp or .ixx files found!");
|
|
110
119
|
return;
|
|
111
120
|
}
|
|
112
121
|
|
|
113
|
-
|
|
114
|
-
if (currentAppProcess) {
|
|
115
|
-
currentAppProcess.kill();
|
|
116
|
-
currentAppProcess = null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// 2. Background cleanup of unlocked old files
|
|
122
|
+
if (currentAppProcess) currentAppProcess.kill();
|
|
120
123
|
cleanupOldBuilds();
|
|
121
124
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const outputExe = `app_build_${timestamp}.exe`;
|
|
125
|
+
const outputExe = `app_build_${Date.now()}.exe`;
|
|
126
|
+
console.log(`\nšØ Compiling with SMART DEPENDENCY GRAPH...`);
|
|
125
127
|
|
|
126
|
-
console.log(`\nšØ Compiling (Standard: C++20)...`);
|
|
127
128
|
const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${outputExe}"`;
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (success) {
|
|
130
|
+
if (runSyncCommand(compileCmd)) {
|
|
132
131
|
console.log(`š¢ RUNNING -> ${outputExe}\n` + "-".repeat(40));
|
|
133
|
-
|
|
134
|
-
// 4. Run the new executable asynchronously so Node.js can keep watching
|
|
135
132
|
currentAppProcess = spawn(`.\\${outputExe}`, [], { shell: true, stdio: 'inherit' });
|
|
136
|
-
|
|
137
133
|
currentAppProcess.on('close', (code) => {
|
|
138
|
-
if (code !== null) {
|
|
139
|
-
console.log("-".repeat(40) + `\nš Process exited with code ${code}`);
|
|
140
|
-
}
|
|
134
|
+
if (code !== null) console.log("-".repeat(40) + `\nš Process exited with code ${code}`);
|
|
141
135
|
});
|
|
142
136
|
} else {
|
|
143
137
|
console.log(`\nā BUILD FAILED`);
|
|
144
138
|
}
|
|
145
139
|
}
|
|
146
140
|
|
|
147
|
-
// Command: procpp watch
|
|
148
141
|
function watchProject() {
|
|
149
|
-
console.log("š PRO C++ Watcher Started (C++20
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Initial build
|
|
153
|
-
buildAndRun(true);
|
|
142
|
+
console.log("š PRO C++ Watcher Started (Mode: Smart C++20 Modules)");
|
|
143
|
+
buildAndRun();
|
|
154
144
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (filename && (filename.endsWith('.cpp') || filename.endsWith('.h'))) {
|
|
158
|
-
// Debounce to prevent multiple rapid triggers when saving
|
|
145
|
+
fs.watch(process.cwd(), { recursive: true }, (eventType, filename) => {
|
|
146
|
+
if (filename && (filename.endsWith('.cpp') || filename.endsWith('.ixx') || filename.endsWith('.h'))) {
|
|
159
147
|
clearTimeout(watchTimeout);
|
|
160
148
|
watchTimeout = setTimeout(() => {
|
|
161
149
|
console.clear();
|
|
162
|
-
console.log(`[${new Date().toLocaleTimeString()}] Change detected
|
|
163
|
-
buildAndRun(
|
|
164
|
-
}, 300);
|
|
150
|
+
console.log(`[${new Date().toLocaleTimeString()}] Change detected: ${filename}`);
|
|
151
|
+
buildAndRun();
|
|
152
|
+
}, 300);
|
|
165
153
|
}
|
|
166
154
|
});
|
|
167
155
|
}
|
|
168
156
|
|
|
169
|
-
// CLI Router
|
|
170
157
|
switch (command) {
|
|
171
|
-
case 'init':
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
buildAndRun(false);
|
|
176
|
-
break;
|
|
177
|
-
case 'watch':
|
|
178
|
-
watchProject();
|
|
179
|
-
break;
|
|
180
|
-
default:
|
|
181
|
-
console.log(`
|
|
182
|
-
š ļø PRO CPP CLI š ļø
|
|
183
|
-
Usage:
|
|
184
|
-
procpp init - Scaffold C++ project & VS Code debugger configs
|
|
185
|
-
procpp run - Compile and run all .cpp files once
|
|
186
|
-
procpp watch - Live reload! Auto-compile and run on file save
|
|
187
|
-
`);
|
|
188
|
-
break;
|
|
158
|
+
case 'init': initProject(); break;
|
|
159
|
+
case 'run': buildAndRun(); break;
|
|
160
|
+
case 'watch': watchProject(); break;
|
|
161
|
+
default: console.log("š ļø PRO CPP CLI\nUsage: procpp <init|run|watch>"); break;
|
|
189
162
|
}
|