@kvell007/embed-labs-cli 0.1.0-alpha.30 → 0.1.0-alpha.31
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/index.js +84 -12
- package/dist/index.js.map +1 -1
- package/dist/local-toolchain.d.ts +4 -0
- package/dist/local-toolchain.js +208 -23
- package/dist/local-toolchain.js.map +1 -1
- package/package.json +3 -3
|
@@ -83,6 +83,7 @@ export interface LocalToolchainPackageManifest {
|
|
|
83
83
|
family?: string;
|
|
84
84
|
board?: string;
|
|
85
85
|
variant?: string;
|
|
86
|
+
board_id?: string;
|
|
86
87
|
requires?: Array<{
|
|
87
88
|
id: string;
|
|
88
89
|
version: string;
|
|
@@ -148,6 +149,7 @@ export interface LocalToolchainCurrentResult {
|
|
|
148
149
|
}
|
|
149
150
|
export interface LocalToolchainListOptions extends LocalToolchainLatestOptions {
|
|
150
151
|
installRoot?: string;
|
|
152
|
+
installedOnly?: boolean;
|
|
151
153
|
}
|
|
152
154
|
export interface LocalToolchainEnvironmentRecord {
|
|
153
155
|
board_id: string;
|
|
@@ -193,6 +195,7 @@ export interface LocalToolchainEnvironmentComponent {
|
|
|
193
195
|
export interface LocalToolchainListResult {
|
|
194
196
|
host: string;
|
|
195
197
|
channel: string;
|
|
198
|
+
metadata_source: "built_in" | "local_override";
|
|
196
199
|
metadata_root?: string;
|
|
197
200
|
install_root: string;
|
|
198
201
|
registry_path: string;
|
|
@@ -258,6 +261,7 @@ export declare function installLocalToolchain(options?: LocalToolchainInstallOpt
|
|
|
258
261
|
export declare function validateLocalToolchain(input?: string | {
|
|
259
262
|
releaseRoot?: string;
|
|
260
263
|
mode?: string;
|
|
264
|
+
boardId?: string;
|
|
261
265
|
}): Promise<LocalToolchainValidationResult>;
|
|
262
266
|
export declare function compileTaishanPiSingleFile(options: LocalCompileOptions): Promise<LocalCompileResult>;
|
|
263
267
|
export declare function buildTaishanPiQtSmoke(options: LocalQtSmokeBuildOptions): Promise<LocalCompileResult>;
|
package/dist/local-toolchain.js
CHANGED
|
@@ -9,8 +9,8 @@ import { pipeline } from "node:stream/promises";
|
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
const DEFAULT_RELEASE_ROOT = "/Volumes/LLVM-TSPI/tspi-rk3566-llvm-release-minimal";
|
|
11
11
|
const DEFAULT_QT_SMOKE_SOURCE = "/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi/qt-smoke";
|
|
12
|
-
const DEFAULT_METADATA_ROOT = "/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi/embedlabs-release";
|
|
13
12
|
const DEFAULT_BOARD_ID = "taishanpi-1m-rk3566";
|
|
13
|
+
const PICO2W_RP2350_BOARD_ID = "pico2w-rp2350-monitor";
|
|
14
14
|
const DEFAULT_CHANNEL = "stable";
|
|
15
15
|
const DEFAULT_DOWNLOAD_BASE_URL = "https://download.embedboard.com";
|
|
16
16
|
const DOWNLOAD_REQUEST_TIMEOUT_MS = 12_000;
|
|
@@ -24,7 +24,9 @@ const BUILT_IN_CHANNEL = {
|
|
|
24
24
|
{ id: "embedlabs.tools.runtime.qtquick-live-preview", version: "1.0.31", manifest: "" },
|
|
25
25
|
{ id: "embedlabs.tools.runtime.rp2350-monitor", version: "1.0.31", manifest: "" },
|
|
26
26
|
{ id: "embedlabs.family.rk356x", version: "1.0.0", manifest: "" },
|
|
27
|
-
{ id: "embedlabs.
|
|
27
|
+
{ id: "embedlabs.family.rp2350", version: "1.0.0", manifest: "" },
|
|
28
|
+
{ id: "embedlabs.board.taishanpi.1m-rk3566", version: "1.0.31", manifest: "" },
|
|
29
|
+
{ id: "embedlabs.board.pico2w.rp2350-monitor", version: "1.0.31", manifest: "" }
|
|
28
30
|
]
|
|
29
31
|
};
|
|
30
32
|
const BUILT_IN_MANIFESTS = {
|
|
@@ -80,6 +82,16 @@ const BUILT_IN_MANIFESTS = {
|
|
|
80
82
|
{ id: "embedlabs.tools.common.e2fsprogs", version: "^1.0.0" }
|
|
81
83
|
]
|
|
82
84
|
},
|
|
85
|
+
"embedlabs.family.rp2350": {
|
|
86
|
+
schema: "embedlabs.package.v1",
|
|
87
|
+
id: "embedlabs.family.rp2350",
|
|
88
|
+
version: "1.0.0",
|
|
89
|
+
kind: "family",
|
|
90
|
+
family: "rp2350",
|
|
91
|
+
requires: [
|
|
92
|
+
{ id: "embedlabs.tools.runtime.rp2350-monitor", version: "^1.0.31" }
|
|
93
|
+
]
|
|
94
|
+
},
|
|
83
95
|
"embedlabs.board.taishanpi.1m-rk3566": {
|
|
84
96
|
schema: "embedlabs.package.v1",
|
|
85
97
|
id: "embedlabs.board.taishanpi.1m-rk3566",
|
|
@@ -97,6 +109,22 @@ const BUILT_IN_MANIFESTS = {
|
|
|
97
109
|
{ id: "embedlabs.tools.runtime.rp2350-monitor", version: "^1.0.31", roles: ["rp2350-monitor"] }
|
|
98
110
|
],
|
|
99
111
|
build_modes: ["local-llvm"]
|
|
112
|
+
},
|
|
113
|
+
"embedlabs.board.pico2w.rp2350-monitor": {
|
|
114
|
+
schema: "embedlabs.package.v1",
|
|
115
|
+
id: "embedlabs.board.pico2w.rp2350-monitor",
|
|
116
|
+
version: "1.0.31",
|
|
117
|
+
kind: "board",
|
|
118
|
+
display_name: "Pico 2 W / RP2350 Monitor",
|
|
119
|
+
family: "rp2350",
|
|
120
|
+
board: "Pico 2 W",
|
|
121
|
+
variant: "RP2350 Monitor",
|
|
122
|
+
board_id: PICO2W_RP2350_BOARD_ID,
|
|
123
|
+
requires: [
|
|
124
|
+
{ id: "embedlabs.family.rp2350", version: "^1.0.0" },
|
|
125
|
+
{ id: "embedlabs.tools.runtime.rp2350-monitor", version: "^1.0.31", roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
|
|
126
|
+
],
|
|
127
|
+
build_modes: ["local-monitor"]
|
|
100
128
|
}
|
|
101
129
|
};
|
|
102
130
|
const INSTALL_COPY_PATHS = [
|
|
@@ -119,7 +147,7 @@ const INSTALL_COPY_PATHS = [
|
|
|
119
147
|
"support",
|
|
120
148
|
"third_party"
|
|
121
149
|
];
|
|
122
|
-
const LOCAL_TOOLCHAIN_INSTALL_MODES = ["minimal", "compile", "qt", "full", "images"];
|
|
150
|
+
const LOCAL_TOOLCHAIN_INSTALL_MODES = ["minimal", "runtime", "compile", "qt", "firmware", "full", "images"];
|
|
123
151
|
export function defaultLocalReleaseRoot() {
|
|
124
152
|
return process.env.EMBEDLABS_LOCAL_RELEASE_ROOT?.trim()
|
|
125
153
|
|| process.env.EMBEDLABS_RELEASE_ROOT?.trim()
|
|
@@ -134,12 +162,13 @@ export async function latestLocalToolchain(options = {}) {
|
|
|
134
162
|
if (!board) {
|
|
135
163
|
throw new Error(`No local toolchain board package found for ${boardId}.`);
|
|
136
164
|
}
|
|
165
|
+
const canonicalBoardId = boardIdForPackageManifest(board);
|
|
137
166
|
const packages = resolvePackageRefs(boardPackageId, channel, manifests);
|
|
138
167
|
let download;
|
|
139
168
|
let downloadError;
|
|
140
169
|
try {
|
|
141
170
|
download = await resolveLocalToolchainDownloadPlan({
|
|
142
|
-
boardId,
|
|
171
|
+
boardId: canonicalBoardId,
|
|
143
172
|
channel: channelName,
|
|
144
173
|
host: hostId(),
|
|
145
174
|
toolchain: "llvm"
|
|
@@ -149,7 +178,7 @@ export async function latestLocalToolchain(options = {}) {
|
|
|
149
178
|
downloadError = error instanceof Error ? error.message : String(error);
|
|
150
179
|
}
|
|
151
180
|
return {
|
|
152
|
-
board_id:
|
|
181
|
+
board_id: canonicalBoardId,
|
|
153
182
|
channel: channel.channel,
|
|
154
183
|
host: hostId(),
|
|
155
184
|
version: download?.version ?? board.version,
|
|
@@ -164,10 +193,34 @@ export async function currentLocalToolchain(installRoot, boardId = DEFAULT_BOARD
|
|
|
164
193
|
const registryPath = localToolchainRegistryPath(root);
|
|
165
194
|
try {
|
|
166
195
|
const registry = JSON.parse(await readFile(registryPath, "utf8"));
|
|
196
|
+
const environments = registry.environments;
|
|
197
|
+
const boardInstall = environments?.[normalizeBoardId(boardId)];
|
|
198
|
+
if (boardInstall?.release_root) {
|
|
199
|
+
return {
|
|
200
|
+
installed: true,
|
|
201
|
+
board_id: typeof boardInstall.board_id === "string" ? boardInstall.board_id : boardId,
|
|
202
|
+
version: typeof boardInstall.version === "string" ? boardInstall.version : undefined,
|
|
203
|
+
mode: typeof boardInstall.mode === "string" ? boardInstall.mode : undefined,
|
|
204
|
+
release_root: boardInstall.release_root,
|
|
205
|
+
registry_path: registryPath,
|
|
206
|
+
install_root: root,
|
|
207
|
+
channel: typeof boardInstall.channel === "string" ? boardInstall.channel : undefined,
|
|
208
|
+
packages: Array.isArray(boardInstall.packages) ? boardInstall.packages : undefined
|
|
209
|
+
};
|
|
210
|
+
}
|
|
167
211
|
const releaseRoot = typeof registry.release_root === "string" ? registry.release_root : undefined;
|
|
212
|
+
const registryBoardId = typeof registry.board_id === "string" ? registry.board_id : boardId;
|
|
213
|
+
if (releaseRoot && normalizeBoardId(registryBoardId) !== normalizeBoardId(boardId)) {
|
|
214
|
+
return {
|
|
215
|
+
installed: false,
|
|
216
|
+
board_id: boardId,
|
|
217
|
+
registry_path: registryPath,
|
|
218
|
+
install_root: root
|
|
219
|
+
};
|
|
220
|
+
}
|
|
168
221
|
return {
|
|
169
222
|
installed: !!releaseRoot,
|
|
170
|
-
board_id:
|
|
223
|
+
board_id: registryBoardId,
|
|
171
224
|
version: typeof registry.version === "string" ? registry.version : undefined,
|
|
172
225
|
mode: typeof registry.mode === "string" ? registry.mode : undefined,
|
|
173
226
|
release_root: releaseRoot,
|
|
@@ -186,6 +239,58 @@ export async function currentLocalToolchain(installRoot, boardId = DEFAULT_BOARD
|
|
|
186
239
|
};
|
|
187
240
|
}
|
|
188
241
|
}
|
|
242
|
+
async function discoverInstalledLocalToolchains(installRoot, current) {
|
|
243
|
+
const installed = new Map();
|
|
244
|
+
if (current.installed && current.release_root) {
|
|
245
|
+
installed.set(normalizeBoardId(current.board_id), {
|
|
246
|
+
board_id: current.board_id,
|
|
247
|
+
version: current.version,
|
|
248
|
+
channel: current.channel,
|
|
249
|
+
mode: current.mode,
|
|
250
|
+
release_root: current.release_root
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const toolchainsRoot = join(installRoot, "toolchains");
|
|
254
|
+
let boardEntries;
|
|
255
|
+
try {
|
|
256
|
+
boardEntries = await readdir(toolchainsRoot, { withFileTypes: true });
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return installed;
|
|
260
|
+
}
|
|
261
|
+
for (const boardEntry of boardEntries) {
|
|
262
|
+
if (!boardEntry.isDirectory()) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const boardId = normalizeBoardId(boardEntry.name);
|
|
266
|
+
if (installed.has(boardId)) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const boardRoot = join(toolchainsRoot, boardEntry.name);
|
|
270
|
+
let versionEntries;
|
|
271
|
+
try {
|
|
272
|
+
versionEntries = await readdir(boardRoot, { withFileTypes: true });
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const versions = versionEntries
|
|
278
|
+
.filter((entry) => entry.isDirectory())
|
|
279
|
+
.map((entry) => entry.name)
|
|
280
|
+
.sort(compareVersionLike)
|
|
281
|
+
.reverse();
|
|
282
|
+
const version = versions[0];
|
|
283
|
+
if (!version) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
installed.set(boardId, {
|
|
287
|
+
board_id: boardId,
|
|
288
|
+
version,
|
|
289
|
+
release_root: join(boardRoot, version)
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return installed;
|
|
293
|
+
}
|
|
189
294
|
export async function listLocalToolchainEnvironments(options = {}) {
|
|
190
295
|
const channelName = options.channel ?? DEFAULT_CHANNEL;
|
|
191
296
|
const host = hostId();
|
|
@@ -193,6 +298,7 @@ export async function listLocalToolchainEnvironments(options = {}) {
|
|
|
193
298
|
const registryPath = localToolchainRegistryPath(installRoot);
|
|
194
299
|
const { channel, manifests, metadataRoot } = await loadLocalToolchainMetadata(options.metadataRoot, channelName);
|
|
195
300
|
const current = await currentLocalToolchain(installRoot);
|
|
301
|
+
const installedByBoard = await discoverInstalledLocalToolchains(installRoot, current);
|
|
196
302
|
const boardManifests = [...manifests.values()]
|
|
197
303
|
.filter((manifest) => manifest.kind === "board")
|
|
198
304
|
.filter((manifest) => {
|
|
@@ -224,12 +330,16 @@ export async function listLocalToolchainEnvironments(options = {}) {
|
|
|
224
330
|
downloadError = error instanceof Error ? error.message : String(error);
|
|
225
331
|
}
|
|
226
332
|
const latestVersion = download?.version ?? board.version;
|
|
227
|
-
const
|
|
333
|
+
const currentForBoard = await currentLocalToolchain(installRoot, boardId);
|
|
334
|
+
const installedCandidate = currentForBoard.installed
|
|
335
|
+
? currentForBoard
|
|
336
|
+
: installedByBoard.get(normalizeBoardId(boardId));
|
|
337
|
+
const installed = installedCandidate
|
|
228
338
|
? {
|
|
229
|
-
version:
|
|
230
|
-
channel:
|
|
231
|
-
mode:
|
|
232
|
-
release_root:
|
|
339
|
+
version: installedCandidate.version,
|
|
340
|
+
channel: installedCandidate.channel,
|
|
341
|
+
mode: installedCandidate.mode,
|
|
342
|
+
release_root: installedCandidate.release_root
|
|
233
343
|
}
|
|
234
344
|
: undefined;
|
|
235
345
|
const updateAvailable = !!installed?.version && installed.version !== latestVersion;
|
|
@@ -241,6 +351,7 @@ export async function listLocalToolchainEnvironments(options = {}) {
|
|
|
241
351
|
? "installed"
|
|
242
352
|
: "available";
|
|
243
353
|
const mode = download?.default_mode ?? "qt";
|
|
354
|
+
const installModes = localToolchainInstallModesForDownload(download);
|
|
244
355
|
environments.push({
|
|
245
356
|
board_id: boardId,
|
|
246
357
|
package_id: board.id,
|
|
@@ -252,7 +363,7 @@ export async function listLocalToolchainEnvironments(options = {}) {
|
|
|
252
363
|
status,
|
|
253
364
|
supported_host: hostSupport.supported,
|
|
254
365
|
unsupported_packages: hostSupport.unsupportedPackages,
|
|
255
|
-
install_modes:
|
|
366
|
+
install_modes: installModes,
|
|
256
367
|
installed,
|
|
257
368
|
latest: {
|
|
258
369
|
version: latestVersion,
|
|
@@ -269,13 +380,17 @@ export async function listLocalToolchainEnvironments(options = {}) {
|
|
|
269
380
|
notes: environmentNotes({ status, downloadError, unsupportedPackages: hostSupport.unsupportedPackages })
|
|
270
381
|
});
|
|
271
382
|
}
|
|
383
|
+
const filteredEnvironments = options.installedOnly
|
|
384
|
+
? environments.filter((environment) => !!environment.installed)
|
|
385
|
+
: environments;
|
|
272
386
|
return {
|
|
273
387
|
host,
|
|
274
388
|
channel: channel.channel,
|
|
389
|
+
metadata_source: metadataRoot ? "local_override" : "built_in",
|
|
275
390
|
metadata_root: metadataRoot,
|
|
276
391
|
install_root: installRoot,
|
|
277
392
|
registry_path: registryPath,
|
|
278
|
-
environments
|
|
393
|
+
environments: filteredEnvironments
|
|
279
394
|
};
|
|
280
395
|
}
|
|
281
396
|
export async function installLocalToolchain(options = {}) {
|
|
@@ -284,7 +399,7 @@ export async function installLocalToolchain(options = {}) {
|
|
|
284
399
|
const releaseRoot = resolve(installRoot, "toolchains", latest.board_id, latest.version);
|
|
285
400
|
const installMode = normalizeLocalToolchainInstallMode(options.mode ?? latest.download?.default_mode);
|
|
286
401
|
if (await pathExists(releaseRoot) && !options.force) {
|
|
287
|
-
const validation = await validateLocalToolchain({ releaseRoot, mode: installMode });
|
|
402
|
+
const validation = await validateLocalToolchain({ releaseRoot, mode: installMode, boardId: latest.board_id });
|
|
288
403
|
if (!validation.ok) {
|
|
289
404
|
if (latest.download?.components?.length) {
|
|
290
405
|
// Component installs can upgrade an existing lower-mode install by overlaying
|
|
@@ -336,7 +451,7 @@ export async function installLocalToolchain(options = {}) {
|
|
|
336
451
|
installedPaths.push(relativePath);
|
|
337
452
|
}
|
|
338
453
|
await writeCurrentRegistry(installRoot, latest, releaseRoot, installMode, sourceRoot.source);
|
|
339
|
-
const validation = await validateLocalToolchain({ releaseRoot, mode: installMode });
|
|
454
|
+
const validation = await validateLocalToolchain({ releaseRoot, mode: installMode, boardId: latest.board_id });
|
|
340
455
|
if (!validation.ok) {
|
|
341
456
|
throw new Error(`Installed local toolchain is incomplete: ${validation.missing_paths.join(", ")}`);
|
|
342
457
|
}
|
|
@@ -362,8 +477,9 @@ export async function installLocalToolchain(options = {}) {
|
|
|
362
477
|
export async function validateLocalToolchain(input) {
|
|
363
478
|
const releaseRoot = typeof input === "string" ? input : input?.releaseRoot;
|
|
364
479
|
const mode = normalizeLocalToolchainInstallMode(typeof input === "string" ? undefined : input?.mode);
|
|
480
|
+
const boardId = normalizeBoardId(typeof input === "string" ? DEFAULT_BOARD_ID : input?.boardId ?? DEFAULT_BOARD_ID);
|
|
365
481
|
const resolvedRoot = await resolveLocalReleaseRoot(releaseRoot);
|
|
366
|
-
const required = requiredLocalToolchainChecks(mode);
|
|
482
|
+
const required = requiredLocalToolchainChecks(mode, boardId);
|
|
367
483
|
const checked_paths = [];
|
|
368
484
|
for (const [label, relativePath] of required) {
|
|
369
485
|
const absolutePath = resolve(resolvedRoot, relativePath);
|
|
@@ -381,13 +497,13 @@ export async function validateLocalToolchain(input) {
|
|
|
381
497
|
platform: platform(),
|
|
382
498
|
arch: arch()
|
|
383
499
|
},
|
|
384
|
-
board_id:
|
|
500
|
+
board_id: boardId,
|
|
385
501
|
release_root: resolvedRoot,
|
|
386
502
|
checked_paths,
|
|
387
503
|
missing_paths,
|
|
388
504
|
notes: [
|
|
389
505
|
"Local build commands require an Embed Labs auth token so local resource use remains account attributable.",
|
|
390
|
-
`This validator checks the
|
|
506
|
+
`This validator checks the ${boardId} local support layout for install mode ${mode}.`
|
|
391
507
|
]
|
|
392
508
|
};
|
|
393
509
|
}
|
|
@@ -401,7 +517,10 @@ function normalizeLocalToolchainInstallMode(mode) {
|
|
|
401
517
|
}
|
|
402
518
|
throw new Error(`Unsupported local toolchain install mode ${normalized}; expected ${LOCAL_TOOLCHAIN_INSTALL_MODES.join(", ")}.`);
|
|
403
519
|
}
|
|
404
|
-
function requiredLocalToolchainChecks(mode) {
|
|
520
|
+
function requiredLocalToolchainChecks(mode, boardId) {
|
|
521
|
+
if (boardId === PICO2W_RP2350_BOARD_ID || boardId === "rp2350" || boardId === "rp2350-monitor") {
|
|
522
|
+
return requiredRp2350MonitorChecks(mode);
|
|
523
|
+
}
|
|
405
524
|
const base = [
|
|
406
525
|
["release root", "."],
|
|
407
526
|
["Rockchip mkimage", "tools/mac/mkimage"],
|
|
@@ -452,6 +571,25 @@ function requiredLocalToolchainChecks(mode) {
|
|
|
452
571
|
}
|
|
453
572
|
return [...base, ...compile, ...qt, ...images, ...full];
|
|
454
573
|
}
|
|
574
|
+
function requiredRp2350MonitorChecks(mode) {
|
|
575
|
+
const runtime = [
|
|
576
|
+
["release root", "."],
|
|
577
|
+
["RP2350 Monitor UI", "toolkit-runtime/rp2350-monitor/ui/index.html"],
|
|
578
|
+
["RP2350 Monitor bridge", "toolkit-runtime/rp2350-monitor/ui/bridge/rpmon_bridge.py"],
|
|
579
|
+
["RP2350 Monitor CLI", "toolkit-runtime/rp2350-monitor/tools/rpmon_cli.py"],
|
|
580
|
+
["RP2350 Monitor logic analyzer", "toolkit-runtime/rp2350-monitor/ui/bin/embed-labs-logic-analyzer"],
|
|
581
|
+
["RP2350 Monitor AI operation contract", "toolkit-runtime/rp2350-monitor/ui/docs/ai-operation-contract.md"],
|
|
582
|
+
["package metadata", "meta"]
|
|
583
|
+
];
|
|
584
|
+
const firmware = [
|
|
585
|
+
["Pico 2 W monitor UF2", "toolkit-runtime/rp2350-monitor/firmware/rp2350_monitor.uf2"],
|
|
586
|
+
["Pico 2 W firmware source", "toolkit-runtime/rp2350-monitor/firmware/src/main.cpp"]
|
|
587
|
+
];
|
|
588
|
+
if (mode === "firmware" || mode === "full") {
|
|
589
|
+
return [...runtime, ...firmware];
|
|
590
|
+
}
|
|
591
|
+
return runtime;
|
|
592
|
+
}
|
|
455
593
|
export async function compileTaishanPiSingleFile(options) {
|
|
456
594
|
assertAuthenticated(options.auth);
|
|
457
595
|
const releaseRoot = await resolveLocalReleaseRoot(options.releaseRoot);
|
|
@@ -521,15 +659,14 @@ export async function buildTaishanPiQtSmoke(options) {
|
|
|
521
659
|
}
|
|
522
660
|
async function loadLocalToolchainMetadata(metadataRoot, channelName) {
|
|
523
661
|
const explicitRoot = metadataRoot || process.env.EMBEDLABS_METADATA_ROOT?.trim();
|
|
524
|
-
|
|
525
|
-
if (!candidateRoot) {
|
|
662
|
+
if (!explicitRoot) {
|
|
526
663
|
return {
|
|
527
664
|
channel: BUILT_IN_CHANNEL,
|
|
528
665
|
manifests: new Map(Object.entries(BUILT_IN_MANIFESTS)),
|
|
529
666
|
metadataRoot: undefined
|
|
530
667
|
};
|
|
531
668
|
}
|
|
532
|
-
const root = resolve(
|
|
669
|
+
const root = resolve(explicitRoot);
|
|
533
670
|
const channelPath = join(root, "channels", channelName, "index.json");
|
|
534
671
|
const channel = JSON.parse(await readFile(channelPath, "utf8"));
|
|
535
672
|
if (channel.schema !== "embedlabs.channel.v1") {
|
|
@@ -709,6 +846,14 @@ function boardPackageIdFor(boardId) {
|
|
|
709
846
|
if (boardId === DEFAULT_BOARD_ID || boardId === "taishanpi" || boardId === "taishanpi-1m-rk3566") {
|
|
710
847
|
return "embedlabs.board.taishanpi.1m-rk3566";
|
|
711
848
|
}
|
|
849
|
+
if (boardId === PICO2W_RP2350_BOARD_ID
|
|
850
|
+
|| boardId === "pico2w"
|
|
851
|
+
|| boardId === "pico-2-w"
|
|
852
|
+
|| boardId === "pico2"
|
|
853
|
+
|| boardId === "rp2350"
|
|
854
|
+
|| boardId === "rp2350-monitor") {
|
|
855
|
+
return "embedlabs.board.pico2w.rp2350-monitor";
|
|
856
|
+
}
|
|
712
857
|
if (boardId.startsWith("embedlabs.board.")) {
|
|
713
858
|
return boardId;
|
|
714
859
|
}
|
|
@@ -738,6 +883,12 @@ function boardIdForPackageManifest(manifest) {
|
|
|
738
883
|
function normalizeBoardId(boardId) {
|
|
739
884
|
return boardId.trim().toLowerCase().replaceAll("_", "-");
|
|
740
885
|
}
|
|
886
|
+
function compareVersionLike(left, right) {
|
|
887
|
+
return left.localeCompare(right, undefined, { numeric: true, sensitivity: "base" });
|
|
888
|
+
}
|
|
889
|
+
function isRecord(value) {
|
|
890
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
891
|
+
}
|
|
741
892
|
function packageHostSupport(packages, manifests, host) {
|
|
742
893
|
const unsupportedPackages = [];
|
|
743
894
|
for (const item of packages) {
|
|
@@ -767,6 +918,20 @@ function environmentNotes(input) {
|
|
|
767
918
|
}
|
|
768
919
|
return notes;
|
|
769
920
|
}
|
|
921
|
+
function localToolchainInstallModesForDownload(download) {
|
|
922
|
+
if (!download?.components?.length) {
|
|
923
|
+
return [...LOCAL_TOOLCHAIN_INSTALL_MODES];
|
|
924
|
+
}
|
|
925
|
+
const modes = new Set();
|
|
926
|
+
for (const component of download.components) {
|
|
927
|
+
for (const mode of component.install_modes ?? []) {
|
|
928
|
+
modes.add(mode);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return modes.size > 0
|
|
932
|
+
? [...modes].filter((mode) => LOCAL_TOOLCHAIN_INSTALL_MODES.includes(mode))
|
|
933
|
+
: [...LOCAL_TOOLCHAIN_INSTALL_MODES];
|
|
934
|
+
}
|
|
770
935
|
function localToolchainEnvironmentComponent(component) {
|
|
771
936
|
return {
|
|
772
937
|
id: component.id,
|
|
@@ -798,7 +963,14 @@ function localToolchainRegistryPath(installRoot) {
|
|
|
798
963
|
async function writeCurrentRegistry(installRoot, latest, releaseRoot, mode, source) {
|
|
799
964
|
const registryPath = localToolchainRegistryPath(installRoot);
|
|
800
965
|
await mkdir(dirname(registryPath), { recursive: true });
|
|
801
|
-
|
|
966
|
+
let existing = {};
|
|
967
|
+
try {
|
|
968
|
+
existing = JSON.parse(await readFile(registryPath, "utf8"));
|
|
969
|
+
}
|
|
970
|
+
catch {
|
|
971
|
+
existing = {};
|
|
972
|
+
}
|
|
973
|
+
const entry = {
|
|
802
974
|
installed: true,
|
|
803
975
|
board_id: latest.board_id,
|
|
804
976
|
version: latest.version,
|
|
@@ -810,6 +982,19 @@ async function writeCurrentRegistry(installRoot, latest, releaseRoot, mode, sour
|
|
|
810
982
|
source,
|
|
811
983
|
installed_components: source?.components,
|
|
812
984
|
updated_at: new Date().toISOString()
|
|
985
|
+
};
|
|
986
|
+
const environments = isRecord(existing.environments)
|
|
987
|
+
? { ...existing.environments }
|
|
988
|
+
: {};
|
|
989
|
+
environments[normalizeBoardId(latest.board_id)] = entry;
|
|
990
|
+
const preserveTopLevel = latest.board_id !== DEFAULT_BOARD_ID
|
|
991
|
+
&& typeof existing.release_root === "string"
|
|
992
|
+
&& normalizeBoardId(String(existing.board_id ?? DEFAULT_BOARD_ID)) === DEFAULT_BOARD_ID;
|
|
993
|
+
const topLevel = preserveTopLevel ? existing : entry;
|
|
994
|
+
await writeFile(registryPath, `${JSON.stringify({
|
|
995
|
+
...topLevel,
|
|
996
|
+
environments,
|
|
997
|
+
updated_at: new Date().toISOString()
|
|
813
998
|
}, null, 2)}\n`, "utf8");
|
|
814
999
|
}
|
|
815
1000
|
async function resolveLocalReleaseRoot(releaseRoot) {
|