@typecad/framework-zephyr 1.0.0-alpha.10 → 1.0.0-alpha.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/dist/framework.manifest.d.ts +28 -31
- package/dist/framework.manifest.js +0 -11
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -5
- package/dist/toolchain/index.js +1 -18
- package/package.json +4 -4
- package/src/framework.manifest.ts +0 -13
- package/src/index.ts +0 -6
- package/src/toolchain/index.ts +1 -24
- package/dist/doctor.d.ts +0 -6
- package/dist/doctor.js +0 -48
- package/dist/toolchain/compat.d.ts +0 -38
- package/dist/toolchain/compat.js +0 -133
- package/src/doctor.ts +0 -56
- package/src/toolchain/compat.ts +0 -145
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
|
+
hal: {
|
|
3
|
+
[x: string]: {
|
|
4
|
+
supported: boolean;
|
|
5
|
+
ops: Record<string, "stub" | "polyfill" | "supported" | "unsupported" | "probe-inconclusive">;
|
|
6
|
+
partialCoverage: boolean;
|
|
7
|
+
unsupportedReason?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
raw?: unknown;
|
|
10
|
+
} & {
|
|
11
|
+
[k: string]: {
|
|
12
|
+
supported: boolean;
|
|
13
|
+
ops: Record<string, "stub" | "polyfill" | "supported" | "unsupported" | "probe-inconclusive">;
|
|
14
|
+
partialCoverage: boolean;
|
|
15
|
+
unsupportedReason?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
packageName: string;
|
|
2
19
|
schemaVersion: 1;
|
|
3
20
|
frameworkId: string;
|
|
4
|
-
packageName: string;
|
|
5
21
|
canonical: boolean;
|
|
6
22
|
displayName: string;
|
|
7
23
|
description: string;
|
|
8
24
|
implementationMode: "from-scratch" | "extends-canonical" | "extends-other";
|
|
9
25
|
entrypoint: {
|
|
26
|
+
sourceExtension: "cpp" | "ino" | "cc" | "h";
|
|
10
27
|
entrypointFunctionName: string;
|
|
11
28
|
requiresLoopFunction: boolean;
|
|
12
|
-
sourceExtension: "ino" | "cc" | "cpp" | "h";
|
|
13
29
|
generateHeaderFile: boolean;
|
|
14
30
|
overrideBaseName?: string | undefined;
|
|
15
31
|
outputSubdirectory?: string | undefined;
|
|
16
32
|
customBridgeShim?: string | undefined;
|
|
17
33
|
};
|
|
18
34
|
profile: {
|
|
19
|
-
targets: string[];
|
|
20
35
|
forcedIncludes: string[];
|
|
21
36
|
symbolAliases: Record<string, string>;
|
|
22
|
-
|
|
23
|
-
hal: {
|
|
24
|
-
[x: string]: {
|
|
25
|
-
supported: boolean;
|
|
26
|
-
ops: Record<string, "supported" | "stub" | "unsupported" | "probe-inconclusive" | "polyfill">;
|
|
27
|
-
partialCoverage: boolean;
|
|
28
|
-
unsupportedReason?: string | undefined;
|
|
29
|
-
};
|
|
30
|
-
raw?: unknown;
|
|
31
|
-
} & {
|
|
32
|
-
[k: string]: {
|
|
33
|
-
supported: boolean;
|
|
34
|
-
ops: Record<string, "supported" | "stub" | "unsupported" | "probe-inconclusive" | "polyfill">;
|
|
35
|
-
partialCoverage: boolean;
|
|
36
|
-
unsupportedReason?: string | undefined;
|
|
37
|
-
};
|
|
37
|
+
targets: string[];
|
|
38
38
|
};
|
|
39
39
|
polyfills: {
|
|
40
40
|
emitted: {
|
|
@@ -58,12 +58,12 @@ declare const _default: {
|
|
|
58
58
|
reexportedFrom?: string | undefined;
|
|
59
59
|
};
|
|
60
60
|
typeEmission: {
|
|
61
|
-
|
|
62
|
-
mathHeader: "none" | "<math.h>" | "<Arduino.h>";
|
|
61
|
+
needsIostream: boolean;
|
|
63
62
|
needsStdString: boolean;
|
|
64
63
|
needsStdVector: boolean;
|
|
65
|
-
needsIostream: boolean;
|
|
66
64
|
needsStdFunction: boolean;
|
|
65
|
+
mathHeader: "none" | "<math.h>" | "<Arduino.h>";
|
|
66
|
+
normalizeCppType: boolean;
|
|
67
67
|
stdlibSupport: {
|
|
68
68
|
hasVector: boolean;
|
|
69
69
|
hasString: boolean;
|
|
@@ -79,6 +79,12 @@ declare const _default: {
|
|
|
79
79
|
hardwareTestGroups: string[];
|
|
80
80
|
halResolutionTests: string[];
|
|
81
81
|
};
|
|
82
|
+
doctor?: {
|
|
83
|
+
available: boolean;
|
|
84
|
+
} | undefined;
|
|
85
|
+
licenses?: {
|
|
86
|
+
available: boolean;
|
|
87
|
+
} | undefined;
|
|
82
88
|
basedOn?: string | undefined;
|
|
83
89
|
inheritsStrategyId?: string | undefined;
|
|
84
90
|
libraryResolution?: {
|
|
@@ -88,14 +94,5 @@ declare const _default: {
|
|
|
88
94
|
tryGenerateLibDecl: boolean;
|
|
89
95
|
reexportedFrom?: string | undefined;
|
|
90
96
|
} | undefined;
|
|
91
|
-
doctor?: {
|
|
92
|
-
available: boolean;
|
|
93
|
-
} | undefined;
|
|
94
|
-
licenses?: {
|
|
95
|
-
available: boolean;
|
|
96
|
-
} | undefined;
|
|
97
|
-
compat?: {
|
|
98
|
-
zephyr?: string | undefined;
|
|
99
|
-
} | undefined;
|
|
100
97
|
};
|
|
101
98
|
export default _default;
|
|
@@ -522,15 +522,4 @@ export default defineFrameworkManifest({
|
|
|
522
522
|
'uart', 'wdt', 'worker',
|
|
523
523
|
],
|
|
524
524
|
},
|
|
525
|
-
// Declared compatibility range for the installed Zephyr RTOS. The framework's
|
|
526
|
-
// build-time version check (toolchain/compat.ts) reads this and fails fast
|
|
527
|
-
// with a clear message when the user's Zephyr is outside the range, instead
|
|
528
|
-
// of letting west/CMake surface a cryptic board-target error (the class of
|
|
529
|
-
// breakage behind the HWMv2 qualifier requirement in Zephyr 4.3+).
|
|
530
|
-
compat: {
|
|
531
|
-
zephyr: '>=4.3 <5.0',
|
|
532
|
-
},
|
|
533
|
-
// `cuttlefish doctor` prints the detected Zephyr version + compat result and
|
|
534
|
-
// previews how the configured board target resolves for that version.
|
|
535
|
-
doctor: { available: true },
|
|
536
525
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
2
2
|
export { ZephyrStrategy } from './strategy.js';
|
|
3
3
|
export { Toolchain } from './toolchain/index.js';
|
|
4
|
-
export { runDoctor as doctor } from './doctor.js';
|
|
5
4
|
export { chipForTarget, setActiveChip, getActiveChip, XIAO_BLE, } from './chips/index.js';
|
|
6
5
|
export type { ZephyrChipDescriptor, ZephyrGpioDtSpec, } from './chips/types.js';
|
package/dist/index.js
CHANGED
|
@@ -8,10 +8,5 @@
|
|
|
8
8
|
export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
9
9
|
export { ZephyrStrategy } from './strategy.js';
|
|
10
10
|
export { Toolchain } from './toolchain/index.js';
|
|
11
|
-
// `cuttlefish doctor` — verify the installed Zephyr is reachable + inside the
|
|
12
|
-
// declared compat range, and preview board-target normalization. Re-exported
|
|
13
|
-
// under the dispatcher-facing alias `doctor` so the loader picks it up as
|
|
14
|
-
// mod.doctor (see framework-package.ts).
|
|
15
|
-
export { runDoctor as doctor } from './doctor.js';
|
|
16
11
|
// Chip descriptor registry (for downstream tooling / additional boards).
|
|
17
12
|
export { chipForTarget, setActiveChip, getActiveChip, XIAO_BLE, } from './chips/index.js';
|
package/dist/toolchain/index.js
CHANGED
|
@@ -28,7 +28,6 @@ import { writeDebugConfig, resolveDebugLocations } from './debug-config.js';
|
|
|
28
28
|
import { ZephyrStrategy } from '../strategy.js';
|
|
29
29
|
import { generateOverlay } from '../dt-config/overlay.js';
|
|
30
30
|
import { chipForTarget } from '../chips/index.js';
|
|
31
|
-
import { detectZephyrVersion, checkZephyrCompat, resolveBoardTarget } from './compat.js';
|
|
32
31
|
import { DEFAULT_ZEPHYR_DISPLAY_PROFILE } from '../display/profiles.js';
|
|
33
32
|
/** Default board target — the framework's MVP canonical board. */
|
|
34
33
|
const DEFAULT_BOARD = 'xiao_ble';
|
|
@@ -198,23 +197,7 @@ export const Toolchain = {
|
|
|
198
197
|
},
|
|
199
198
|
compile(o) {
|
|
200
199
|
const projectRoot = projectRootFromOptions(o);
|
|
201
|
-
const
|
|
202
|
-
// Fail fast on an incompatible Zephyr (clear message vs. a cryptic west/
|
|
203
|
-
// CMake board error), then normalize the board target for the installed
|
|
204
|
-
// version — Zephyr 4.3+ rejects bare multi-core board names, so a stale
|
|
205
|
-
// config (esp32s3_devkitc) is rewritten to the qualified form
|
|
206
|
-
// (esp32s3_devkitc/esp32s3/procpu). See toolchain/compat.ts.
|
|
207
|
-
const zephyrVersion = detectZephyrVersion();
|
|
208
|
-
const compat = checkZephyrCompat(zephyrVersion);
|
|
209
|
-
if (compat.status === 'out-of-range') {
|
|
210
|
-
throw new Error(`Zephyr ${zephyrVersion} is outside the supported range (${compat.range}) for @typecad/framework-zephyr. ` +
|
|
211
|
-
`Set ZEPHYR_BASE to a compatible Zephyr checkout, or install one via '@typecad/zephyr-installer'.`);
|
|
212
|
-
}
|
|
213
|
-
if (compat.status === 'undetectable') {
|
|
214
|
-
console.warn(`! Could not detect the installed Zephyr version (is ZEPHYR_BASE set?). ` +
|
|
215
|
-
`Skipping compat check; declared range is ${compat.range}.`);
|
|
216
|
-
}
|
|
217
|
-
const board = resolveBoardTarget(rawBoard, zephyrVersion);
|
|
200
|
+
const board = targetFromOptions(o);
|
|
218
201
|
const debugMode = new ZephyrStrategy().debugMode(board);
|
|
219
202
|
const isGdbDebug = o.debug === true && debugMode === 'gdb';
|
|
220
203
|
const zc = o.zephyrConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typecad/framework-zephyr",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.9",
|
|
4
4
|
"description": "TypeCAD framework package for the Zephyr RTOS — west/CMake build, devicetree-driven GPIO",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"test:hw:mqtt": "cd ../../tests/hardware && npm exec -- cuttlefish-test mqtt-client.test.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@typecad/cuttlefish": "1.0.0-alpha.
|
|
41
|
+
"@typecad/cuttlefish": "1.0.0-alpha.9"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@typecad/expect": "1.0.0-alpha.
|
|
45
|
-
"@typecad/board-xiao-nrf52840": "1.0.0-alpha.
|
|
44
|
+
"@typecad/expect": "1.0.0-alpha.9",
|
|
45
|
+
"@typecad/board-xiao-nrf52840": "1.0.0-alpha.9",
|
|
46
46
|
"typescript": "^5.7.3"
|
|
47
47
|
},
|
|
48
48
|
"license": "MIT",
|
|
@@ -542,17 +542,4 @@ export default defineFrameworkManifest({
|
|
|
542
542
|
'uart', 'wdt', 'worker',
|
|
543
543
|
],
|
|
544
544
|
},
|
|
545
|
-
|
|
546
|
-
// Declared compatibility range for the installed Zephyr RTOS. The framework's
|
|
547
|
-
// build-time version check (toolchain/compat.ts) reads this and fails fast
|
|
548
|
-
// with a clear message when the user's Zephyr is outside the range, instead
|
|
549
|
-
// of letting west/CMake surface a cryptic board-target error (the class of
|
|
550
|
-
// breakage behind the HWMv2 qualifier requirement in Zephyr 4.3+).
|
|
551
|
-
compat: {
|
|
552
|
-
zephyr: '>=4.3 <5.0',
|
|
553
|
-
},
|
|
554
|
-
|
|
555
|
-
// `cuttlefish doctor` prints the detected Zephyr version + compat result and
|
|
556
|
-
// previews how the configured board target resolves for that version.
|
|
557
|
-
doctor: { available: true },
|
|
558
545
|
});
|
package/src/index.ts
CHANGED
|
@@ -10,12 +10,6 @@ export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
|
10
10
|
export { ZephyrStrategy } from './strategy.js';
|
|
11
11
|
export { Toolchain } from './toolchain/index.js';
|
|
12
12
|
|
|
13
|
-
// `cuttlefish doctor` — verify the installed Zephyr is reachable + inside the
|
|
14
|
-
// declared compat range, and preview board-target normalization. Re-exported
|
|
15
|
-
// under the dispatcher-facing alias `doctor` so the loader picks it up as
|
|
16
|
-
// mod.doctor (see framework-package.ts).
|
|
17
|
-
export { runDoctor as doctor } from './doctor.js';
|
|
18
|
-
|
|
19
13
|
// Chip descriptor registry (for downstream tooling / additional boards).
|
|
20
14
|
export {
|
|
21
15
|
chipForTarget,
|
package/src/toolchain/index.ts
CHANGED
|
@@ -30,7 +30,6 @@ import { writeDebugConfig, resolveDebugLocations } from './debug-config.js';
|
|
|
30
30
|
import { ZephyrStrategy } from '../strategy.js';
|
|
31
31
|
import { generateOverlay, type DisplayWiring, type TouchWiring } from '../dt-config/overlay.js';
|
|
32
32
|
import { chipForTarget } from '../chips/index.js';
|
|
33
|
-
import { detectZephyrVersion, checkZephyrCompat, resolveBoardTarget } from './compat.js';
|
|
34
33
|
import { DEFAULT_ZEPHYR_DISPLAY_PROFILE } from '../display/profiles.js';
|
|
35
34
|
|
|
36
35
|
/** Default board target — the framework's MVP canonical board. */
|
|
@@ -220,29 +219,7 @@ export const Toolchain = {
|
|
|
220
219
|
|
|
221
220
|
compile(o: ToolchainOptions): CompileResult {
|
|
222
221
|
const projectRoot = projectRootFromOptions(o);
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
// Fail fast on an incompatible Zephyr (clear message vs. a cryptic west/
|
|
226
|
-
// CMake board error), then normalize the board target for the installed
|
|
227
|
-
// version — Zephyr 4.3+ rejects bare multi-core board names, so a stale
|
|
228
|
-
// config (esp32s3_devkitc) is rewritten to the qualified form
|
|
229
|
-
// (esp32s3_devkitc/esp32s3/procpu). See toolchain/compat.ts.
|
|
230
|
-
const zephyrVersion = detectZephyrVersion();
|
|
231
|
-
const compat = checkZephyrCompat(zephyrVersion);
|
|
232
|
-
if (compat.status === 'out-of-range') {
|
|
233
|
-
throw new Error(
|
|
234
|
-
`Zephyr ${zephyrVersion} is outside the supported range (${compat.range}) for @typecad/framework-zephyr. ` +
|
|
235
|
-
`Set ZEPHYR_BASE to a compatible Zephyr checkout, or install one via '@typecad/zephyr-installer'.`,
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
if (compat.status === 'undetectable') {
|
|
239
|
-
console.warn(
|
|
240
|
-
`! Could not detect the installed Zephyr version (is ZEPHYR_BASE set?). ` +
|
|
241
|
-
`Skipping compat check; declared range is ${compat.range}.`,
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
const board = resolveBoardTarget(rawBoard, zephyrVersion);
|
|
245
|
-
|
|
222
|
+
const board = targetFromOptions(o);
|
|
246
223
|
const debugMode = new ZephyrStrategy().debugMode(board);
|
|
247
224
|
const isGdbDebug = o.debug === true && debugMode === 'gdb';
|
|
248
225
|
const zc = o.zephyrConfig as Record<string, unknown> | undefined;
|
package/dist/doctor.d.ts
DELETED
package/dist/doctor.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// @typecad/framework-zephyr — Zephyr environment doctor
|
|
3
|
-
//
|
|
4
|
-
// `cuttlefish doctor` (Zephyr framework) — verify the installed Zephyr RTOS is
|
|
5
|
-
// reachable and inside the framework's declared compat range, and preview how
|
|
6
|
-
// the configured board target resolves for that version. Exits 0 if the
|
|
7
|
-
// environment is OK, non-zero otherwise. Mirrors framework-arduino's doctor
|
|
8
|
-
// shape (dispatched via the framework's `doctor` export).
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
import * as ui from '@typecad/cuttlefish/utils/ui';
|
|
11
|
-
import { loadCuttlefishConfig } from '@typecad/cuttlefish/config-loader';
|
|
12
|
-
import { detectZephyrVersion, checkZephyrCompat, resolveBoardTarget } from './toolchain/compat.js';
|
|
13
|
-
/**
|
|
14
|
-
* Verify the installed Zephyr is reachable + inside the supported range, and
|
|
15
|
-
* preview board-target normalization for the configured target. Sets
|
|
16
|
-
* process.exitCode = 1 on an out-of-range Zephyr.
|
|
17
|
-
*/
|
|
18
|
-
export function runDoctor() {
|
|
19
|
-
ui.printHeader();
|
|
20
|
-
ui.printStep('Checking Zephyr environment...');
|
|
21
|
-
const base = process.env.ZEPHYR_BASE;
|
|
22
|
-
const version = detectZephyrVersion();
|
|
23
|
-
const result = checkZephyrCompat(version);
|
|
24
|
-
ui.printInfo(`ZEPHYR_BASE ..... ${base ?? '(not set)'}`);
|
|
25
|
-
ui.printInfo(`Zephyr version .. ${version ?? 'unknown (could not read ZEPHYR_BASE/VERSION)'}`);
|
|
26
|
-
ui.printInfo(`Supported range . ${result.range ?? '(none declared)'}`);
|
|
27
|
-
if (result.status === 'out-of-range') {
|
|
28
|
-
ui.printError(`Zephyr ${version} is OUTSIDE the supported range (${result.range}).`);
|
|
29
|
-
ui.printInfo("Set ZEPHYR_BASE to a compatible Zephyr checkout, or install one via '@typecad/zephyr-installer'.");
|
|
30
|
-
process.exitCode = 1;
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (result.status === 'undetectable') {
|
|
34
|
-
ui.printWarning('Could not detect the Zephyr version (is ZEPHYR_BASE set?) — compat check skipped.');
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
ui.printInfo('Zephyr compat ... OK');
|
|
38
|
-
}
|
|
39
|
-
// Preview how the configured board target resolves for this Zephyr version
|
|
40
|
-
// (e.g. a stale bare id would be qualified at build time). The loader extracts
|
|
41
|
-
// frameworkData.buildTarget to a top-level field.
|
|
42
|
-
const config = loadCuttlefishConfig(process.cwd());
|
|
43
|
-
const buildTarget = config?.buildTarget;
|
|
44
|
-
if (buildTarget) {
|
|
45
|
-
const resolved = resolveBoardTarget(buildTarget, version);
|
|
46
|
-
ui.printInfo(`Board target .... ${buildTarget}${resolved === buildTarget ? '' : ` → ${resolved}`}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/** Parse "4.3.99" / "v4.3" / "4.3.99-rc1" → [4, 3, 99]. Undefined if unparseable. */
|
|
2
|
-
export declare function parseVersion(v: string | undefined): [number, number, number] | undefined;
|
|
3
|
-
/** Compare two version strings: -1 if a<b, 0 if equal, 1 if a>b. */
|
|
4
|
-
export declare function compareVersion(a: string, b: string): number;
|
|
5
|
-
/**
|
|
6
|
-
* Evaluate a simple range of space-separated comparators against a version.
|
|
7
|
-
* Supported operators: >= <= > < =. Each comparator glues the operator to its
|
|
8
|
-
* version (">=4.3", "<5.0"); spaces between comparators are AND.
|
|
9
|
-
* satisfiesRange("4.3.99", ">=4.3 <5.0") === true
|
|
10
|
-
*/
|
|
11
|
-
export declare function satisfiesRange(version: string, range: string): boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Detect the installed Zephyr version from ZEPHYR_BASE/VERSION. Returns
|
|
14
|
-
* undefined when ZEPHYR_BASE is unset or VERSION can't be read/parsed. Handles
|
|
15
|
-
* the CMake-style file (VERSION_MAJOR = 4 / VERSION_MINOR = 3 / PATCHLEVEL = 99)
|
|
16
|
-
* and a bare "4.3.99".
|
|
17
|
-
*/
|
|
18
|
-
export declare function detectZephyrVersion(): string | undefined;
|
|
19
|
-
export type CompatStatus = 'ok' | 'undetectable' | 'out-of-range';
|
|
20
|
-
export interface CompatResult {
|
|
21
|
-
version: string | undefined;
|
|
22
|
-
/** Declared supported range (manifest.compat.zephyr), if any. */
|
|
23
|
-
range: string | undefined;
|
|
24
|
-
status: CompatStatus;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Compare the detected Zephyr version against the declared compat range. Pure:
|
|
28
|
-
* returns a status; the caller decides whether to throw/warn. 'ok' covers both
|
|
29
|
-
* "in range" and "no range declared".
|
|
30
|
-
*/
|
|
31
|
-
export declare function checkZephyrCompat(version: string | undefined): CompatResult;
|
|
32
|
-
/**
|
|
33
|
-
* Normalize a board target for the installed Zephyr version. Rewrites a stale
|
|
34
|
-
* bare id (esp32s3_devkitc) to the qualified form on Zephyr >=4.3; idempotent
|
|
35
|
-
* if the target is already qualified. Older Zephyr, single-core boards
|
|
36
|
-
* (xiao_ble), and unknown boards pass through unchanged.
|
|
37
|
-
*/
|
|
38
|
-
export declare function resolveBoardTarget(boardTarget: string, version: string | undefined): string;
|
package/dist/toolchain/compat.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
// Zephyr version compatibility + board-target normalization.
|
|
2
|
-
//
|
|
3
|
-
// Two mechanisms absorb Zephyr version churn:
|
|
4
|
-
// 1. checkZephyrCompat() — compare the installed Zephyr version against the
|
|
5
|
-
// declared range (manifest.compat.zephyr) so an incompatible Zephyr fails
|
|
6
|
-
// fast with a clear message instead of a cryptic west/CMake board error.
|
|
7
|
-
// 2. resolveBoardTarget() — normalize the board target for the installed
|
|
8
|
-
// Zephyr version. Zephyr 4.3+ rejects bare multi-core board names
|
|
9
|
-
// (esp32s3_devkitc) and requires a qualified target
|
|
10
|
-
// (esp32s3_devkitc/esp32s3/procpu). This rewrites stale configs at build
|
|
11
|
-
// time so users don't have to regenerate them after a Zephyr upgrade.
|
|
12
|
-
//
|
|
13
|
-
// This module is intentionally pure (no chalk/ui/console) so it unit-tests
|
|
14
|
-
// cleanly; the doctor and the toolchain decide how to present results.
|
|
15
|
-
import { readFileSync } from 'node:fs';
|
|
16
|
-
import { join } from 'node:path';
|
|
17
|
-
import manifest from '../framework.manifest.js';
|
|
18
|
-
// ── minimal semver ──────────────────────────────────────────────────────────
|
|
19
|
-
/** Parse "4.3.99" / "v4.3" / "4.3.99-rc1" → [4, 3, 99]. Undefined if unparseable. */
|
|
20
|
-
export function parseVersion(v) {
|
|
21
|
-
if (!v)
|
|
22
|
-
return undefined;
|
|
23
|
-
const m = v.replace(/^v/i, '').match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
24
|
-
if (!m)
|
|
25
|
-
return undefined;
|
|
26
|
-
return [Number(m[1]), Number(m[2] ?? 0), Number(m[3] ?? 0)];
|
|
27
|
-
}
|
|
28
|
-
/** Compare two version strings: -1 if a<b, 0 if equal, 1 if a>b. */
|
|
29
|
-
export function compareVersion(a, b) {
|
|
30
|
-
const pa = parseVersion(a) ?? [0, 0, 0];
|
|
31
|
-
const pb = parseVersion(b) ?? [0, 0, 0];
|
|
32
|
-
for (let i = 0; i < 3; i++) {
|
|
33
|
-
if (pa[i] < pb[i])
|
|
34
|
-
return -1;
|
|
35
|
-
if (pa[i] > pb[i])
|
|
36
|
-
return 1;
|
|
37
|
-
}
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Evaluate a simple range of space-separated comparators against a version.
|
|
42
|
-
* Supported operators: >= <= > < =. Each comparator glues the operator to its
|
|
43
|
-
* version (">=4.3", "<5.0"); spaces between comparators are AND.
|
|
44
|
-
* satisfiesRange("4.3.99", ">=4.3 <5.0") === true
|
|
45
|
-
*/
|
|
46
|
-
export function satisfiesRange(version, range) {
|
|
47
|
-
return range
|
|
48
|
-
.trim()
|
|
49
|
-
.split(/\s+/)
|
|
50
|
-
.every((clause) => {
|
|
51
|
-
const m = clause.replace(/\s+/g, '').match(/^(>=|<=|>|<|=)(.+)$/);
|
|
52
|
-
if (!m)
|
|
53
|
-
return true; // ignore anything that isn't a comparator
|
|
54
|
-
const cmp = compareVersion(version, m[2]);
|
|
55
|
-
switch (m[1]) {
|
|
56
|
-
case '>=': return cmp >= 0;
|
|
57
|
-
case '<=': return cmp <= 0;
|
|
58
|
-
case '>': return cmp > 0;
|
|
59
|
-
case '<': return cmp < 0;
|
|
60
|
-
case '=': return cmp === 0;
|
|
61
|
-
default: return true;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
// ── Zephyr version detection ────────────────────────────────────────────────
|
|
66
|
-
/**
|
|
67
|
-
* Detect the installed Zephyr version from ZEPHYR_BASE/VERSION. Returns
|
|
68
|
-
* undefined when ZEPHYR_BASE is unset or VERSION can't be read/parsed. Handles
|
|
69
|
-
* the CMake-style file (VERSION_MAJOR = 4 / VERSION_MINOR = 3 / PATCHLEVEL = 99)
|
|
70
|
-
* and a bare "4.3.99".
|
|
71
|
-
*/
|
|
72
|
-
export function detectZephyrVersion() {
|
|
73
|
-
const base = process.env.ZEPHYR_BASE;
|
|
74
|
-
if (!base)
|
|
75
|
-
return undefined;
|
|
76
|
-
let content;
|
|
77
|
-
try {
|
|
78
|
-
content = readFileSync(join(base, 'VERSION'), 'utf-8');
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
const field = (key) => {
|
|
84
|
-
const m = content.match(new RegExp(`^\\s*${key}\\s*=\\s*(\\d+)`, 'm'));
|
|
85
|
-
return m ? m[1] : undefined;
|
|
86
|
-
};
|
|
87
|
-
const major = field('VERSION_MAJOR');
|
|
88
|
-
if (major !== undefined) {
|
|
89
|
-
return `${major}.${field('VERSION_MINOR') ?? 0}.${field('PATCHLEVEL') ?? 0}`;
|
|
90
|
-
}
|
|
91
|
-
const m = content.match(/(\d+\.\d+(?:\.\d+)?)/);
|
|
92
|
-
return m ? m[1] : undefined;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Compare the detected Zephyr version against the declared compat range. Pure:
|
|
96
|
-
* returns a status; the caller decides whether to throw/warn. 'ok' covers both
|
|
97
|
-
* "in range" and "no range declared".
|
|
98
|
-
*/
|
|
99
|
-
export function checkZephyrCompat(version) {
|
|
100
|
-
const range = manifest.compat?.zephyr;
|
|
101
|
-
if (!range)
|
|
102
|
-
return { version, range, status: 'ok' };
|
|
103
|
-
if (version === undefined)
|
|
104
|
-
return { version, range, status: 'undetectable' };
|
|
105
|
-
return { version, range, status: satisfiesRange(version, range) ? 'ok' : 'out-of-range' };
|
|
106
|
-
}
|
|
107
|
-
// ── board-target normalization ──────────────────────────────────────────────
|
|
108
|
-
/**
|
|
109
|
-
* For Zephyr >=4.3, multi-core ESP32 boards require a qualified board target
|
|
110
|
-
* (board/<soc>/<core>) — the bare id is rejected with "Board qualifiers … not
|
|
111
|
-
* found". Map each known multi-core board id to its procpu (main app core)
|
|
112
|
-
* qualified form. procpu is the core that runs application firmware; appcpu is
|
|
113
|
-
* the secondary core (selected explicitly only when offloading to it).
|
|
114
|
-
*/
|
|
115
|
-
const QUALIFIED_TARGETS_GE_4_3 = {
|
|
116
|
-
esp32_devkitc: 'esp32_devkitc/esp32/procpu',
|
|
117
|
-
esp32s3_devkitc: 'esp32s3_devkitc/esp32s3/procpu',
|
|
118
|
-
};
|
|
119
|
-
/**
|
|
120
|
-
* Normalize a board target for the installed Zephyr version. Rewrites a stale
|
|
121
|
-
* bare id (esp32s3_devkitc) to the qualified form on Zephyr >=4.3; idempotent
|
|
122
|
-
* if the target is already qualified. Older Zephyr, single-core boards
|
|
123
|
-
* (xiao_ble), and unknown boards pass through unchanged.
|
|
124
|
-
*/
|
|
125
|
-
export function resolveBoardTarget(boardTarget, version) {
|
|
126
|
-
const boardId = boardTarget.split('/')[0];
|
|
127
|
-
if (version !== undefined && satisfiesRange(version, '>=4.3')) {
|
|
128
|
-
const qualified = QUALIFIED_TARGETS_GE_4_3[boardId];
|
|
129
|
-
if (qualified)
|
|
130
|
-
return qualified;
|
|
131
|
-
}
|
|
132
|
-
return boardTarget;
|
|
133
|
-
}
|
package/src/doctor.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// @typecad/framework-zephyr — Zephyr environment doctor
|
|
3
|
-
//
|
|
4
|
-
// `cuttlefish doctor` (Zephyr framework) — verify the installed Zephyr RTOS is
|
|
5
|
-
// reachable and inside the framework's declared compat range, and preview how
|
|
6
|
-
// the configured board target resolves for that version. Exits 0 if the
|
|
7
|
-
// environment is OK, non-zero otherwise. Mirrors framework-arduino's doctor
|
|
8
|
-
// shape (dispatched via the framework's `doctor` export).
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
|
|
11
|
-
import * as ui from '@typecad/cuttlefish/utils/ui';
|
|
12
|
-
import { loadCuttlefishConfig } from '@typecad/cuttlefish/config-loader';
|
|
13
|
-
import { detectZephyrVersion, checkZephyrCompat, resolveBoardTarget } from './toolchain/compat.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Verify the installed Zephyr is reachable + inside the supported range, and
|
|
17
|
-
* preview board-target normalization for the configured target. Sets
|
|
18
|
-
* process.exitCode = 1 on an out-of-range Zephyr.
|
|
19
|
-
*/
|
|
20
|
-
export function runDoctor(): void {
|
|
21
|
-
ui.printHeader();
|
|
22
|
-
ui.printStep('Checking Zephyr environment...');
|
|
23
|
-
|
|
24
|
-
const base = process.env.ZEPHYR_BASE;
|
|
25
|
-
const version = detectZephyrVersion();
|
|
26
|
-
const result = checkZephyrCompat(version);
|
|
27
|
-
|
|
28
|
-
ui.printInfo(`ZEPHYR_BASE ..... ${base ?? '(not set)'}`);
|
|
29
|
-
ui.printInfo(`Zephyr version .. ${version ?? 'unknown (could not read ZEPHYR_BASE/VERSION)'}`);
|
|
30
|
-
ui.printInfo(`Supported range . ${result.range ?? '(none declared)'}`);
|
|
31
|
-
|
|
32
|
-
if (result.status === 'out-of-range') {
|
|
33
|
-
ui.printError(`Zephyr ${version} is OUTSIDE the supported range (${result.range}).`);
|
|
34
|
-
ui.printInfo(
|
|
35
|
-
"Set ZEPHYR_BASE to a compatible Zephyr checkout, or install one via '@typecad/zephyr-installer'.",
|
|
36
|
-
);
|
|
37
|
-
process.exitCode = 1;
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (result.status === 'undetectable') {
|
|
42
|
-
ui.printWarning('Could not detect the Zephyr version (is ZEPHYR_BASE set?) — compat check skipped.');
|
|
43
|
-
} else {
|
|
44
|
-
ui.printInfo('Zephyr compat ... OK');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Preview how the configured board target resolves for this Zephyr version
|
|
48
|
-
// (e.g. a stale bare id would be qualified at build time). The loader extracts
|
|
49
|
-
// frameworkData.buildTarget to a top-level field.
|
|
50
|
-
const config = loadCuttlefishConfig(process.cwd());
|
|
51
|
-
const buildTarget = config?.buildTarget;
|
|
52
|
-
if (buildTarget) {
|
|
53
|
-
const resolved = resolveBoardTarget(buildTarget, version);
|
|
54
|
-
ui.printInfo(`Board target .... ${buildTarget}${resolved === buildTarget ? '' : ` → ${resolved}`}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
package/src/toolchain/compat.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
// Zephyr version compatibility + board-target normalization.
|
|
2
|
-
//
|
|
3
|
-
// Two mechanisms absorb Zephyr version churn:
|
|
4
|
-
// 1. checkZephyrCompat() — compare the installed Zephyr version against the
|
|
5
|
-
// declared range (manifest.compat.zephyr) so an incompatible Zephyr fails
|
|
6
|
-
// fast with a clear message instead of a cryptic west/CMake board error.
|
|
7
|
-
// 2. resolveBoardTarget() — normalize the board target for the installed
|
|
8
|
-
// Zephyr version. Zephyr 4.3+ rejects bare multi-core board names
|
|
9
|
-
// (esp32s3_devkitc) and requires a qualified target
|
|
10
|
-
// (esp32s3_devkitc/esp32s3/procpu). This rewrites stale configs at build
|
|
11
|
-
// time so users don't have to regenerate them after a Zephyr upgrade.
|
|
12
|
-
//
|
|
13
|
-
// This module is intentionally pure (no chalk/ui/console) so it unit-tests
|
|
14
|
-
// cleanly; the doctor and the toolchain decide how to present results.
|
|
15
|
-
|
|
16
|
-
import { readFileSync } from 'node:fs';
|
|
17
|
-
import { join } from 'node:path';
|
|
18
|
-
import manifest from '../framework.manifest.js';
|
|
19
|
-
|
|
20
|
-
// ── minimal semver ──────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
/** Parse "4.3.99" / "v4.3" / "4.3.99-rc1" → [4, 3, 99]. Undefined if unparseable. */
|
|
23
|
-
export function parseVersion(v: string | undefined): [number, number, number] | undefined {
|
|
24
|
-
if (!v) return undefined;
|
|
25
|
-
const m = v.replace(/^v/i, '').match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
26
|
-
if (!m) return undefined;
|
|
27
|
-
return [Number(m[1]), Number(m[2] ?? 0), Number(m[3] ?? 0)];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Compare two version strings: -1 if a<b, 0 if equal, 1 if a>b. */
|
|
31
|
-
export function compareVersion(a: string, b: string): number {
|
|
32
|
-
const pa = parseVersion(a) ?? [0, 0, 0];
|
|
33
|
-
const pb = parseVersion(b) ?? [0, 0, 0];
|
|
34
|
-
for (let i = 0; i < 3; i++) {
|
|
35
|
-
if (pa[i]! < pb[i]!) return -1;
|
|
36
|
-
if (pa[i]! > pb[i]!) return 1;
|
|
37
|
-
}
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Evaluate a simple range of space-separated comparators against a version.
|
|
43
|
-
* Supported operators: >= <= > < =. Each comparator glues the operator to its
|
|
44
|
-
* version (">=4.3", "<5.0"); spaces between comparators are AND.
|
|
45
|
-
* satisfiesRange("4.3.99", ">=4.3 <5.0") === true
|
|
46
|
-
*/
|
|
47
|
-
export function satisfiesRange(version: string, range: string): boolean {
|
|
48
|
-
return range
|
|
49
|
-
.trim()
|
|
50
|
-
.split(/\s+/)
|
|
51
|
-
.every((clause) => {
|
|
52
|
-
const m = clause.replace(/\s+/g, '').match(/^(>=|<=|>|<|=)(.+)$/);
|
|
53
|
-
if (!m) return true; // ignore anything that isn't a comparator
|
|
54
|
-
const cmp = compareVersion(version, m[2]!);
|
|
55
|
-
switch (m[1]) {
|
|
56
|
-
case '>=': return cmp >= 0;
|
|
57
|
-
case '<=': return cmp <= 0;
|
|
58
|
-
case '>': return cmp > 0;
|
|
59
|
-
case '<': return cmp < 0;
|
|
60
|
-
case '=': return cmp === 0;
|
|
61
|
-
default: return true;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ── Zephyr version detection ────────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Detect the installed Zephyr version from ZEPHYR_BASE/VERSION. Returns
|
|
70
|
-
* undefined when ZEPHYR_BASE is unset or VERSION can't be read/parsed. Handles
|
|
71
|
-
* the CMake-style file (VERSION_MAJOR = 4 / VERSION_MINOR = 3 / PATCHLEVEL = 99)
|
|
72
|
-
* and a bare "4.3.99".
|
|
73
|
-
*/
|
|
74
|
-
export function detectZephyrVersion(): string | undefined {
|
|
75
|
-
const base = process.env.ZEPHYR_BASE;
|
|
76
|
-
if (!base) return undefined;
|
|
77
|
-
let content: string;
|
|
78
|
-
try {
|
|
79
|
-
content = readFileSync(join(base, 'VERSION'), 'utf-8');
|
|
80
|
-
} catch {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
const field = (key: string): string | undefined => {
|
|
84
|
-
const m = content.match(new RegExp(`^\\s*${key}\\s*=\\s*(\\d+)`, 'm'));
|
|
85
|
-
return m ? m[1] : undefined;
|
|
86
|
-
};
|
|
87
|
-
const major = field('VERSION_MAJOR');
|
|
88
|
-
if (major !== undefined) {
|
|
89
|
-
return `${major}.${field('VERSION_MINOR') ?? 0}.${field('PATCHLEVEL') ?? 0}`;
|
|
90
|
-
}
|
|
91
|
-
const m = content.match(/(\d+\.\d+(?:\.\d+)?)/);
|
|
92
|
-
return m ? m[1] : undefined;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ── compat check ────────────────────────────────────────────────────────────
|
|
96
|
-
|
|
97
|
-
export type CompatStatus = 'ok' | 'undetectable' | 'out-of-range';
|
|
98
|
-
|
|
99
|
-
export interface CompatResult {
|
|
100
|
-
version: string | undefined;
|
|
101
|
-
/** Declared supported range (manifest.compat.zephyr), if any. */
|
|
102
|
-
range: string | undefined;
|
|
103
|
-
status: CompatStatus;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Compare the detected Zephyr version against the declared compat range. Pure:
|
|
108
|
-
* returns a status; the caller decides whether to throw/warn. 'ok' covers both
|
|
109
|
-
* "in range" and "no range declared".
|
|
110
|
-
*/
|
|
111
|
-
export function checkZephyrCompat(version: string | undefined): CompatResult {
|
|
112
|
-
const range = manifest.compat?.zephyr;
|
|
113
|
-
if (!range) return { version, range, status: 'ok' };
|
|
114
|
-
if (version === undefined) return { version, range, status: 'undetectable' };
|
|
115
|
-
return { version, range, status: satisfiesRange(version, range) ? 'ok' : 'out-of-range' };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// ── board-target normalization ──────────────────────────────────────────────
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* For Zephyr >=4.3, multi-core ESP32 boards require a qualified board target
|
|
122
|
-
* (board/<soc>/<core>) — the bare id is rejected with "Board qualifiers … not
|
|
123
|
-
* found". Map each known multi-core board id to its procpu (main app core)
|
|
124
|
-
* qualified form. procpu is the core that runs application firmware; appcpu is
|
|
125
|
-
* the secondary core (selected explicitly only when offloading to it).
|
|
126
|
-
*/
|
|
127
|
-
const QUALIFIED_TARGETS_GE_4_3: Record<string, string> = {
|
|
128
|
-
esp32_devkitc: 'esp32_devkitc/esp32/procpu',
|
|
129
|
-
esp32s3_devkitc: 'esp32s3_devkitc/esp32s3/procpu',
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Normalize a board target for the installed Zephyr version. Rewrites a stale
|
|
134
|
-
* bare id (esp32s3_devkitc) to the qualified form on Zephyr >=4.3; idempotent
|
|
135
|
-
* if the target is already qualified. Older Zephyr, single-core boards
|
|
136
|
-
* (xiao_ble), and unknown boards pass through unchanged.
|
|
137
|
-
*/
|
|
138
|
-
export function resolveBoardTarget(boardTarget: string, version: string | undefined): string {
|
|
139
|
-
const boardId = boardTarget.split('/')[0]!;
|
|
140
|
-
if (version !== undefined && satisfiesRange(version, '>=4.3')) {
|
|
141
|
-
const qualified = QUALIFIED_TARGETS_GE_4_3[boardId];
|
|
142
|
-
if (qualified) return qualified;
|
|
143
|
-
}
|
|
144
|
-
return boardTarget;
|
|
145
|
-
}
|