From dd2ea4aae0cce1631a7fd9fff1419e3c2afe4a11 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Fri, 7 Feb 2025 23:30:48 +1100 Subject: [PATCH] Add `introspection.h` support and example. --- builddefs/build_keyboard.mk | 11 ++++-- .../qmk/cli/generate/community_modules.py | 35 +++++++++++++++++-- modules/hello_world/hello_world.c | 6 ++-- modules/hello_world/introspection.c | 8 +++-- modules/hello_world/introspection.h | 9 +++++ quantum/keymap_introspection.c | 8 +++-- 6 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 modules/hello_world/introspection.h diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk index 786d1263bc..03053ebd7a 100644 --- a/builddefs/build_keyboard.mk +++ b/builddefs/build_keyboard.mk @@ -270,14 +270,19 @@ $(INTERMEDIATE_OUTPUT)/src/community_modules.c: $(KEYMAP_JSON) $(DD_CONFIG_FILES $(eval CMD=$(QMK_BIN) generate-community-modules-c -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(KEYMAP_JSON)) @$(BUILD_CMD) -$(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.inc: $(KEYMAP_JSON) $(DD_CONFIG_FILES) +$(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c: $(KEYMAP_JSON) $(DD_CONFIG_FILES) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) - $(eval CMD=$(QMK_BIN) generate-community-modules-introspection-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.inc $(KEYMAP_JSON)) + $(eval CMD=$(QMK_BIN) generate-community-modules-introspection-c -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(KEYMAP_JSON)) + @$(BUILD_CMD) + +$(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES) + @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) + $(eval CMD=$(QMK_BIN) generate-community-modules-introspection-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(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 $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.inc +generated-files: $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h include $(BUILDDEFS_PATH)/converters.mk diff --git a/lib/python/qmk/cli/generate/community_modules.py b/lib/python/qmk/cli/generate/community_modules.py index 10fe7bf8e3..cb8c3b9a77 100644 --- a/lib/python/qmk/cli/generate/community_modules.py +++ b/lib/python/qmk/cli/generate/community_modules.py @@ -202,9 +202,38 @@ def generate_community_modules_c(cli): @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") @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_introspection.inc from a keymap.json file.') -def generate_community_modules_introspection_inc(cli): - """Creates a community_modules_introspection.inc from a keymap.json file +@cli.subcommand('Creates a community_modules_introspection.h from a keymap.json file.') +def generate_community_modules_introspection_h(cli): + """Creates a community_modules_introspection.h from a keymap.json file + """ + if cli.args.output and cli.args.output.name == '-': + cli.args.output = None + + lines = [ + GPL2_HEADER_C_LIKE, + GENERATED_HEADER_C_LIKE, + '', + ] + + modules = get_modules(cli.args.keyboard, cli.args.filename) + if len(modules) > 0: + for module in modules: + module_path = find_module_path(module) + lines.append(f'#if __has_include("{module_path}/introspection.h")') + lines.append(f'#include "{module_path}/introspection.h"') + lines.append(f'#endif // __has_include("{module_path}/introspection.h")') + lines.append('') + + dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True) + + +@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('-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_introspection.c from a keymap.json file.') +def generate_community_modules_introspection_c(cli): + """Creates a community_modules_introspection.c from a keymap.json file """ if cli.args.output and cli.args.output.name == '-': cli.args.output = None diff --git a/modules/hello_world/hello_world.c b/modules/hello_world/hello_world.c index 0dbe2ce817..adcf21593a 100644 --- a/modules/hello_world/hello_world.c +++ b/modules/hello_world/hello_world.c @@ -2,12 +2,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include QMK_KEYBOARD_H +#include "introspection.h" + ASSERT_COMMUNITY_MODULES_MIN_API_VERSION(20250122); -extern int keymap_byte_count(void); // example of use of introspection - uint32_t delayed_hello_world(uint32_t trigger_time, void *cb_arg) { - printf("Hello, world! I'm a QMK based keyboard! The keymap array size is %d bytes.\n", keymap_byte_count()); + printf("Hello, world! I'm a QMK based keyboard! The keymap array size is %d bytes.\n", hello_world_introspection().total_size); return 0; } diff --git a/modules/hello_world/introspection.c b/modules/hello_world/introspection.c index f33371c8f7..2c32a074f5 100644 --- a/modules/hello_world/introspection.c +++ b/modules/hello_world/introspection.c @@ -1,6 +1,10 @@ // Copyright 2025 Nick Brassel (@tzarc) // SPDX-License-Identifier: GPL-2.0-or-later -int keymap_byte_count(void) { - return sizeof(keymaps); +hello_world_introspection_t hello_world_introspection(void) { + hello_world_introspection_t introspection = { + .total_size = sizeof(keymaps), + .layer_count = sizeof(keymaps) / sizeof(keymaps[0]), + }; + return introspection; } diff --git a/modules/hello_world/introspection.h b/modules/hello_world/introspection.h new file mode 100644 index 0000000000..3aba0f2051 --- /dev/null +++ b/modules/hello_world/introspection.h @@ -0,0 +1,9 @@ +// Copyright 2025 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +typedef struct hello_world_introspection_t { + int total_size; + int layer_count; +} hello_world_introspection_t; + +hello_world_introspection_t hello_world_introspection(void); diff --git a/quantum/keymap_introspection.c b/quantum/keymap_introspection.c index cd95868baa..57377e31b4 100644 --- a/quantum/keymap_introspection.c +++ b/quantum/keymap_introspection.c @@ -12,6 +12,10 @@ #include "keymap_introspection.h" #include "util.h" +#if defined(COMMUNITY_MODULES_ENABLE) +# include "community_modules_introspection.h" +#endif // defined(COMMUNITY_MODULES_ENABLE) + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Key mapping @@ -173,8 +177,8 @@ __attribute__((weak)) const key_override_t* key_override_get(uint16_t key_overri #endif // defined(KEY_OVERRIDE_ENABLE) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Community modules +// Community modules (must be last in this file!) #if defined(COMMUNITY_MODULES_ENABLE) -# include "community_modules_introspection.inc" +# include "community_modules_introspection.c" #endif // defined(COMMUNITY_MODULES_ENABLE)