at master 5.2 kB view raw
1"""Compile and flash QMK Firmware 2 3You can compile a keymap already in the repo or using a QMK Configurator export. 4A bootloader must be specified. 5""" 6from argcomplete.completers import FilesCompleter 7from pathlib import Path 8 9from milc import cli 10 11import qmk.path 12from qmk.decorators import automagic_keyboard, automagic_keymap 13from qmk.commands import build_environment 14from qmk.keyboard import keyboard_completer, keyboard_folder 15from qmk.keymap import keymap_completer, locate_keymap 16from qmk.flashers import flasher 17from qmk.build_targets import KeyboardKeymapBuildTarget, JsonKeymapBuildTarget 18 19 20def _list_bootloaders(): 21 """Prints the available bootloaders listed in docs.qmk.fm. 22 """ 23 cli.print_help() 24 cli.log.info('Here are the available bootloaders:') 25 cli.echo('\tavrdude') 26 cli.echo('\tbootloadhid') 27 cli.echo('\tdfu') 28 cli.echo('\tdfu-util') 29 cli.echo('\tmdloader') 30 cli.echo('\tst-flash') 31 cli.echo('\tst-link-cli') 32 cli.log.info('Enhanced variants for split keyboards:') 33 cli.echo('\tavrdude-split-left') 34 cli.echo('\tavrdude-split-right') 35 cli.echo('\tdfu-ee') 36 cli.echo('\tdfu-split-left') 37 cli.echo('\tdfu-split-right') 38 cli.echo('\tdfu-util-split-left') 39 cli.echo('\tdfu-util-split-right') 40 cli.echo('\tuf2-split-left') 41 cli.echo('\tuf2-split-right') 42 cli.echo('For more info, visit https://docs.qmk.fm/#/flashing') 43 return False 44 45 46def _flash_binary(filename, mcu): 47 """Try to flash binary firmware 48 """ 49 cli.echo('Flashing binary firmware...\nPlease reset your keyboard into bootloader mode now!\nPress Ctrl-C to exit.\n') 50 try: 51 err, msg = flasher(mcu, filename) 52 if err: 53 cli.log.error(msg) 54 return False 55 except KeyboardInterrupt: 56 cli.log.info('Ctrl-C was pressed, exiting...') 57 return True 58 59 60@cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.') 61@cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.') 62@cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.') 63@cli.argument('-m', '--mcu', help='The MCU name. Required for HalfKay, HID, USBAspLoader and ISP flashing.') 64@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') 65@cli.argument('-km', '--keymap', completer=keymap_completer, help='The keymap to build a firmware for. Ignored when a configurator export is supplied.') 66@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") 67@cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.") 68@cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") 69@cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.") 70@cli.subcommand('QMK Flash.') 71@automagic_keyboard 72@automagic_keymap 73def flash(cli): 74 """Compile and or flash QMK Firmware or keyboard/layout 75 76 If a binary firmware is supplied, try to flash that. 77 78 If a Configurator export is supplied this command will create a new keymap, overwriting an existing keymap if one exists. 79 80 If a keyboard and keymap are provided this command will build a firmware based on that. 81 82 If bootloader is omitted the make system will use the configured bootloader for that keyboard. 83 """ 84 if cli.args.filename and isinstance(cli.args.filename, Path) and cli.args.filename.suffix in ['.bin', '.hex', '.uf2']: 85 return _flash_binary(cli.args.filename, cli.args.mcu) 86 87 if cli.args.bootloaders: 88 return _list_bootloaders() 89 90 # Build the environment vars 91 envs = build_environment(cli.args.env) 92 93 # Handler for the build target 94 target = None 95 96 if cli.args.filename: 97 # if we were given a filename, assume we have a json build target 98 target = JsonKeymapBuildTarget(cli.args.filename) 99 100 elif cli.config.flash.keyboard and cli.config.flash.keymap: 101 # if we got a keyboard and keymap, attempt to find it 102 if not locate_keymap(cli.config.flash.keyboard, cli.config.flash.keymap): 103 cli.log.error('Invalid keymap argument.') 104 cli.print_help() 105 return False 106 107 # If we got here, then we have a valid keyboard and keymap for a build target 108 target = KeyboardKeymapBuildTarget(cli.config.flash.keyboard, cli.config.flash.keymap) 109 110 if not target: 111 cli.log.error('You must supply a configurator export, both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.') 112 cli.print_help() 113 return False 114 115 target.configure(parallel=cli.config.flash.parallel, clean=cli.args.clean) 116 return target.compile(cli.args.bootloader, dry_run=cli.args.dry_run, **envs)