Print build failures with qmk mass-compile and qmk userspace-compile if requested (-p/--print-failures) (#25518)

This commit is contained in:
Nick Brassel 2025-09-10 02:35:01 +10:00 committed by GitHub
parent 4fc14c2712
commit f6f627d07f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 7 deletions

View File

@ -631,14 +631,15 @@ This command compiles all the External Userspace build targets.
**Usage**: **Usage**:
``` ```
qmk userspace-compile [-h] [-e ENV] [-n] [-c] [-j PARALLEL] [-t] qmk userspace-compile [-h] [-e ENV] [-p] [-n] [-c] [-j PARALLEL] [-t]
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit
-e ENV, --env ENV Set a variable to be passed to make. May be passed multiple times. -e, --env ENV Set a variable to be passed to make. May be passed multiple times.
-p, --print-failures Print failed builds.
-n, --dry-run Don't actually build, just show the commands to be run. -n, --dry-run Don't actually build, just show the commands to be run.
-c, --clean Remove object files before compiling. -c, --clean Remove object files before compiling.
-j PARALLEL, --parallel PARALLEL -j, --parallel PARALLEL
Set the number of parallel make jobs; 0 means unlimited. Set the number of parallel make jobs; 0 means unlimited.
-t, --no-temp Remove temporary files during build. -t, --no-temp Remove temporary files during build.
``` ```

View File

@ -16,7 +16,7 @@ from qmk.build_targets import BuildTarget, JsonKeymapBuildTarget
from qmk.util import maybe_exit_config from qmk.util import maybe_exit_config
def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool, no_temp: bool, parallel: int, **env): def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool, no_temp: bool, parallel: int, print_failures: bool, **env):
if len(targets) == 0: if len(targets) == 0:
return return
@ -37,6 +37,30 @@ def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool,
builddir.mkdir(parents=True, exist_ok=True) builddir.mkdir(parents=True, exist_ok=True)
with open(makefile, "w") as f: with open(makefile, "w") as f:
# yapf: disable
f.write(
f"""\
# This file is auto-generated by qmk mass-compile
# Do not edit this file directly.
all: print_failures
.PHONY: all_targets print_failures
print_failures: all_targets
"""# noqa
)
if print_failures:
f.write(
f"""\
@for f in $$(ls .build/failed.log.{os.getpid()}.* 2>/dev/null | sort); do \\
echo; \\
echo "======================================================================================"; \\
echo "Failed build log: $$f"; \\
echo "------------------------------------------------------"; \\
cat $$f; \\
echo "------------------------------------------------------"; \\
done
"""# noqa
)
# yapf: enable
for target in sorted(targets, key=lambda t: (t.keyboard, t.keymap)): for target in sorted(targets, key=lambda t: (t.keyboard, t.keymap)):
keyboard_name = target.keyboard keyboard_name = target.keyboard
keymap_name = target.keymap keymap_name = target.keymap
@ -58,7 +82,7 @@ def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool,
f.write( f.write(
f"""\ f"""\
.PHONY: {target_filename}{target_suffix}_binary .PHONY: {target_filename}{target_suffix}_binary
all: {target_filename}{target_suffix}_binary all_targets: {target_filename}{target_suffix}_binary
{target_filename}{target_suffix}_binary: {target_filename}{target_suffix}_binary:
@rm -f "{build_log}" || true @rm -f "{build_log}" || true
@echo "Compiling QMK Firmware for target: '{keyboard_name}:{keymap_name}'..." >>"{build_log}" @echo "Compiling QMK Firmware for target: '{keyboard_name}:{keymap_name}'..." >>"{build_log}"
@ -98,6 +122,7 @@ all: {target_filename}{target_suffix}_binary
@cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.") @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.")
@cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.") @cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.")
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the commands to be run.") @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the commands to be run.")
@cli.argument('-p', '--print-failures', arg_only=True, action='store_true', help="Print failed builds.")
@cli.argument( @cli.argument(
'-f', '-f',
'--filter', '--filter',
@ -123,4 +148,4 @@ def mass_compile(cli):
else: else:
targets = search_keymap_targets([('all', cli.config.mass_compile.keymap)], cli.args.filter) targets = search_keymap_targets([('all', cli.config.mass_compile.keymap)], cli.args.filter)
return mass_compile_targets(targets, cli.args.clean, cli.args.dry_run, cli.args.no_temp, cli.config.mass_compile.parallel, **build_environment(cli.args.env)) return mass_compile_targets(targets, cli.args.clean, cli.args.dry_run, cli.args.no_temp, cli.config.mass_compile.parallel, cli.args.print_failures, **build_environment(cli.args.env))

View File

@ -20,6 +20,7 @@ def _extra_arg_setter(target, extra_args):
@cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.") @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.")
@cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.") @cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.")
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the commands to be run.") @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the commands to be run.")
@cli.argument('-p', '--print-failures', arg_only=True, action='store_true', help="Print failed builds.")
@cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.")
@cli.subcommand('Compiles the build targets specified in userspace `qmk.json`.') @cli.subcommand('Compiles the build targets specified in userspace `qmk.json`.')
def userspace_compile(cli): def userspace_compile(cli):
@ -42,4 +43,4 @@ def userspace_compile(cli):
if len(keyboard_keymap_targets) > 0: if len(keyboard_keymap_targets) > 0:
build_targets.extend(search_keymap_targets(keyboard_keymap_targets)) build_targets.extend(search_keymap_targets(keyboard_keymap_targets))
return mass_compile_targets(list(set(build_targets)), cli.args.clean, cli.args.dry_run, cli.config.userspace_compile.no_temp, cli.config.userspace_compile.parallel, **build_environment(cli.args.env)) return mass_compile_targets(list(set(build_targets)), cli.args.clean, cli.args.dry_run, cli.config.userspace_compile.no_temp, cli.config.userspace_compile.parallel, cli.args.print_failures, **build_environment(cli.args.env))