From c9ee24ba86507a582d89a26f198414c0e6e42790 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Fri, 24 Jan 2025 01:11:45 +1100 Subject: [PATCH] keyboard and keymap modules --- builddefs/build_keyboard.mk | 85 ++++++++++--------- .../qmk/cli/generate/community_modules.py | 34 ++++---- lib/python/qmk/cli/generate/rules_mk.py | 7 +- lib/python/qmk/cli/info.py | 5 ++ lib/python/qmk/info.py | 27 ++++++ 5 files changed, 97 insertions(+), 61 deletions(-) diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk index e4661a7f3f..9ae7b213a8 100644 --- a/builddefs/build_keyboard.mk +++ b/builddefs/build_keyboard.mk @@ -112,6 +112,39 @@ endif ifneq ("$(wildcard $(KEYBOARD_PATH_1)/rules.mk)","") include $(KEYBOARD_PATH_1)/rules.mk endif +# Create dependencies on DD keyboard config - structure validated elsewhere +DD_CONFIG_FILES := +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/info.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_1)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/info.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_2)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/info.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_3)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/info.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_4)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_5)/info.json +endif + +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/keyboard.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_1)/keyboard.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/keyboard.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_2)/keyboard.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/keyboard.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_3)/keyboard.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/keyboard.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_4)/keyboard.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/keyboard.json)","") + DD_CONFIG_FILES += $(KEYBOARD_PATH_5)/keyboard.json +endif MAIN_KEYMAP_PATH_1 := $(KEYBOARD_PATH_1)/keymaps/$(KEYMAP) MAIN_KEYMAP_PATH_2 := $(KEYBOARD_PATH_2)/keymaps/$(KEYMAP) @@ -207,38 +240,40 @@ ifneq ("$(wildcard $(KEYMAP_JSON))", "") include $(INFO_RULES_MK) # Add rules to generate the keymap files - indentation here is important -$(INTERMEDIATE_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) +$(INTERMEDIATE_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) $(DD_CONFIG_FILES) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) $(eval CMD=$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)) @$(BUILD_CMD) -$(INTERMEDIATE_OUTPUT)/src/config.h: $(KEYMAP_JSON) +$(INTERMEDIATE_OUTPUT)/src/config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) $(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON)) @$(BUILD_CMD) -$(INTERMEDIATE_OUTPUT)/src/keymap.h: $(KEYMAP_JSON) +$(INTERMEDIATE_OUTPUT)/src/keymap.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) $(eval CMD=$(QMK_BIN) generate-keymap-h --quiet --output $(INTERMEDIATE_OUTPUT)/src/keymap.h $(KEYMAP_JSON)) @$(BUILD_CMD) generated-files: $(INTERMEDIATE_OUTPUT)/src/config.h $(INTERMEDIATE_OUTPUT)/src/keymap.c $(INTERMEDIATE_OUTPUT)/src/keymap.h -$(INTERMEDIATE_OUTPUT)/src/community_modules.h: $(KEYMAP_JSON) +endif + +# Community modules +$(INTERMEDIATE_OUTPUT)/src/community_modules.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) - $(eval CMD=$(QMK_BIN) generate-community-modules-h --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(KEYMAP_JSON)) + $(eval CMD=$(QMK_BIN) generate-community-modules-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(KEYMAP_JSON)) @$(BUILD_CMD) -$(INTERMEDIATE_OUTPUT)/src/community_modules.c: $(KEYMAP_JSON) +$(INTERMEDIATE_OUTPUT)/src/community_modules.c: $(KEYMAP_JSON) $(DD_CONFIG_FILES) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) - $(eval CMD=$(QMK_BIN) generate-community-modules-c --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(KEYMAP_JSON)) + $(eval CMD=$(QMK_BIN) generate-community-modules-c -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(KEYMAP_JSON)) @$(BUILD_CMD) SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c generated-files: $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c -endif include $(BUILDDEFS_PATH)/converters.mk @@ -362,40 +397,6 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","") POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h endif -# Create dependencies on DD keyboard config - structure validated elsewhere -DD_CONFIG_FILES := -ifneq ("$(wildcard $(KEYBOARD_PATH_1)/info.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_1)/info.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_2)/info.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_2)/info.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_3)/info.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_3)/info.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_4)/info.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_4)/info.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_5)/info.json -endif - -ifneq ("$(wildcard $(KEYBOARD_PATH_1)/keyboard.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_1)/keyboard.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_2)/keyboard.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_2)/keyboard.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_3)/keyboard.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_3)/keyboard.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_4)/keyboard.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_4)/keyboard.json -endif -ifneq ("$(wildcard $(KEYBOARD_PATH_5)/keyboard.json)","") - DD_CONFIG_FILES += $(KEYBOARD_PATH_5)/keyboard.json -endif - CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c diff --git a/lib/python/qmk/cli/generate/community_modules.py b/lib/python/qmk/cli/generate/community_modules.py index 96a1c1fc94..cc192e20e4 100644 --- a/lib/python/qmk/cli/generate/community_modules.py +++ b/lib/python/qmk/cli/generate/community_modules.py @@ -5,7 +5,9 @@ from milc import cli from milc.attrdict import AttrDict import qmk.path -from qmk.commands import dump_lines, parse_configurator_json +from qmk.info import get_modules +from qmk.keyboard import keyboard_completer, keyboard_folder +from qmk.commands import dump_lines from qmk.constants import GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE @@ -95,14 +97,14 @@ def _render_api_implementations(api, module): return lines -def _render_core_implementation(api, keymap_json): +def _render_core_implementation(api, modules): lines = [] lines.append('') with _api_guard(lines, api): lines.append(f'{api.ret_type} {api.name}_modules({api.args}) {{') if api.ret_type == 'bool': lines.append(' return true') - for module in keymap_json['modules']: + for module in modules: if api.ret_type == 'bool': lines.append(f' && {api.name}_{module}({api.call_params})') else: @@ -115,7 +117,8 @@ def _render_core_implementation(api, keymap_json): @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") -@cli.argument('filename', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file') +@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.h for.') +@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file') @cli.subcommand('Creates a community_modules.h from a keymap.json file.') def generate_community_modules_h(cli): """Creates a community_modules.h from a keymap.json file @@ -137,13 +140,12 @@ def generate_community_modules_h(cli): '', ] - keymap_json = parse_configurator_json(cli.args.filename) + modules = get_modules(cli.args.keyboard, cli.args.filename) + if len(modules) > 0: + for api in MODULE_API_LIST: + lines.extend(_render_api_header(api)) - for api in MODULE_API_LIST: - lines.extend(_render_api_header(api)) - - if keymap_json and 'modules' in keymap_json: - for module in keymap_json['modules']: + for module in modules: lines.append('') lines.append(f'// From module: {module}') for api in MODULE_API_LIST: @@ -159,7 +161,8 @@ def generate_community_modules_h(cli): @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") -@cli.argument('filename', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file') +@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.c for.') +@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file') @cli.subcommand('Creates a community_modules.c from a keymap.json file.') def generate_community_modules_c(cli): """Creates a community_modules.c from a keymap.json file @@ -174,15 +177,14 @@ def generate_community_modules_c(cli): '#include "community_modules.h"', ] - keymap_json = parse_configurator_json(cli.args.filename) + modules = get_modules(cli.args.keyboard, cli.args.filename) + if len(modules) > 0: - if keymap_json and 'modules' in keymap_json: - - for module in keymap_json['modules']: + for module in modules: for api in MODULE_API_LIST: lines.extend(_render_api_implementations(api, module)) for api in MODULE_API_LIST: - lines.extend(_render_core_implementation(api, keymap_json)) + lines.extend(_render_core_implementation(api, modules)) dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True) diff --git a/lib/python/qmk/cli/generate/rules_mk.py b/lib/python/qmk/cli/generate/rules_mk.py index ea44f1e58a..0a888f863c 100755 --- a/lib/python/qmk/cli/generate/rules_mk.py +++ b/lib/python/qmk/cli/generate/rules_mk.py @@ -6,7 +6,7 @@ from dotty_dict import dotty from argcomplete.completers import FilesCompleter from milc import cli -from qmk.info import info_json +from qmk.info import info_json, get_modules from qmk.json_schema import json_load from qmk.keyboard import keyboard_completer, keyboard_folder from qmk.commands import dump_lines, parse_configurator_json @@ -100,10 +100,11 @@ def generate_rules_mk(cli): if converter: rules_mk_lines.append(generate_rule('CONVERT_TO', converter)) - if user_keymap and 'modules' in user_keymap: + modules = get_modules(cli.args.keyboard, cli.args.filename) + if len(modules) > 0: rules_mk_lines.append('') rules_mk_lines.append('OPT_DEFS += -DCOMMUNITY_MODULES_ENABLED=TRUE') - for module in user_keymap['modules']: + for module in modules: rules_mk_lines.append('') rules_mk_lines.append(f'COMMUNITY_MODULES += {module}') rules_mk_lines.append(f'OPT_DEFS += -DCOMMUNITY_MODULE_{module.upper()}=TRUE') diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index e662407474..5925b57258 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -52,6 +52,11 @@ def show_keymap(kb_info_json, title_caps=True): if keymap_path and keymap_path.suffix == '.json': keymap_data = json.load(keymap_path.open(encoding='utf-8')) + + # cater for layout-less keymap.json + if 'layout' not in keymap_data: + return + layout_name = keymap_data['layout'] layout_name = kb_info_json.get('layout_aliases', {}).get(layout_name, layout_name) # Resolve alias names diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py index 38ca89697c..08b15cf799 100644 --- a/lib/python/qmk/info.py +++ b/lib/python/qmk/info.py @@ -1052,3 +1052,30 @@ def keymap_json(keyboard, keymap, force_layout=None): _extract_config_h(kb_info_json, parse_config_h_file(keymap_config)) return kb_info_json + + +def get_modules(keyboard, keymap_filename): + """Get the modules for a keyboard/keymap. + """ + modules = [] + + if keymap_filename: + keymap_json = parse_configurator_json(keymap_filename) + + if keymap_json: + kb = keymap_json.get('keyboard', None) + if not kb: + kb = keyboard + + if kb: + kb_info_json = info_json(kb) + if kb_info_json: + modules.extend(kb_info_json.get('modules', [])) + + modules.extend(keymap_json.get('modules', [])) + + elif keyboard: + kb_info_json = info_json(keyboard) + modules.extend(kb_info_json.get('modules', [])) + + return list(dict.fromkeys(modules)) # remove dupes