From 07aea4bf6a1d90e09396de4c02f96f545dd1989e Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sat, 3 Oct 2026 15:51:12 +0200 Subject: [PATCH] cc65: only append warnings when errors are present --- CHANGELOG.md | 1 + src/worker/tools/cc65.ts | 31 +++++++++++++++++++++---------- test/cli/testworker.js | 3 +++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cf7fffd..af28bc88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ See [extension/CHANGELOG.md](extension/CHANGELOG.md). - Emulators now run on a timeline: step back, seek, reverse run, `rbreak`, and deterministic replay with a replay-verification test that found determinism bugs in several platforms. - Step Over for C and assembly sources, a Breakpoints pane, and more breakpoint conditions. - Call Stack view renamed Call Graph, with clocks and more detail per line. +- cc65/ca65/ld65 warnings are still ignored on a successful build, but are now listed with the errors when a build fails. - Reset clears the call graph; breakpoints are re-armed after a build. - Click the hex offset in the gutter to run to that line. - Waveform viewer for Verilog, with help and shortcuts. diff --git a/src/worker/tools/cc65.ts b/src/worker/tools/cc65.ts index 83eef8eb..265717fa 100644 --- a/src/worker/tools/cc65.ts +++ b/src/worker/tools/cc65.ts @@ -11,10 +11,19 @@ import { wasiFSAdapter, runWASITool, checkExitCode, readWASIOutput, readWASIOutp const CC65_SHARE = 'share/cc65'; // cc65/ca65/ld65 report both errors and non-fatal warnings as -// ":: : " on stderr; skip the warnings so a -// clean build with only style/deprecation warnings doesn't fail. +// ":: : " on stderr; warnings don't fail a +// build, and are only reported when the build fails (see matchCC65Errors). const re_cc65_warning = /:\s*Warning:/; +// collect errors from stderr; if the tool failed, append its warnings as context +function matchCC65Errors(tool: string, errno: number, stderr: string[], errors: WorkerError[], + regex: RegExp, iline: number, imsg: number, path: string) { + const match = makeErrorMatcher(errors, regex, iline, imsg, path, 1); + stderr.filter(s => !re_cc65_warning.test(s)).forEach(match); + checkExitCode(tool, errno, stderr, errors); + if (errors.length) stderr.filter(s => re_cc65_warning.test(s)).forEach(match); +} + const wasiModules: { [tool: string]: WebAssembly.Module } = {}; /** @@ -155,8 +164,7 @@ export async function assembleCA65(step: BuildStep): Promise { .concat(extraArgsFor('ca65', step.params.buildArgs)); args.splice(args.length - 1, 0, ...extra); const { wasi, errno, stderr } = await runCC65Tool(step, 'ca65', args, (fs) => populateFiles(step, fs)); - stderr.filter(s => !re_cc65_warning.test(s)).forEach(makeErrorMatcher(errors, /(.+?):(\d+): (.+)/, 2, 3, step.path, 1)); - checkExitCode('ca65', errno, stderr, errors); + matchCC65Errors('ca65', errno, stderr, errors, /(.+?):(\d+): (.+)/, 2, 3, step.path); if (errors.length) { let listings : CodeListingMap = {}; // TODO? change extension to .lst @@ -199,14 +207,18 @@ export async function linkLD65(step: BuildStep): Promise { populateEntry(fs, params.cfgfile, store.getFileEntry(params.cfgfile), null); } }); - // any non-warning ld65 message fails the build; again, "Warning:"-severity + // any non-warning ld65 message fails the build; "Warning:"-severity // output (e.g. the sp->c_sp deprecation from our prebuilt crt0.o/neslib2.lib) - // is non-fatal noise the user can't act on. + // is non-fatal noise, shown only if the link fails. for (let s of stderr) { - if (re_cc65_warning.test(s)) continue; - errors.push({ msg: s, line: 0 }); + if (!re_cc65_warning.test(s)) errors.push({ msg: s, line: 0 }); } checkExitCode('ld65', errno, stderr, errors); + if (errors.length) { + for (let s of stderr) { + if (re_cc65_warning.test(s)) errors.push({ msg: s, line: 0 }); + } + } if (errors.length) return { errors: errors }; var aout = readWASIOutput(wasi, "main"); @@ -349,8 +361,7 @@ export async function compileCC65(step: BuildStep): Promise { }); populateExtraFiles(step, fs, params.extra_compile_files); }); - stderr.filter(s => !re_cc65_warning.test(s)).forEach(makeErrorMatcher(errors, /(.*?):(\d+): (.+)/, 2, 3, step.path, 1)); - checkExitCode('cc65', errno, stderr, errors); + matchCC65Errors('cc65', errno, stderr, errors, /(.*?):(\d+): (.+)/, 2, 3, step.path); if (errors.length) return { errors }; putWorkFile(destpath, readWASIOutputString(wasi, destpath)); } diff --git a/test/cli/testworker.js b/test/cli/testworker.js index 313867ab..51375d9d 100644 --- a/test/cli/testworker.js +++ b/test/cli/testworker.js @@ -169,6 +169,9 @@ describe('Worker', function() { it('should NOT compile CC65 (compile error)', function(done) { compile('cc65', 'int main() {\nint x=1;\nprintf("%d",x);\nreturn x+2;\n}', 'nes', done, 0, 0, 1); }); + it('should report CC65 warnings along with errors', function(done) { + compile('cc65', 'int main() {\nconst const int x=1;\nreturn y;\n}', 'nes', done, 0, 0, 2); + }); it('should NOT compile CC65 (link error)', function(done) { compile('cc65', 'extern void bad();\nint main() {\nbad();\nreturn 0;\n}', 'nes', done, 0, 0, 1, {ignoreErrorPath:true}); });