pro-cpp-cli-core 1.0.3 → 1.0.5
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 +150 -121
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* PRO C++ CLI Core (With C++20 Modules Topological Sorter)
|
|
5
|
+
* FIX: Restored initProject!
|
|
6
|
+
* FIX: Smart post-build artifact routing to .build/ directory!
|
|
7
|
+
*/
|
|
8
|
+
|
|
3
9
|
const { execSync, spawn } = require('child_process');
|
|
4
10
|
const fs = require('fs');
|
|
5
11
|
const path = require('path');
|
|
6
12
|
|
|
7
13
|
const [,, command, ...args] = process.argv;
|
|
8
|
-
|
|
9
14
|
let currentAppProcess = null;
|
|
10
15
|
let watchTimeout = null;
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
const BUILD_DIR = path.join(process.cwd(), '.build');
|
|
18
|
+
|
|
13
19
|
function runSyncCommand(cmd) {
|
|
14
20
|
try {
|
|
15
21
|
execSync(cmd, { stdio: 'inherit' });
|
|
@@ -19,171 +25,194 @@ function runSyncCommand(cmd) {
|
|
|
19
25
|
}
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
// Helper: Clean up old build files to save disk space
|
|
23
28
|
function cleanupOldBuilds() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// Ignore errors: file might be locked by OS or Antivirus. We will try next time!
|
|
29
|
+
// 1. Clean .build folder
|
|
30
|
+
if (fs.existsSync(BUILD_DIR)) {
|
|
31
|
+
const files = fs.readdirSync(BUILD_DIR);
|
|
32
|
+
files.forEach(file => {
|
|
33
|
+
if (file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || file.endsWith('.ifc') || file.startsWith('app_build_')) {
|
|
34
|
+
try { fs.unlinkSync(path.join(BUILD_DIR, file)); } catch (err) {}
|
|
31
35
|
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
// 2. Clean root folder (just in case)
|
|
39
|
+
const rootFiles = fs.readdirSync(process.cwd());
|
|
40
|
+
rootFiles.forEach(file => {
|
|
41
|
+
if (file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || file.endsWith('.ifc') || (file.startsWith('app_build_') && file.endsWith('.exe'))) {
|
|
42
|
+
try { fs.unlinkSync(path.join(process.cwd(), file)); } catch (err) {}
|
|
32
43
|
}
|
|
33
44
|
});
|
|
34
45
|
}
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const files = fs.readdirSync(process.cwd());
|
|
39
|
-
return files.filter(file => file.endsWith('.cpp')).join(' ');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Command: procpp init
|
|
43
|
-
function initProject() {
|
|
44
|
-
console.log("🚀 Initializing PRO C++ Project with C++20....");
|
|
47
|
+
function getSortedCppFiles() {
|
|
48
|
+
const fileList = [];
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
function scanDir(dir) {
|
|
51
|
+
const files = fs.readdirSync(dir);
|
|
52
|
+
for (const file of files) {
|
|
53
|
+
const filePath = path.join(dir, file);
|
|
54
|
+
if (fs.statSync(filePath).isDirectory()) {
|
|
55
|
+
// ИГНОРИРУЕМ ПАПКУ .build, ЧТОБЫ ВОЧЕР НЕ СОШЕЛ С УМА
|
|
56
|
+
if (file !== 'node_modules' && file !== '.vscode' && file !== '.build') {
|
|
57
|
+
scanDir(filePath);
|
|
58
|
+
}
|
|
59
|
+
} else if (filePath.endsWith('.cpp') || filePath.endsWith('.ixx')) {
|
|
60
|
+
fileList.push(filePath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
49
63
|
}
|
|
64
|
+
scanDir(process.cwd());
|
|
50
65
|
|
|
51
|
-
const
|
|
52
|
-
|
|
66
|
+
const fileData = fileList.map(file => {
|
|
67
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
68
|
+
const exportsMatch = content.match(/export\s+module\s+([a-zA-Z0-9_]+)\s*;/);
|
|
69
|
+
const importsMatches = [...content.matchAll(/import\s+([a-zA-Z0-9_]+)\s*;/g)].map(m => m[1]);
|
|
70
|
+
|
|
71
|
+
return { file, exports: exportsMatch ? exportsMatch[1] : null, imports: importsMatches };
|
|
72
|
+
});
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
const sortedFiles = [];
|
|
75
|
+
const visited = new Set();
|
|
76
|
+
const processing = new Set();
|
|
77
|
+
|
|
78
|
+
function visit(node) {
|
|
79
|
+
if (visited.has(node.file)) return;
|
|
80
|
+
if (processing.has(node.file)) return;
|
|
81
|
+
processing.add(node.file);
|
|
82
|
+
|
|
83
|
+
node.imports.forEach(imp => {
|
|
84
|
+
const dep = fileData.find(f => f.exports === imp);
|
|
85
|
+
if (dep) visit(dep);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
processing.delete(node.file);
|
|
89
|
+
visited.add(node.file);
|
|
90
|
+
sortedFiles.push(`"${node.file}"`);
|
|
57
91
|
}
|
|
58
92
|
|
|
59
|
-
|
|
93
|
+
fileData.forEach(visit);
|
|
94
|
+
return sortedFiles.join(' ');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function initProject() {
|
|
98
|
+
console.log("🚀 Initializing PRO C++ Project (C++20 Modules)...");
|
|
99
|
+
const vscodeDir = path.join(process.cwd(), '.vscode');
|
|
100
|
+
if (!fs.existsSync(vscodeDir)) fs.mkdirSync(vscodeDir);
|
|
101
|
+
|
|
102
|
+
// 1. tasks.json
|
|
60
103
|
const tasksContent = {
|
|
61
104
|
"version": "2.0.0",
|
|
62
|
-
"tasks": [
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"${file}"
|
|
71
|
-
],
|
|
72
|
-
"options": { "cwd": "${fileDirname}" },
|
|
73
|
-
"problemMatcher": ["$msCompile"],
|
|
74
|
-
"group": "build"
|
|
75
|
-
}
|
|
76
|
-
]
|
|
105
|
+
"tasks": [{
|
|
106
|
+
"type": "cppbuild",
|
|
107
|
+
"label": "DEBUG-BUILD-MSVC",
|
|
108
|
+
"command": "cl.exe",
|
|
109
|
+
"args": ["/std:c++20", "/Zi", "/EHsc", "/nologo", "/Fe${fileDirname}\\.build\\debug_build.exe", "${file}"],
|
|
110
|
+
"problemMatcher": ["$msCompile"],
|
|
111
|
+
"group": "build"
|
|
112
|
+
}]
|
|
77
113
|
};
|
|
78
114
|
fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(tasksContent, null, 4));
|
|
79
115
|
|
|
80
|
-
//
|
|
81
|
-
const
|
|
82
|
-
"
|
|
83
|
-
|
|
84
|
-
{
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
116
|
+
// 2. c_cpp_properties.json (FIX FOR IDE SQUIGGLES!)
|
|
117
|
+
const propertiesContent = {
|
|
118
|
+
"configurations": [{
|
|
119
|
+
"name": "Win32",
|
|
120
|
+
"includePath": ["${workspaceFolder}/**"],
|
|
121
|
+
"compilerPath": "cl.exe",
|
|
122
|
+
"cStandard": "c17",
|
|
123
|
+
"cppStandard": "c++20",
|
|
124
|
+
"intelliSenseMode": "windows-msvc-x64",
|
|
125
|
+
"compilerArgs": [
|
|
126
|
+
"/std:c++20",
|
|
127
|
+
"/experimental:module",
|
|
128
|
+
"/ifcSearchDir", // Указываем IDE, где искать .ifc файлы!
|
|
129
|
+
"${workspaceFolder}/.build"
|
|
130
|
+
]
|
|
131
|
+
}],
|
|
132
|
+
"version": 4
|
|
133
|
+
};
|
|
134
|
+
fs.writeFileSync(path.join(vscodeDir, 'c_cpp_properties.json'), JSON.stringify(propertiesContent, null, 4));
|
|
135
|
+
|
|
136
|
+
// 3. settings.json (Hide .build folder from UI)
|
|
137
|
+
const settingsContent = {
|
|
138
|
+
"files.exclude": {
|
|
139
|
+
".build": true,
|
|
140
|
+
"**/.build": true
|
|
141
|
+
},
|
|
142
|
+
"C_Cpp.errorSquiggles": "disabled"
|
|
97
143
|
};
|
|
98
|
-
fs.writeFileSync(path.join(vscodeDir, '
|
|
144
|
+
fs.writeFileSync(path.join(vscodeDir, 'settings.json'), JSON.stringify(settingsContent, null, 4));
|
|
99
145
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
146
|
+
// 4. main.cpp template
|
|
147
|
+
const mainCppPath = path.join(process.cwd(), 'main.cpp');
|
|
148
|
+
if (!fs.existsSync(mainCppPath)) {
|
|
149
|
+
fs.writeFileSync(mainCppPath, `import std.core;\n// C++20 Modules ready!\nint main() { return 0; }`);
|
|
150
|
+
}
|
|
103
151
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const cppFiles = getCppFiles();
|
|
152
|
+
console.log("✅ Ready! .vscode configs created. IntelliSense is pointed to .build/");
|
|
153
|
+
}
|
|
107
154
|
|
|
155
|
+
function buildAndRun() {
|
|
156
|
+
const cppFiles = getSortedCppFiles();
|
|
108
157
|
if (!cppFiles) {
|
|
109
|
-
console.error("❌ No .cpp files found
|
|
158
|
+
console.error("❌ Error: No .cpp or .ixx files found!");
|
|
110
159
|
return;
|
|
111
160
|
}
|
|
112
161
|
|
|
113
|
-
|
|
114
|
-
if (currentAppProcess) {
|
|
115
|
-
currentAppProcess.kill();
|
|
116
|
-
currentAppProcess = null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// 2. Background cleanup of unlocked old files
|
|
162
|
+
if (currentAppProcess) currentAppProcess.kill();
|
|
120
163
|
cleanupOldBuilds();
|
|
164
|
+
if (!fs.existsSync(BUILD_DIR)) fs.mkdirSync(BUILD_DIR);
|
|
121
165
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
166
|
+
const outputExeName = `app_build_${Date.now()}.exe`;
|
|
167
|
+
|
|
168
|
+
console.log(`\n🔨 Compiling with SMART DEPENDENCY GRAPH...`);
|
|
125
169
|
|
|
126
|
-
|
|
127
|
-
const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${
|
|
170
|
+
// Компилируем чисто, без странных флагов
|
|
171
|
+
const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${outputExeName}"`;
|
|
128
172
|
|
|
129
|
-
|
|
173
|
+
if (runSyncCommand(compileCmd)) {
|
|
174
|
+
// МАГИЯ ПЕРЕНОСА: Двигаем все созданные файлы в папку .build
|
|
175
|
+
const files = fs.readdirSync(process.cwd());
|
|
176
|
+
files.forEach(file => {
|
|
177
|
+
if (file.endsWith('.obj') || file.endsWith('.ifc') || file.endsWith('.pdb') || file.endsWith('.ilk') || file === outputExeName) {
|
|
178
|
+
try {
|
|
179
|
+
fs.renameSync(path.join(process.cwd(), file), path.join(BUILD_DIR, file));
|
|
180
|
+
} catch(e) {}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
130
183
|
|
|
131
|
-
|
|
132
|
-
console.log(`🟢 RUNNING -> ${outputExe}\n` + "-".repeat(40));
|
|
133
|
-
|
|
134
|
-
// 4. Run the new executable asynchronously so Node.js can keep watching
|
|
135
|
-
currentAppProcess = spawn(`.\\${outputExe}`, [], { shell: true, stdio: 'inherit' });
|
|
184
|
+
console.log(`🟢 RUNNING -> .build\\${outputExeName}\n` + "-".repeat(40));
|
|
136
185
|
|
|
186
|
+
// Запускаем из папки .build
|
|
187
|
+
currentAppProcess = spawn(`.\\.build\\${outputExeName}`, [], { shell: true, stdio: 'inherit' });
|
|
137
188
|
currentAppProcess.on('close', (code) => {
|
|
138
|
-
if (code !== null) {
|
|
139
|
-
console.log("-".repeat(40) + `\n🛑 Process exited with code ${code}`);
|
|
140
|
-
}
|
|
189
|
+
if (code !== null) console.log("-".repeat(40) + `\n🛑 Process exited with code ${code}`);
|
|
141
190
|
});
|
|
142
191
|
} else {
|
|
143
192
|
console.log(`\n❌ BUILD FAILED`);
|
|
144
193
|
}
|
|
145
194
|
}
|
|
146
195
|
|
|
147
|
-
// Command: procpp watch
|
|
148
196
|
function watchProject() {
|
|
149
|
-
console.log("👀 PRO C++ Watcher Started (C++20
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Initial build
|
|
153
|
-
buildAndRun(true);
|
|
197
|
+
console.log("👀 PRO C++ Watcher Started (Mode: Smart C++20 Modules)");
|
|
198
|
+
buildAndRun();
|
|
154
199
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (filename && (filename.endsWith('.cpp') || filename.endsWith('.h'))) {
|
|
158
|
-
// Debounce to prevent multiple rapid triggers when saving
|
|
200
|
+
fs.watch(process.cwd(), { recursive: true }, (eventType, filename) => {
|
|
201
|
+
// Игнорируем всё, что происходит внутри папки .build
|
|
202
|
+
if (filename && (filename.endsWith('.cpp') || filename.endsWith('.ixx') || filename.endsWith('.h')) && !filename.includes('.build')) {
|
|
159
203
|
clearTimeout(watchTimeout);
|
|
160
204
|
watchTimeout = setTimeout(() => {
|
|
161
205
|
console.clear();
|
|
162
|
-
console.log(`[${new Date().toLocaleTimeString()}] Change detected
|
|
163
|
-
buildAndRun(
|
|
164
|
-
}, 300);
|
|
206
|
+
console.log(`[${new Date().toLocaleTimeString()}] Change detected: ${filename}`);
|
|
207
|
+
buildAndRun();
|
|
208
|
+
}, 300);
|
|
165
209
|
}
|
|
166
210
|
});
|
|
167
211
|
}
|
|
168
212
|
|
|
169
|
-
// CLI Router
|
|
170
213
|
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;
|
|
214
|
+
case 'init': initProject(); break;
|
|
215
|
+
case 'run': buildAndRun(); break;
|
|
216
|
+
case 'watch': watchProject(); break;
|
|
217
|
+
default: console.log("🛠️ PRO CPP CLI\nUsage: procpp <init|run|watch>"); break;
|
|
189
218
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pro-cpp-cli-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/anton-po-github/pro-cpp-cli-core.git"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"description": "The ultimate C++ Developer Experience for Windows",
|
|
13
13
|
"main": "index.js",
|
|
14
14
|
"bin": {
|
|
15
|
-
"procpp": "
|
|
15
|
+
"procpp": "index.js"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"start": "node index.js"
|
|
@@ -26,4 +26,4 @@
|
|
|
26
26
|
],
|
|
27
27
|
"author": "PRO Developer",
|
|
28
28
|
"license": "MIT"
|
|
29
|
-
}
|
|
29
|
+
}
|