diff --git a/developer/src/kmc/src/commands/build.ts b/developer/src/kmc/src/commands/build.ts
index 2f21bb89c3..ddd916f34d 100644
--- a/developer/src/kmc/src/commands/build.ts
+++ b/developer/src/kmc/src/commands/build.ts
@@ -31,7 +31,8 @@ export function declareBuild(program: Command) {
.description('Build a source file into a final file')
)
.option('-d, --debug', 'Include debug information in output')
- .option('-w, --compiler-warnings-as-errors', 'Causes warnings to fail the build')
+ .option('-w, --compiler-warnings-as-errors', 'Causes warnings to fail the build; overrides project-level warnings-as-errors option')
+ .option('-W, --no-compiler-warnings-as-errors', 'Warnings do not fail the build; overrides project-level warnings-as-errors option')
.option('--no-compiler-version', 'Exclude compiler version metadata from output')
.option('--no-warn-deprecated-code', 'Turn off warnings for deprecated code styles')
.option('--color', 'Force colorization for log messages')
diff --git a/developer/src/kmc/test/fixtures/.gitignore b/developer/src/kmc/test/fixtures/.gitignore
index de01b143c3..7fd50f4386 100644
--- a/developer/src/kmc/test/fixtures/.gitignore
+++ b/developer/src/kmc/test/fixtures/.gitignore
@@ -1,3 +1,4 @@
*/*/build
relative_paths/*.kmp
relative_paths/*.kmx
+compiler-warnings-as-errors/*.kmx
diff --git a/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_false.kpj b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_false.kpj
new file mode 100644
index 0000000000..4788070323
--- /dev/null
+++ b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_false.kpj
@@ -0,0 +1,23 @@
+
+
+
+ $PROJECTPATH
+ False
+ False
+ False
+ keyboard
+
+
+
+ keyboard_1
+ keyboard.kmn
+ keyboard.kmn
+ 1.0
+ .kmn
+
+ keyboard
+ Copyright (C) Keyman Team
+
+
+
+
diff --git a/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_true.kpj b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_true.kpj
new file mode 100644
index 0000000000..c671b37358
--- /dev/null
+++ b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_true.kpj
@@ -0,0 +1,23 @@
+
+
+
+ $PROJECTPATH
+ True
+ False
+ False
+ keyboard
+
+
+
+ keyboard_1
+ keyboard.kmn
+ keyboard.kmn
+ 1.0
+ .kmn
+
+ keyboard
+ Copyright (C) Keyman Team
+
+
+
+
diff --git a/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_undefined.kpj b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_undefined.kpj
new file mode 100644
index 0000000000..621c22ddad
--- /dev/null
+++ b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/compiler_warnings_as_errors_undefined.kpj
@@ -0,0 +1,22 @@
+
+
+
+ $PROJECTPATH
+ False
+ False
+ keyboard
+
+
+
+ keyboard_1
+ keyboard.kmn
+ keyboard.kmn
+ 1.0
+ .kmn
+
+ keyboard
+ Copyright (C) Keyman Team
+
+
+
+
diff --git a/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/keyboard.kmn b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/keyboard.kmn
new file mode 100644
index 0000000000..87e5b263c0
--- /dev/null
+++ b/developer/src/kmc/test/fixtures/compiler-warnings-as-errors/keyboard.kmn
@@ -0,0 +1,10 @@
+store(&NAME) '000 - null keyboard'
+store(&version) '6.0'
+
+c The following line generates warn KM0209D: Header statements are deprecated; use instead the equivalent system store
+LANGUAGE x1, x1
+
+begin Unicode > use(Main)
+
+group(Main) using keys
+
diff --git a/developer/src/kmc/test/test-build.ts b/developer/src/kmc/test/test-build.ts
new file mode 100644
index 0000000000..adee69f98b
--- /dev/null
+++ b/developer/src/kmc/test/test-build.ts
@@ -0,0 +1,45 @@
+import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
+import { assert } from 'chai';
+import 'mocha';
+import { BuildProject } from '../src/commands/buildClasses/BuildProject.js';
+import { makePathToFixture } from './helpers/index.js';
+
+const callbacks = new TestCompilerCallbacks();
+
+interface CompilerWarningsAsErrorsTruthTable {
+ cli: boolean;
+ kpj: boolean;
+ result: boolean;
+};
+
+describe('compilerWarningsAsErrors', function () {
+ beforeEach(() => callbacks.clear());
+
+ // The CLI option should override the project setting
+
+ const truthTable: CompilerWarningsAsErrorsTruthTable[] = [
+ {cli:undefined, kpj:undefined, result:true}, // default setting (false) wins
+ {cli:undefined, kpj:false, result:true}, // kpj setting wins
+ {cli:undefined, kpj:true, result:false}, // kpj setting wins
+ {cli:false, kpj:undefined, result:true}, // cli setting wins
+ {cli:false, kpj:false, result:true}, // cli setting wins
+ {cli:false, kpj:true, result:true}, // cli setting wins
+ {cli:true, kpj:undefined, result:false}, // cli setting wins
+ {cli:true, kpj:false, result:false}, // cli setting wins
+ {cli:true, kpj:true, result:false}, // cli setting wins
+ ]
+
+ for(const truth of truthTable) {
+ it(`should ${truth.result?'':'fail to '}build a project when kpj option=${truth.kpj} and cli option=${truth.cli}`, async function() {
+ const builder = new BuildProject();
+ const path = makePathToFixture('compiler-warnings-as-errors',
+ `compiler_warnings_as_errors_${truth.kpj === true ? 'true' : (truth.kpj === false ? 'false' : 'undefined')}.kpj`);
+ const result = await builder.build(path, callbacks, {compilerWarningsAsErrors: truth.cli});
+ if(truth.result) {
+ assert.isTrue(result);
+ } else {
+ assert.isFalse(result);
+ }
+ });
+ }
+});