plusui-native 0.2.68 → 0.2.70
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 +4 -4
- package/src/doctor/detectors/compiler.js +16 -20
- package/src/index.js +135 -62
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plusui-native",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.70",
|
|
4
4
|
"description": "PlusUI CLI - Build C++ desktop apps modern UI ",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"semver": "^7.6.0",
|
|
28
28
|
"which": "^4.0.0",
|
|
29
29
|
"execa": "^8.0.1",
|
|
30
|
-
"plusui-native-builder": "^0.1.
|
|
31
|
-
"plusui-native-connect": "^0.1.
|
|
30
|
+
"plusui-native-builder": "^0.1.69",
|
|
31
|
+
"plusui-native-connect": "^0.1.69"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"plusui-native-connect": "^0.1.
|
|
34
|
+
"plusui-native-connect": "^0.1.69"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
@@ -19,25 +19,21 @@ async function detectMSVC() {
|
|
|
19
19
|
const vswherePath = 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe';
|
|
20
20
|
|
|
21
21
|
if (!existsSync(vswherePath)) {
|
|
22
|
-
// Fallback: check common VS paths
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
name: version,
|
|
38
|
-
path: vsPath,
|
|
39
|
-
valid: true
|
|
40
|
-
};
|
|
22
|
+
// Fallback: check common VS paths for years 2019–2026
|
|
23
|
+
const vsYears = ['2026', '2025', '2024', '2023', '2022', '2019'];
|
|
24
|
+
const vsEditions = ['Community', 'Professional', 'Enterprise', 'BuildTools'];
|
|
25
|
+
|
|
26
|
+
for (const year of vsYears) {
|
|
27
|
+
for (const edition of vsEditions) {
|
|
28
|
+
const vsPath = `C:\\Program Files\\Microsoft Visual Studio\\${year}\\${edition}\\VC\\Tools\\MSVC`;
|
|
29
|
+
if (existsSync(vsPath)) {
|
|
30
|
+
return {
|
|
31
|
+
found: true,
|
|
32
|
+
name: `Visual Studio ${year} ${edition}`,
|
|
33
|
+
path: vsPath,
|
|
34
|
+
valid: true
|
|
35
|
+
};
|
|
36
|
+
}
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
39
|
|
|
@@ -95,7 +91,7 @@ async function detectXcode() {
|
|
|
95
91
|
|
|
96
92
|
// Parse clang version
|
|
97
93
|
const versionMatch = clangResult.output.match(/clang version (\d+\.\d+\.\d+)/i) ||
|
|
98
|
-
|
|
94
|
+
clangResult.output.match(/Apple clang version (\d+\.\d+\.\d+)/i);
|
|
99
95
|
const version = versionMatch ? versionMatch[1] : 'unknown';
|
|
100
96
|
|
|
101
97
|
return {
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { mkdir, readFile, stat, rm, readdir, writeFile, copyFile } from 'fs/promises';
|
|
4
4
|
import { existsSync, watch, statSync, mkdirSync } from 'fs';
|
|
@@ -74,23 +74,38 @@ function checkTools() {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// Compiler / build tools check
|
|
77
78
|
if (platform === 'win32') {
|
|
78
|
-
|
|
79
|
-
'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC',
|
|
80
|
-
'C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC',
|
|
81
|
-
'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC'
|
|
82
|
-
];
|
|
83
|
-
|
|
79
|
+
// Use vswhere.exe first (same detection as `plusui doctor`)
|
|
84
80
|
let vsFound = false;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
const vswherePath = 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe';
|
|
82
|
+
if (existsSync(vswherePath)) {
|
|
83
|
+
try {
|
|
84
|
+
const output = execSync(
|
|
85
|
+
`"${vswherePath}" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`,
|
|
86
|
+
{ stdio: ['pipe', 'pipe', 'pipe'], encoding: 'utf8', timeout: 10000 }
|
|
87
|
+
).trim();
|
|
88
|
+
if (output) vsFound = true;
|
|
89
|
+
} catch { }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Fallback: check common VS paths for years 2019–2026
|
|
93
|
+
if (!vsFound) {
|
|
94
|
+
const vsYears = ['2026', '2025', '2024', '2023', '2022', '2019'];
|
|
95
|
+
const vsEditions = ['Community', 'Professional', 'Enterprise', 'BuildTools'];
|
|
96
|
+
for (const year of vsYears) {
|
|
97
|
+
for (const edition of vsEditions) {
|
|
98
|
+
if (existsSync(`C:\\Program Files\\Microsoft Visual Studio\\${year}\\${edition}\\VC\\Tools\\MSVC`)) {
|
|
99
|
+
vsFound = true;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (vsFound) break;
|
|
89
104
|
}
|
|
90
105
|
}
|
|
91
106
|
|
|
92
107
|
if (!vsFound) {
|
|
93
|
-
required.push({ name: 'Visual Studio
|
|
108
|
+
required.push({ name: 'Visual Studio (C++ workload)', install: 'Download from visualstudio.microsoft.com with C++ workload', auto: null });
|
|
94
109
|
}
|
|
95
110
|
} else if (platform === 'darwin') {
|
|
96
111
|
try {
|
|
@@ -196,16 +211,64 @@ function getCMakePath() {
|
|
|
196
211
|
return 'cmake';
|
|
197
212
|
}
|
|
198
213
|
|
|
214
|
+
// Find vcvarsall.bat for Windows builds (needed for Ninja generator)
|
|
215
|
+
let _vcvarsallCache = undefined;
|
|
216
|
+
function findVcvarsall() {
|
|
217
|
+
if (_vcvarsallCache !== undefined) return _vcvarsallCache;
|
|
218
|
+
|
|
219
|
+
const vswherePath = 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe';
|
|
220
|
+
if (existsSync(vswherePath)) {
|
|
221
|
+
try {
|
|
222
|
+
const installPath = execSync(
|
|
223
|
+
`"${vswherePath}" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`,
|
|
224
|
+
{ stdio: ['pipe', 'pipe', 'pipe'], encoding: 'utf8', timeout: 10000 }
|
|
225
|
+
).trim();
|
|
226
|
+
if (installPath) {
|
|
227
|
+
const vcvars = join(installPath, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat');
|
|
228
|
+
if (existsSync(vcvars)) {
|
|
229
|
+
_vcvarsallCache = vcvars;
|
|
230
|
+
return vcvars;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
} catch { }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Fallback: scan known paths
|
|
237
|
+
const vsYears = ['2026', '2025', '2024', '2023', '2022', '2019'];
|
|
238
|
+
const vsEditions = ['Community', 'Professional', 'Enterprise', 'BuildTools'];
|
|
239
|
+
for (const year of vsYears) {
|
|
240
|
+
for (const edition of vsEditions) {
|
|
241
|
+
const vcvars = `C:\\Program Files\\Microsoft Visual Studio\\${year}\\${edition}\\VC\\Auxiliary\\Build\\vcvarsall.bat`;
|
|
242
|
+
if (existsSync(vcvars)) {
|
|
243
|
+
_vcvarsallCache = vcvars;
|
|
244
|
+
return vcvars;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
_vcvarsallCache = null;
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
199
253
|
function runCMake(args, options = {}) {
|
|
200
254
|
const cmake = getCMakePath();
|
|
255
|
+
|
|
256
|
+
// On Windows, wrap cmake in vcvarsall to ensure cl.exe is in PATH (needed for Ninja)
|
|
257
|
+
if (process.platform === 'win32') {
|
|
258
|
+
const vcvarsall = findVcvarsall();
|
|
259
|
+
if (vcvarsall) {
|
|
260
|
+
return execSync(`cmd /c ""${vcvarsall}" x64 >nul 2>&1 && "${cmake}" ${args}"`, { stdio: 'inherit', shell: true, ...options });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
201
264
|
return execSync(`"${cmake}" ${args}`, { stdio: 'inherit', ...options });
|
|
202
265
|
}
|
|
203
266
|
|
|
204
267
|
function getInstalledPackageVersion(packageName) {
|
|
205
268
|
try {
|
|
206
|
-
const result = execSync(`npm list ${packageName} --depth=0 --json`, {
|
|
207
|
-
encoding: 'utf8',
|
|
208
|
-
stdio: ['pipe', 'pipe', 'ignore']
|
|
269
|
+
const result = execSync(`npm list ${packageName} --depth=0 --json`, {
|
|
270
|
+
encoding: 'utf8',
|
|
271
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
209
272
|
});
|
|
210
273
|
const json = JSON.parse(result);
|
|
211
274
|
if (json.dependencies && json.dependencies[packageName]) {
|
|
@@ -214,12 +277,12 @@ function getInstalledPackageVersion(packageName) {
|
|
|
214
277
|
} catch {
|
|
215
278
|
// Package not installed locally
|
|
216
279
|
}
|
|
217
|
-
|
|
280
|
+
|
|
218
281
|
// Try global installation
|
|
219
282
|
try {
|
|
220
|
-
const result = execSync(`npm list -g ${packageName} --depth=0 --json`, {
|
|
221
|
-
encoding: 'utf8',
|
|
222
|
-
stdio: ['pipe', 'pipe', 'ignore']
|
|
283
|
+
const result = execSync(`npm list -g ${packageName} --depth=0 --json`, {
|
|
284
|
+
encoding: 'utf8',
|
|
285
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
223
286
|
});
|
|
224
287
|
const json = JSON.parse(result);
|
|
225
288
|
if (json.dependencies && json.dependencies[packageName]) {
|
|
@@ -228,15 +291,15 @@ function getInstalledPackageVersion(packageName) {
|
|
|
228
291
|
} catch {
|
|
229
292
|
return null;
|
|
230
293
|
}
|
|
231
|
-
|
|
294
|
+
|
|
232
295
|
return null;
|
|
233
296
|
}
|
|
234
297
|
|
|
235
298
|
function getLatestPackageVersion(packageName) {
|
|
236
299
|
try {
|
|
237
|
-
const result = execSync(`npm view ${packageName} version`, {
|
|
238
|
-
encoding: 'utf8',
|
|
239
|
-
stdio: ['pipe', 'pipe', 'ignore']
|
|
300
|
+
const result = execSync(`npm view ${packageName} version`, {
|
|
301
|
+
encoding: 'utf8',
|
|
302
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
240
303
|
});
|
|
241
304
|
return result.trim();
|
|
242
305
|
} catch {
|
|
@@ -247,7 +310,7 @@ function getLatestPackageVersion(packageName) {
|
|
|
247
310
|
function compareVersions(v1, v2) {
|
|
248
311
|
const parts1 = v1.split('.').map(Number);
|
|
249
312
|
const parts2 = v2.split('.').map(Number);
|
|
250
|
-
|
|
313
|
+
|
|
251
314
|
for (let i = 0; i < 3; i++) {
|
|
252
315
|
if (parts1[i] > parts2[i]) return 1;
|
|
253
316
|
if (parts1[i] < parts2[i]) return -1;
|
|
@@ -262,9 +325,9 @@ function showVersionInfo() {
|
|
|
262
325
|
'plusui-native-builder',
|
|
263
326
|
'plusui-native-connect'
|
|
264
327
|
];
|
|
265
|
-
|
|
328
|
+
|
|
266
329
|
logSection('PlusUI Package Versions');
|
|
267
|
-
|
|
330
|
+
|
|
268
331
|
packages.forEach(pkg => {
|
|
269
332
|
let version;
|
|
270
333
|
if (pkg === cliPackageJson.name) {
|
|
@@ -279,33 +342,33 @@ function showVersionInfo() {
|
|
|
279
342
|
}
|
|
280
343
|
}
|
|
281
344
|
});
|
|
282
|
-
|
|
345
|
+
|
|
283
346
|
console.log('');
|
|
284
347
|
}
|
|
285
348
|
|
|
286
349
|
async function updatePlusUIPackages() {
|
|
287
350
|
logSection('Updating PlusUI Packages');
|
|
288
|
-
|
|
351
|
+
|
|
289
352
|
const packages = [
|
|
290
353
|
cliPackageJson.name,
|
|
291
354
|
'plusui-native-core',
|
|
292
355
|
'plusui-native-builder',
|
|
293
356
|
'plusui-native-connect'
|
|
294
357
|
];
|
|
295
|
-
|
|
358
|
+
|
|
296
359
|
log('Checking for updates...\n', 'blue');
|
|
297
|
-
|
|
360
|
+
|
|
298
361
|
// Check if packages are installed locally or globally
|
|
299
362
|
const isInProject = existsSync(join(process.cwd(), 'package.json'));
|
|
300
|
-
|
|
363
|
+
|
|
301
364
|
if (isInProject) {
|
|
302
365
|
let updatedCount = 0;
|
|
303
366
|
let upToDateCount = 0;
|
|
304
367
|
let installedCount = 0;
|
|
305
|
-
|
|
368
|
+
|
|
306
369
|
for (const pkg of packages) {
|
|
307
370
|
const currentVersion = getInstalledPackageVersion(pkg);
|
|
308
|
-
|
|
371
|
+
|
|
309
372
|
if (!currentVersion) {
|
|
310
373
|
const latestVersion = getLatestPackageVersion(pkg);
|
|
311
374
|
|
|
@@ -327,22 +390,22 @@ async function updatePlusUIPackages() {
|
|
|
327
390
|
}
|
|
328
391
|
continue;
|
|
329
392
|
}
|
|
330
|
-
|
|
393
|
+
|
|
331
394
|
// Get latest version from npm
|
|
332
395
|
const latestVersion = getLatestPackageVersion(pkg);
|
|
333
|
-
|
|
396
|
+
|
|
334
397
|
if (!latestVersion) {
|
|
335
398
|
log(`${COLORS.yellow}${pkg}: couldn't check for updates${COLORS.reset}`);
|
|
336
399
|
continue;
|
|
337
400
|
}
|
|
338
|
-
|
|
401
|
+
|
|
339
402
|
const comparison = compareVersions(latestVersion, currentVersion);
|
|
340
|
-
|
|
403
|
+
|
|
341
404
|
if (comparison > 0) {
|
|
342
405
|
// Newer version available
|
|
343
406
|
try {
|
|
344
407
|
log(`${COLORS.blue}${pkg}: ${currentVersion} → ${latestVersion}${COLORS.reset}`);
|
|
345
|
-
execSync(`npm install ${pkg}@${latestVersion}`, {
|
|
408
|
+
execSync(`npm install ${pkg}@${latestVersion}`, {
|
|
346
409
|
stdio: ['ignore', 'ignore', 'pipe'],
|
|
347
410
|
encoding: 'utf8'
|
|
348
411
|
});
|
|
@@ -357,7 +420,7 @@ async function updatePlusUIPackages() {
|
|
|
357
420
|
upToDateCount++;
|
|
358
421
|
}
|
|
359
422
|
}
|
|
360
|
-
|
|
423
|
+
|
|
361
424
|
console.log('');
|
|
362
425
|
if (updatedCount > 0) {
|
|
363
426
|
log(`Updated ${updatedCount} package${updatedCount !== 1 ? 's' : ''}`, 'green');
|
|
@@ -370,17 +433,17 @@ async function updatePlusUIPackages() {
|
|
|
370
433
|
}
|
|
371
434
|
} else {
|
|
372
435
|
log('Updating global CLI package...', 'cyan');
|
|
373
|
-
|
|
436
|
+
|
|
374
437
|
const currentVersion = cliPackageJson.version;
|
|
375
438
|
const latestVersion = getLatestPackageVersion(cliPackageJson.name);
|
|
376
|
-
|
|
439
|
+
|
|
377
440
|
if (!latestVersion) {
|
|
378
441
|
log('Couldn\'t check for updates', 'yellow');
|
|
379
442
|
return;
|
|
380
443
|
}
|
|
381
|
-
|
|
444
|
+
|
|
382
445
|
const comparison = compareVersions(latestVersion, currentVersion);
|
|
383
|
-
|
|
446
|
+
|
|
384
447
|
if (comparison > 0) {
|
|
385
448
|
try {
|
|
386
449
|
log(`${COLORS.blue}${cliPackageJson.name}: ${currentVersion} → ${latestVersion}${COLORS.reset}`);
|
|
@@ -393,7 +456,7 @@ async function updatePlusUIPackages() {
|
|
|
393
456
|
log(`✓ ${cliPackageJson.name} v${currentVersion} (already up to date)`, 'green');
|
|
394
457
|
}
|
|
395
458
|
}
|
|
396
|
-
|
|
459
|
+
|
|
397
460
|
console.log('');
|
|
398
461
|
}
|
|
399
462
|
|
|
@@ -411,7 +474,7 @@ function findLikelyProjectDirs(baseDir) {
|
|
|
411
474
|
if (entries) {
|
|
412
475
|
// noop; just to ensure cwd is a Node project when possible
|
|
413
476
|
}
|
|
414
|
-
} catch {}
|
|
477
|
+
} catch { }
|
|
415
478
|
|
|
416
479
|
const candidates = [];
|
|
417
480
|
try {
|
|
@@ -431,7 +494,7 @@ function findLikelyProjectDirs(baseDir) {
|
|
|
431
494
|
candidates.push(dirName);
|
|
432
495
|
}
|
|
433
496
|
}
|
|
434
|
-
} catch {}
|
|
497
|
+
} catch { }
|
|
435
498
|
|
|
436
499
|
return candidates;
|
|
437
500
|
}
|
|
@@ -583,6 +646,9 @@ function buildBackend(platform = null, devMode = false) {
|
|
|
583
646
|
|
|
584
647
|
if (platformConfig.generator) {
|
|
585
648
|
cmakeArgs += ` -G "${platformConfig.generator}"`;
|
|
649
|
+
} else if (process.platform === 'win32') {
|
|
650
|
+
// Use Ninja on Windows to avoid VS generator compatibility issues
|
|
651
|
+
cmakeArgs += ' -G Ninja';
|
|
586
652
|
}
|
|
587
653
|
|
|
588
654
|
log(`Configuring CMake...`, 'blue');
|
|
@@ -645,30 +711,30 @@ async function embedAssets() {
|
|
|
645
711
|
if (!existsSync(assetsDir)) {
|
|
646
712
|
try {
|
|
647
713
|
await mkdir(assetsDir, { recursive: true });
|
|
648
|
-
} catch(e) {}
|
|
714
|
+
} catch (e) { }
|
|
649
715
|
}
|
|
650
716
|
|
|
651
717
|
logSection('Embedding Assets');
|
|
652
|
-
|
|
718
|
+
|
|
653
719
|
// Always generate the header file, even if empty
|
|
654
720
|
let headerContent = '#pragma once\n\n';
|
|
655
721
|
headerContent += '// THIS FILE IS AUTO-GENERATED BY PLUSUI CLI\n';
|
|
656
722
|
headerContent += '// DO NOT MODIFY MANUALLY\n\n';
|
|
657
|
-
|
|
658
|
-
const files = existsSync(assetsDir)
|
|
723
|
+
|
|
724
|
+
const files = existsSync(assetsDir)
|
|
659
725
|
? (await readdir(assetsDir)).filter(f => !statSync(join(assetsDir, f)).isDirectory())
|
|
660
726
|
: [];
|
|
661
|
-
|
|
727
|
+
|
|
662
728
|
if (files.length === 0) {
|
|
663
729
|
log('No assets found in assets/ folder', 'dim');
|
|
664
730
|
} else {
|
|
665
731
|
for (const file of files) {
|
|
666
732
|
const filePath = join(assetsDir, file);
|
|
667
733
|
log(`Processing ${file}...`, 'dim');
|
|
668
|
-
|
|
734
|
+
|
|
669
735
|
const varName = file.replace(/[^a-zA-Z0-9]/g, '_').toUpperCase();
|
|
670
736
|
const data = await readFile(filePath);
|
|
671
|
-
|
|
737
|
+
|
|
672
738
|
headerContent += `static const unsigned char ASSET_${varName}[] = {`;
|
|
673
739
|
for (let i = 0; i < data.length; i++) {
|
|
674
740
|
if (i % 16 === 0) headerContent += '\n ';
|
|
@@ -681,7 +747,7 @@ async function embedAssets() {
|
|
|
681
747
|
|
|
682
748
|
const genDir = join(process.cwd(), 'generated');
|
|
683
749
|
if (!existsSync(genDir)) await mkdir(genDir, { recursive: true });
|
|
684
|
-
|
|
750
|
+
|
|
685
751
|
await writeFile(join(genDir, 'assets.h'), headerContent);
|
|
686
752
|
log(`✓ Assets header generated: generated/assets.h`, 'green');
|
|
687
753
|
}
|
|
@@ -774,9 +840,15 @@ async function startBackend() {
|
|
|
774
840
|
|
|
775
841
|
const buildDir = getDevBuildDir();
|
|
776
842
|
|
|
843
|
+
// On Windows, use Ninja generator to avoid VS generator compatibility issues
|
|
844
|
+
let generatorArgs = '';
|
|
845
|
+
if (process.platform === 'win32') {
|
|
846
|
+
generatorArgs = ' -G Ninja';
|
|
847
|
+
}
|
|
848
|
+
|
|
777
849
|
// Always configure with dev mode to ensure PLUSUI_DEV_MODE is set correctly
|
|
778
850
|
log('Configuring CMake...', 'blue');
|
|
779
|
-
runCMake(`-S . -B "${buildDir}" -DPLUSUI_DEV_MODE=ON`);
|
|
851
|
+
runCMake(`-S . -B "${buildDir}" -DPLUSUI_DEV_MODE=ON${generatorArgs}`);
|
|
780
852
|
|
|
781
853
|
log('Compiling...', 'blue');
|
|
782
854
|
runCMake(`--build "${buildDir}"`);
|
|
@@ -784,16 +856,17 @@ async function startBackend() {
|
|
|
784
856
|
// Find executable
|
|
785
857
|
let exePath;
|
|
786
858
|
if (process.platform === 'win32') {
|
|
787
|
-
//
|
|
788
|
-
exePath = join(buildDir,
|
|
859
|
+
// Ninja puts exe directly in build dir
|
|
860
|
+
exePath = join(buildDir, `${projectName}.exe`);
|
|
789
861
|
if (!existsSync(exePath)) {
|
|
790
|
-
exePath = join(buildDir, '
|
|
862
|
+
exePath = join(buildDir, 'bin', `${projectName}.exe`);
|
|
791
863
|
}
|
|
864
|
+
// Fallback for VS generator (Debug subfolder)
|
|
792
865
|
if (!existsSync(exePath)) {
|
|
793
|
-
exePath = join(buildDir, '
|
|
866
|
+
exePath = join(buildDir, projectName, 'Debug', `${projectName}.exe`);
|
|
794
867
|
}
|
|
795
868
|
if (!existsSync(exePath)) {
|
|
796
|
-
exePath = join(buildDir, `${projectName}.exe`);
|
|
869
|
+
exePath = join(buildDir, 'Debug', `${projectName}.exe`);
|
|
797
870
|
}
|
|
798
871
|
} else {
|
|
799
872
|
exePath = join(buildDir, projectName);
|
|
@@ -828,7 +901,7 @@ async function killPort(port) {
|
|
|
828
901
|
try {
|
|
829
902
|
const output = execSync(`netstat -ano | findstr :${port}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
830
903
|
const lines = output.split('\n').filter(line => line.includes(`:${port}`) && line.includes('LISTENING'));
|
|
831
|
-
|
|
904
|
+
|
|
832
905
|
for (const line of lines) {
|
|
833
906
|
const parts = line.trim().split(/\s+/);
|
|
834
907
|
const pid = parts[parts.length - 1];
|
|
@@ -1097,7 +1170,7 @@ async function runBindgen(providedArgs = null, options = {}) {
|
|
|
1097
1170
|
defaultOutputDir = appOutputDir;
|
|
1098
1171
|
log(`Project mode: ${process.cwd()} -> ${appOutputDir}`, 'dim');
|
|
1099
1172
|
}
|
|
1100
|
-
|
|
1173
|
+
|
|
1101
1174
|
// Spawn node process
|
|
1102
1175
|
const proc = spawn(process.execPath, [scriptPath, ...bindgenArgs], {
|
|
1103
1176
|
stdio: 'inherit',
|