refactored stuff into BuildProducts

This commit is contained in:
Steven Hugg committed 2026-10-01 11:11:52 +02:00
1 parent 2de55caa60
commit 777e1b68fd
10 files changed
+46 -47

No files matched your search

+4 -8
View File
@@ -4,7 +4,8 @@
import * as fs from 'fs';
import * as path from 'path';
import type { CodeListingMap, FileData, Segment, WorkerError, WorkerErrorResult, WorkerResult } from "../../src/common/workertypes";
import type { BuildProducts, FileData, WorkerError, WorkerErrorResult, WorkerResult } from "../../src/common/workertypes";
import { buildProducts } from "../../src/common/workertypes";
import { toInternalError } from "../../src/common/telemetry";
import { getBasePlatform, isProbablyBinary } from "../../src/common/util";
import { getToolForPlatform } from "../../src/common/toolselect";
@@ -33,16 +34,11 @@ export interface BuildDiagnostic {
msg: string;
}
export interface BuildOutcome {
export interface BuildOutcome extends BuildProducts {
success: boolean;
tool: string;
output?: Uint8Array;
diagnostics: BuildDiagnostic[];
listings?: CodeListingMap;
symbolmap?: { [sym: string]: number };
/** symbol -> size in bytes, for the toolchains that report it */
symbolsizes?: { [sym: string]: number };
segments?: Segment[];
/** every project path the build read */
paths: string[];
/**
@@ -142,7 +138,7 @@ export class Builder {
var r = result as any;
var outcome: BuildOutcome = {
success: true, tool, paths, files, diagnostics: [],
output: r.output, listings: r.listings, symbolmap: r.symbolmap, symbolsizes: r.symbolsizes, segments: r.segments,
output: r.output, ...buildProducts(r),
};
this.last.set(key, outcome);
return outcome;
+3 -2
View File
@@ -19,6 +19,7 @@ import { BuildReason, BuildScheduler } from './autobuild';
import { PRESET_SCHEME, PresetFileSystem, Templates } from './templates';
import { chooseForFile, detectDirectoryAt, detectionSummary, describeDetection, describeFinding, dontAskKey, FolderFinding, platformName, scanFolder } from './detection';
import { Detection, classifyFinding, isBuildableSource } from '../../src/common/detect';
import { buildProducts } from '../../src/common/workertypes';
import { TOOL_META } from '../../src/common/toolmeta';
import { ASSET_URLS, AssetStore } from './assets';
import { projectReadme, writeLauncher } from './terminalcli';
@@ -398,7 +399,7 @@ async function runScriptHeadless(target: Target, build: BuildOutcome, script: st
var run = async () => {
await worker.call('start', target.platform, build.output, build.files, { paused: true });
var mainPath = path.posix.basename(target.main.path);
return worker.call<ScriptResult>('script', script, { listings: build.listings, symbols: build.symbolmap, mainPath, paths: build.paths });
return worker.call<ScriptResult>('script', script, { ...buildProducts(build), mainPath, paths: build.paths });
};
return await Promise.race([run(), stop]);
} finally {
@@ -1426,6 +1427,6 @@ async function launchForDebug(folder: vscode.WorkspaceFolder | undefined, args:
if (!result.output) throw new Error('the build produced no ROM to run');
if (!await startEmulator(target, result, { paused: true })) throw new Error('the emulator failed to start; see Output');
var mainPath = path.posix.basename(target.main.path);
await emu!.call('debug', 'setBuild', { listings: result.listings, symbols: result.symbolmap, symbolsizes: result.symbolsizes, mainPath, paths: result.paths });
await emu!.call('debug', 'setBuild', { ...buildProducts(result), mainPath, paths: result.paths });
return { root: path.dirname(target.main.fsPath) };
}
+5 -5
View File
@@ -160,7 +160,7 @@ describe('extension emuworker', function () {
files: new ProjectFileProvider(read, ROOT, 'nes'),
});
await rpc.call('start', 'nes', nes.output, nes.files, { paused: true });
var build = { listings: nes.listings, symbols: nes.symbolmap, mainPath: 'attributes.c', paths: nes.paths };
var build = { listings: nes.listings, symbolmap: nes.symbolmap, mainPath: 'attributes.c', paths: nes.paths };
var r = await rpc.call<ScriptResult>('script', 'run 30; mem main 4', build);
assert.equal(r.error, undefined);
assert.equal(r.frame, 30);
@@ -251,7 +251,7 @@ describe('extension emuworker', function () {
it('starts stopped, then stops at a source breakpoint, steps, and steps back', async function () {
var s = await rpc.call<EmuStatus>('start', 'mw8080bw', built.output, built.files, { paused: true });
assert.equal(s.state, 'paused');
await debug('setBuild', { listings: built.listings, symbols: built.symbolmap, mainPath: 'game2.c', paths: built.paths });
await debug('setBuild', { listings: built.listings, symbolmap: built.symbolmap, mainPath: 'game2.c', paths: built.paths });
var [bp] = await debug('setBreakpoints', [{ id: 1, type: 'source', file: 'game2.c', line: 166, enabled: true }]);
assert.ok(bp.verified, bp.message);
await debug('continue');
@@ -280,7 +280,7 @@ describe('extension emuworker', function () {
});
assert.deepEqual(nes.diagnostics, []);
await rpc.call('start', 'nes', nes.output, nes.files, { paused: true });
await debug('setBuild', { listings: nes.listings, symbols: nes.symbolmap, mainPath: 'hello.c', paths: nes.paths });
await debug('setBuild', { listings: nes.listings, symbolmap: nes.symbolmap, mainPath: 'hello.c', paths: nes.paths });
var [bp] = await debug('setBreakpoints', [{ id: 1, type: 'source', file: 'hello.c', line: 19, enabled: true }]);
assert.ok(bp.verified, bp.message);
await debug('continue');
@@ -306,7 +306,7 @@ describe('extension emuworker', function () {
files: new ProjectFileProvider(read, ROOT, 'nes'),
});
await rpc.call('start', 'nes', nes.output, nes.files, { paused: true });
await debug('setBuild', { listings: nes.listings, symbols: nes.symbolmap, mainPath: 'scroll.c', paths: nes.paths });
await debug('setBuild', { listings: nes.listings, symbolmap: nes.symbolmap, mainPath: 'scroll.c', paths: nes.paths });
var caps = await debug('capabilities');
assert.equal(caps.tree, true);
assert.equal(caps.write, true);
@@ -333,7 +333,7 @@ describe('extension emuworker', function () {
it('drives the debug adapter through the worker, as the extension does', async function () {
var backend = new WorkerDebugBackend((method, ...args) => rpc.call('debug', method, ...args), async () => {
await rpc.call('start', 'mw8080bw', built.output, built.files, { paused: true });
await rpc.call('debug', 'setBuild', { listings: built.listings, symbols: built.symbolmap, mainPath: 'game2.c', paths: built.paths });
await rpc.call('debug', 'setBuild', { listings: built.listings, symbolmap: built.symbolmap, mainPath: 'game2.c', paths: built.paths });
return { root: '/proj' };
}, async () => { });
rpc.on('stopped', e => backend.handleStop(e));
+11 -10
View File
@@ -13,7 +13,7 @@ import { DEFAULT_MAX_FRAMES, EmuCore } from "./emucore";
import { getListingForFile, processListings, stripLocalPath } from "./projectcore";
import { Timestamp, timestamp, timestampsEqual } from "./timeline";
import { getFilenameForPath, getFilenamePrefix } from "./util";
import { CodeListingMap, SourceFile, SourceLine, SourceLocation } from "./workertypes";
import { BuildProducts, CodeListingMap, SourceFile, SourceLine, SourceLocation } from "./workertypes";
export type StopReason = 'breakpoint' | 'step' | 'pause' | 'goto' | 'entry' | 'halt' | 'exception';
@@ -371,17 +371,18 @@ function sameLine(a: SourceLocation, b: SourceLocation): boolean {
return a.line === b.line && a.path === b.path;
}
/** A build's products, and the project files they came from. */
export interface BuildInfo extends BuildProducts {
mainPath: string;
/** the project files, which name the source a listing came from */
paths?: string[];
}
/**
* A DebugContext from a build: source lines from its listings, and symbols.
* `paths` are the project files, which name the source a listing came from.
*/
export function buildDebugContext(build: {
listings?: CodeListingMap,
symbols?: { [name: string]: number },
symbolsizes?: { [name: string]: number },
mainPath: string,
paths?: string[],
}): DebugContext {
export function buildDebugContext(build: BuildInfo): DebugContext {
const listings = build.listings || {};
// listings that came over an RPC have lost their SourceFile methods
if (Object.values(listings).some(l => l.lines && !(l.sourcefile instanceof SourceFile))) processListings(listings);
@@ -390,9 +391,9 @@ export function buildDebugContext(build: {
const want = getFilenamePrefix(getFilenameForPath(stripLocalPath(name, build.mainPath)));
return paths.find(p => getFilenamePrefix(getFilenameForPath(p)) === want) || name;
};
const symbolAddrs = [...new Set(Object.values(build.symbols || {}))].sort((a, b) => a - b);
const symbolAddrs = [...new Set(Object.values(build.symbolmap || {}))].sort((a, b) => a - b);
return {
symbols: build.symbols,
symbols: build.symbolmap,
symbolsizes: build.symbolsizes,
getListingForFile: path => getListingForFile(listings, path, build.mainPath),
sourceAt(pc: number) {
+12
View File
@@ -203,6 +203,18 @@ export interface WorkerOutputResult<T> {
origin?: number
}
/**
* What a build produces for the debugger and the memory map, besides the ROM.
* Types that carry a build's products extend this, and `buildProducts` copies
* them, so a new field is added here and in that function only.
*/
export type BuildProducts = Pick<WorkerOutputResult<unknown>, 'listings' | 'symbolmap' | 'symbolsizes' | 'segments'>;
export function buildProducts(r: BuildProducts): BuildProducts {
const { listings, symbolmap, symbolsizes, segments } = r;
return { listings, symbolmap, symbolsizes, segments };
}
export function isUnchanged(result: WorkerResult) : result is WorkerUnchangedResult {
return ('unchanged' in result);
}
+2 -1
View File
@@ -19,6 +19,7 @@ import { EmuTarget, loadPlatform } from './emutarget';
import { RUN_SCRIPT_HELP, RunScript, parseNum } from './runscript';
import { verifyReplay } from './verifyreplay';
import { buildDebugContext } from '../common/debugcontroller';
import { buildProducts } from '../common/workertypes';
import type { BuildInfo } from './debugservice';
import { parseSymbolFile } from '../common/symbols/symbolfile';
import { romBytes, type CompileResult } from './testlib';
@@ -297,7 +298,7 @@ async function openProgram(command: string, args: Args, input: string): Promise<
let debugInfo: BuildInfo | undefined;
if (built) {
const mainPath = path.basename(input);
debugInfo = { listings: built.result.listings, symbols, symbolsizes: built.result.symbolsizes, mainPath, paths: [mainPath] };
debugInfo = { ...buildProducts(built.result), mainPath, paths: [mainPath] };
}
return { target, source: input, romFile, built, symbols, debugInfo };
}
+3 -9
View File
@@ -10,7 +10,7 @@ import { Breakpoint, makeCondContext } from '../common/breakpoints';
import { compileExpression } from '../common/breakcond';
import { TreeEntry, treeChildren } from '../common/debugtree';
import { walkStack } from '../common/stackwalk';
import { buildDebugContext, DebugController, DebugLocation, StepGranularity, StopEvent } from '../common/debugcontroller';
import { buildDebugContext, BuildInfo, DebugController, DebugLocation, StepGranularity, StopEvent } from '../common/debugcontroller';
import { resolveSymbolName } from '../common/symbols/symbolfile';
import { formatSymbolValue, MAX_SYMBOL_BYTES, SymbolValue } from '../common/symbols/symbolvalue';
import { Granularity, Timestamp } from '../common/timeline';
@@ -74,6 +74,8 @@ export interface EvalResult {
moved?: boolean;
}
export type { BuildInfo };
export interface TimelineInfo {
first: number;
last: number;
@@ -81,14 +83,6 @@ export interface TimelineInfo {
past: boolean;
}
export interface BuildInfo {
listings?: CodeListingMap;
symbols?: { [name: string]: number };
symbolsizes?: { [name: string]: number };
mainPath: string;
paths?: string[];
}
// how far before an address to start disassembling, per instruction wanted
const MAX_INSN_BYTES = 4;
+4 -10
View File
@@ -5,7 +5,8 @@
import * as fs from 'fs';
import * as path from 'path';
import type { WorkerResult, WorkerErrorResult, WorkerMessage, BuildArgLists, BuildSymbolLists, FileData } from "../common/workertypes";
import type { WorkerResult, WorkerErrorResult, WorkerMessage, BuildArgLists, BuildSymbolLists, FileData, BuildProducts } from "../common/workertypes";
import { buildProducts } from "../common/workertypes";
import { isProbablyBinary, getBasePlatform } from "../common/util";
import { getToolForPlatform } from "../common/toolselect";
import { FileProvider, buildWorkerMessage, resolveDependencies } from "../common/projectcore";
@@ -30,14 +31,10 @@ export interface CompileOptions {
buildArgs?: BuildArgLists;
}
export interface CompileResult {
export interface CompileResult extends BuildProducts {
success: boolean;
output?: Uint8Array | any;
errors?: { line: number; msg: string; path?: string }[];
listings?: any;
symbolmap?: any;
symbolsizes?: { [sym: string]: number };
segments?: any;
params?: any;
unchanged?: boolean;
/** every file the build read, by worker filename (verilog's $readmem reads them at load time) */
@@ -224,11 +221,8 @@ function workerResultToCompileResult(result: WorkerResult): CompileResult {
return {
success: true,
output: result.output,
listings: (result as any).listings,
symbolmap: (result as any).symbolmap,
symbolsizes: (result as any).symbolsizes,
segments: (result as any).segments,
params: (result as any).params,
...buildProducts(result),
};
}
return { success: false, errors: [{ line: 0, msg: 'Unknown result format' }] };
+1 -1
View File
@@ -19,7 +19,7 @@ async function launch(args: any = {}): Promise<DapClient> {
const target = await loadPlatform('mw8080bw');
await target.start();
await target.loadROM(build.output);
return { target, root: ROOT, debugInfo: { listings: build.listings, symbols: build.symbolmap, symbolsizes: { _draw_char: 4, _main: 100 }, mainPath: 'game2.c' } };
return { target, root: ROOT, debugInfo: { listings: build.listings, symbolmap: build.symbolmap, symbolsizes: { _draw_char: 4, _main: 100 }, mainPath: 'game2.c' } };
});
const c = new DapClient(new EmuDebugSession(backend));
const caps = await c.request('initialize', { adapterID: '8bitworkshop', linesStartAt1: true, columnsStartAt1: true, pathFormat: 'path' });
+1 -1
View File
@@ -17,7 +17,7 @@ async function open(): Promise<{ t: EmuTarget, dc: DebugController }> {
const t = await loadPlatform('mw8080bw');
await t.start();
await t.loadROM(build.output);
const dc = new DebugController(t, buildDebugContext({ listings: build.listings, symbols: build.symbolmap, mainPath: 'game2.c' }));
const dc = new DebugController(t, buildDebugContext({ listings: build.listings, symbolmap: build.symbolmap, mainPath: 'game2.c' }));
return { t, dc };
}