diff --git a/CMakeLists.txt b/CMakeLists.txt index 74a4b1c8e0c..29829c16b19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.20) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") include(UpdateSubmodule) @@ -34,9 +36,9 @@ else() endif() resolve_keyboard(${QMK_KEYBOARD_FOLDER} QMK_KEYBOARD_FOLDER_ABS) - process_keyboard() cmake_path(IS_PREFIX QMK_KEYBOARDS_FOLDER "${QMK_KEYBOARD_FOLDER_ABS}" IS_KEYBOARDS_FOLDER) resolve_config_h(${QMK_KEYBOARD_FOLDER_ABS} QMK_KEYBOARD_CONFIG_H) + process_keyboard() resolve_keyboard_h(${QMK_KEYBOARD_FOLDER_ABS} QMK_KEYBOARD_H) resolve_keymap_c(${QMK_KEYBOARD_FOLDER_ABS} ${QMK_KEYMAP_FOLDER} QMK_KEYMAP_C) @@ -50,12 +52,6 @@ else() HOMEPAGE_URL ${URL} VERSION ${DEVICE_VER}) - string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" VERSION_MATCH ${DEVICE_VER}) - set(VERSION_MAJOR ${CMAKE_MATCH_1}) - set(VERSION_MINOR ${CMAKE_MATCH_2}) - set(VERSION_PATCH ${CMAKE_MATCH_3}) - math(EXPR VERSION_C_EVAL "${VERSION_MAJOR} * 10000 + ${VERSION_MINOR} * 100 + ${VERSION_PATCH}" OUTPUT_FORMAT HEXADECIMAL) - # add_compile_options( # -include ${QMK_KEYBOARD_CONFIG_H} # ) @@ -65,11 +61,6 @@ else() KEYMAP_C="${QMK_KEYMAP_C}" MATRIX_ROWS=8 MATRIX_COLS=6 - VENDOR_ID=${VENDOR_ID} - PRODUCT_ID=${PRODUCT_ID} - DEVICE_VER=${VERSION_C_EVAL} - MANUFACTURER="${MANUFACTURER}" - PRODUCT="${KEYBOARD_NAME}" ) if(DEFINED DIODE_DIRECTION) diff --git a/cmake/Findchibios.cmake b/cmake/Findchibios.cmake index 7e924f4e462..3fb5744b1cc 100644 --- a/cmake/Findchibios.cmake +++ b/cmake/Findchibios.cmake @@ -72,7 +72,8 @@ find_file(STARTUP_MK startup_${MCU_STARTUP}.mk ) get_filename_component(STARTUP_DIR ${STARTUP_MK} DIRECTORY) ParseMakefile(${STARTUP_MK}) -target_sources(qmk PUBLIC ${STARTUPSRC} ${STARTUPASM}) +target_sources(qmk PUBLIC ${STARTUPSRC}) +target_sources(qmk PUBLIC ${STARTUPASM}) target_include_directories(qmk PUBLIC ${STARTUPINC}) # board paths - we should just standardize these diff --git a/cmake/ParseHeader.cmake b/cmake/ParseHeader.cmake new file mode 100644 index 00000000000..98c0718f202 --- /dev/null +++ b/cmake/ParseHeader.cmake @@ -0,0 +1,64 @@ +# Simple CMake utility to read variables from MK files +# - Gets contents from given file (name or path) +# - Parses the assignment statements +# - Makes the same assignments in the PARENT_SCOPE + +if(POLICY CMP0007) + cmake_policy(SET CMP0007 NEW) +endif() + +function(ParseHeader HeaderFile Prefix) + _ParseHeader(${HeaderFile} ${Prefix}) +endfunction() + +macro(_ParseHeader HeaderFile Prefix) + message(CHECK_START "Parsing Header") + list(APPEND CMAKE_MESSAGE_INDENT " ") + message(STATUS "Reading \"${HeaderFile}\"") + + file(READ "${HeaderFile}" FileContents) + string(REGEX REPLACE "/\\*.*\\*/" "" FileContents ${FileContents}) + # replace the \ newlines with spaces + string(REGEX REPLACE "\\\\\r?\n *" " " FileContents ${FileContents}) + # turn each line into an item in a list + string(REGEX REPLACE "\r?\n" ";" FileLines ${FileContents}) + list(REMOVE_ITEM FileLines "") + + foreach(line ${FileLines}) + # remove comments from the ends of each line + string(REGEX REPLACE "//.*" "" line ${line}) + + # remove now-empty lines + if("${line}" STREQUAL "") + continue() + endif() + + # try to process includes, if the file exists + if(line MATCHES "^#include \"(.+)\"") + set(INCLUDED_HEADER ${CMAKE_MATCH_1}) + if(EXISTS ${INCLUDED_HEADER}) + _ParseHeader("${INCLUDED_HEADER}" ${Prefix}) + else() + message(STATUS "Could not read ${INCLUDED_HEADER}") + endif() + continue() + endif() + + # array + if(line MATCHES "#define ([A-Za-z0-9_]+) {(.*)}") + set(VARIABLE_NAME ${CMAKE_MATCH_1}) + set(VARIABLE_VALUE ${CMAKE_MATCH_2}) + set(${Prefix}${VARIABLE_NAME} ${VARIABLE_VALUE}) + endif() + + # regular variable + if(line MATCHES "#define ([A-Za-z0-9_]+) (.*)") + set(VARIABLE_NAME ${CMAKE_MATCH_1}) + set(VARIABLE_VALUE ${CMAKE_MATCH_2}) + set(${Prefix}${VARIABLE_NAME} ${VARIABLE_VALUE}) + endif() + endforeach() + + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "Complete") +endmacro() \ No newline at end of file diff --git a/cmake/ParseMakefile.cmake b/cmake/ParseMakefile.cmake index 0e7f51480c2..6c59633f61f 100644 --- a/cmake/ParseMakefile.cmake +++ b/cmake/ParseMakefile.cmake @@ -8,65 +8,91 @@ if(POLICY CMP0007) endif() function(ParseMakefile MKFile) - _ParseMakefile(${MKFile}) + _ParseMakefile(${MKFile} ${ARGN}) endfunction() macro(_ParseMakefile MKFile) - message(VERBOSE "Parsing ${MKFile}") + message(CHECK_START "Parsing Makefile") + list(APPEND CMAKE_MESSAGE_INDENT " ") + message(STATUS "Reading \"${MKFile}\"") + file(READ "${MKFile}" FileContents) + # replace the \ newlines with spaces string(REGEX REPLACE "\\\\\r?\n *" " " FileContents ${FileContents}) - string(REGEX REPLACE "(\r?\n)+" ";" FileLines ${FileContents}) + # turn each line into an item in a list + string(REGEX REPLACE "\r?\n" ";" FileLines ${FileContents}) list(REMOVE_ITEM FileLines "") foreach(line ${FileLines}) - # if(line MATCHES "\\$\\((.+)\\)") - # set(MAKE_VARIABLE "${CMAKE_MATCH_1}") - # string(REPLACE "$(${MAKE_VARIABLE})" "${${MAKE_VARIABLE}}" line ${line}) - # endif() - # message(STATUS "From: ${line}") + # remove comments from the ends of each line string(REGEX REPLACE "#.*" "" line ${line}) + # remove now-empty lines if("${line}" STREQUAL "") continue() endif() - string(REGEX REPLACE "\\$\\(([^\\(\\)]+)\\)" "${CHIBIOS}" line ${line}) + # try to process includes, if the file exists + if(line MATCHES "^-?include (.+)$") + set(MAKE_CHILD ${CMAKE_MATCH_1}) + if(EXISTS ${MAKE_CHILD}) + _ParseMakefile("${MAKE_CHILD}" ${ARGN}) + else() + message(STATUS "Could not read ${MAKE_CHILD}") + endif() + continue() + endif() - # message(STATUS "To : ${line}") - # if(line MATCHES "^include (.+)$") - # set(MAKE_CHILD ${CMAKE_MATCH_1}) - # message(STATUS "Reading ${MAKE_CHILD}") - # _ParseMakefile("${MAKE_CHILD}") - # else() + # turn the assignment into a list with the first item being the variable name string(REPLACE "=" ";" line_split ${line}) list(LENGTH line_split count) if(count LESS 2) - message(VERBOSE "Skipping ${line}") + message(STATUS "Skipping ${line}") continue() endif() list(GET line_split -1 value) string(STRIP ${value} value) - separate_arguments(value) + # separate_arguments(value) + # string(REPLACE " " ";" value ${value}) list(REMOVE_AT line_split -1) foreach(var_name ${line_split}) string(STRIP ${var_name} var_name) + # replace $(?) with the variable ? from cmake + if(value MATCHES "\\$\\(([^\\(\\)]+)\\)") + set(MAKE_VARIABLE "${CMAKE_MATCH_1}") + string(REPLACE "$(${MAKE_VARIABLE})" "${${MAKE_VARIABLE}}" value ${value}) + endif() + + # look for +, assuming it used to be += if(${var_name} MATCHES "([^ \\+]+) *\\+") - message(VERBOSE "Appending '${CMAKE_MATCH_1}' with '${value}'") - set(${CMAKE_MATCH_1} ${${CMAKE_MATCH_1}} ${value} PARENT_SCOPE) + message(STATUS "Appending \"${CMAKE_MATCH_1}\" with \"${value}\"") + # read parent variable in local & append + set(LOCAL_${CMAKE_MATCH_1} ${CMAKE_MATCH_1}) + # APPEND accepts spaces between values + list(APPEND LOCAL_${CMAKE_MATCH_1} ${value}) + set(${CMAKE_MATCH_1} ${LOCAL_${CMAKE_MATCH_1}}) + set(${CMAKE_MATCH_1} ${LOCAL_${CMAKE_MATCH_1}} PARENT_SCOPE) else() + # set needs ; between elements to be considered a list + string(REGEX REPLACE " +" ";" value ${value}) + # try to find variable in cache and FORCE wtih INTERNAL if it exists if(DEFINED CACHE${${var_name}}) - message(VERBOSE "Caching '${var_name}' to '${value}'") + message(STATUS "Caching \"${var_name}\" to \"${value}\"") + # set locally so replacement still work + set(${var_name} ${value}) set(${var_name} ${value} CACHE INTERNAL "") else() - message(VERBOSE "Setting '${var_name}' to '${value}'") + message(STATUS "Setting \"${var_name}\" to \"${value}\"") + set(${var_name} ${value}) set(${var_name} ${value} PARENT_SCOPE) endif() endif() endforeach() - - # endif() endforeach() + + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "Complete") endmacro() \ No newline at end of file diff --git a/cmake/ProcessKeyboard.cmake b/cmake/ProcessKeyboard.cmake index a3938d38e73..7e453ccf04a 100644 --- a/cmake/ProcessKeyboard.cmake +++ b/cmake/ProcessKeyboard.cmake @@ -1,17 +1,78 @@ include(ParseMakefile) +include(Utils) macro(process_keyboard) + message(CHECK_START "Processing keyboard") + list(APPEND CMAKE_MESSAGE_INDENT " ") + validate_json(${QMK_KEYBOARD_FOLDER_ABS}/info.json keyboard QMK_KEYBOARD_INFO_JSON_STRING) + # process rules from info.json + file(READ ${CMAKE_SOURCE_DIR}/data/mappings/info_rules.hjson JSON_STRING) + string(JSON MAPPING_LENGTH LENGTH ${JSON_STRING}) + math(EXPR MAX "${MAPPING_LENGTH} - 1") + foreach(IDX RANGE ${MAX}) + string(JSON RULE_KEY MEMBER ${JSON_STRING} ${IDX}) + # string(JSON INFO_KEY GET ${JSON_STRING} ${RULE_KEY} info_key) + json_get_with_default(INFO_KEY ${JSON_STRING} _ ${RULE_KEY} info_key) + string(REPLACE "." " " INFO_KEYS ${INFO_KEY}) + string(JSON RULE_VALUE ERROR_VARIABLE RULE_KEY_NOT_FOUND GET ${QMK_KEYBOARD_INFO_JSON_STRING} ${INFO_KEYS}) + if(${RULE_KEY_NOT_FOUND} STREQUAL "NOTFOUND") + json_get_with_default(VALUE_TYPE ${JSON_STRING} raw ${RULE_KEY} value_type) + if(${VALUE_TYPE} STREQUAL "list") + string(JSON NUM_VALUES LENGTH ${RULE_VALUE}) + math(EXPR MAX "${NUM_VALUES} - 1") + foreach(IDX RANGE ${MAX}) + string(JSON VALUE GET ${RULE_VALUE} ${IDX}) + list(APPEND ${RULE_KEY} ${VALUE}) + endforeach() + message(STATUS "Found rule '${INFO_KEY}': '${${RULE_KEY}}' assigned to '${RULE_KEY}'") + else() + set(${RULE_KEY} ${RULE_VALUE}) + message(STATUS "Found rule '${INFO_KEY}': '${RULE_VALUE}' assigned to '${RULE_KEY}'") + endif() + endif() + endforeach() + + # process definitions from info.json + file(READ ${CMAKE_SOURCE_DIR}/data/mappings/info_config.hjson JSON_STRING) + string(JSON MAPPING_LENGTH LENGTH ${JSON_STRING}) + math(EXPR MAX "${MAPPING_LENGTH} - 1") + foreach(IDX RANGE ${MAX}) + string(JSON CONFIG_KEY MEMBER ${JSON_STRING} ${IDX}) + json_get_with_default(INFO_KEY ${JSON_STRING} _ ${CONFIG_KEY} info_key) + string(REPLACE "." ";" INFO_KEYS ${INFO_KEY}) + # string(JSON CONFIG_VALUE ERROR_VARIABLE CONFIG_KEY_NOT_FOUND GET ${QMK_KEYBOARD_INFO_JSON_STRING} ${INFO_KEYS}) + json_get_with_default(CONFIG_VALUE ${QMK_KEYBOARD_INFO_JSON_STRING} NOTFOUND ${INFO_KEYS}) + if(NOT CONFIG_VALUE STREQUAL "NOTFOUND") + set(${CONFIG_KEY} ${CONFIG_VALUE}) + json_get_with_default(VALUE_TYPE ${JSON_STRING} raw ${CONFIG_KEY} value_type) + if(${VALUE_TYPE} STREQUAL "str") + add_compile_definitions(${CONFIG_KEY}="${CONFIG_VALUE}") + message(STATUS "Found definition '${INFO_KEY}': '\"${CONFIG_VALUE}\"' assigned to '${CONFIG_KEY}'") + elseif(${VALUE_TYPE} STREQUAL "bcd_version") + string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" VERSION_MATCH ${CONFIG_VALUE}) + set(VERSION_MAJOR ${CMAKE_MATCH_1}) + set(VERSION_MINOR ${CMAKE_MATCH_2}) + set(VERSION_PATCH ${CMAKE_MATCH_3}) + math(EXPR BCD_VERSION "${VERSION_MAJOR} * 10000 + ${VERSION_MINOR} * 100 + ${VERSION_PATCH}" OUTPUT_FORMAT HEXADECIMAL) + add_compile_definitions(${CONFIG_KEY}=${BCD_VERSION}) + message(STATUS "Found definition '${INFO_KEY}': '${BCD_VERSION}' assigned to '${CONFIG_KEY}'") + else() + add_compile_definitions(${CONFIG_KEY}=${CONFIG_VALUE}) + message(STATUS "Found definition '${INFO_KEY}': '${CONFIG_VALUE}' assigned to '${CONFIG_KEY}'") + endif() + endif() + endforeach() + string(JSON KEYBOARD_NAME GET ${QMK_KEYBOARD_INFO_JSON_STRING} keyboard_name) string(JSON MANUFACTURER GET ${QMK_KEYBOARD_INFO_JSON_STRING} manufacturer) string(JSON URL GET ${QMK_KEYBOARD_INFO_JSON_STRING} url) string(JSON QMK_MCU GET ${QMK_KEYBOARD_INFO_JSON_STRING} processor) - string(JSON VENDOR_ID GET ${QMK_KEYBOARD_INFO_JSON_STRING} usb vid) - string(JSON PRODUCT_ID GET ${QMK_KEYBOARD_INFO_JSON_STRING} usb pid) - string(JSON DEVICE_VER GET ${QMK_KEYBOARD_INFO_JSON_STRING} usb device_version) - string(JSON DIODE_DIRECTION ERROR_VARIABLE _ GET ${QMK_KEYBOARD_INFO_JSON_STRING} diode_direction) - string(JSON BOOTLOADER ERROR_VARIABLE _ GET ${QMK_KEYBOARD_INFO_JSON_STRING} bootloader) - ParseMakefile(${QMK_KEYBOARD_FOLDER_ABS}/rules.mk) + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "info.json validated and loaded") + + + ParseMakefile(${QMK_KEYBOARD_FOLDER_ABS}/rules.mk) endmacro() \ No newline at end of file diff --git a/cmake/ResolveKeyboard.cmake b/cmake/ResolveKeyboard.cmake index 4f7b3d40e22..796dbac3b0a 100644 --- a/cmake/ResolveKeyboard.cmake +++ b/cmake/ResolveKeyboard.cmake @@ -1,3 +1,5 @@ +include(Utils) + function(resolve_keyboard KEYBOARD KEYBOAD_FOLDER_ABS_STR) message(VERBOSE "Resolving ${KEYBOARD}") if(EXISTS "${CMAKE_SOURCE_DIR}/keyboards/${KEYBOARD}") @@ -42,17 +44,19 @@ function(resolve_keyboard KEYBOARD KEYBOAD_FOLDER_ABS_STR) endfunction() function(resolve_config_h KEYBOARD_FOLDER_ABS CONFIG_H_STR) + set(${CONFIG_H_STR} PARENT_SCOPE) if(${IS_KEYBOARDS_FOLDER}) file(RELATIVE_PATH RELATIVE_KEYBOARD_FOLDER ${QMK_KEYBOARDS_FOLDER} ${KEYBOARD_FOLDER_ABS}) # get the deepest config.h while(NOT ${RELATIVE_KEYBOARD_FOLDER} STREQUAL "") if(EXISTS "${QMK_KEYBOARDS_FOLDER}/${RELATIVE_KEYBOARD_FOLDER}/config.h") - set(${CONFIG_H_STR} "${QMK_KEYBOARDS_FOLDER}/${RELATIVE_KEYBOARD_FOLDER}/config.h" PARENT_SCOPE) - return() + parent_list(PREPEND ${CONFIG_H_STR} "${QMK_KEYBOARDS_FOLDER}/${RELATIVE_KEYBOARD_FOLDER}/config.h") + # set(${CONFIG_H_STR} "${QMK_KEYBOARDS_FOLDER}/${RELATIVE_KEYBOARD_FOLDER}/config.h" PARENT_SCOPE) + # return() endif() get_filename_component(RELATIVE_KEYBOARD_FOLDER ${RELATIVE_KEYBOARD_FOLDER} DIRECTORY) endwhile() - message(FATAL_ERROR "Could not find config.h in ${KEYBOARD_FOLDER_ABS}") + # message(FATAL_ERROR "Could not find config.h in ${KEYBOARD_FOLDER_ABS}") else() if(EXISTS "${KEYBOARD_FOLDER_ABS}/config.h") set(${CONFIG_H_STR} "${KEYBOARD_FOLDER_ABS}/config.h" PARENT_SCOPE) @@ -112,26 +116,26 @@ function(resolve_keymap_c KEYBOARD_FOLDER_ABS KEYMAP_FOLDER KEYMAP_C_STR) endif() endif() - string(JSON COMMUNITY_LAYOUTS ERROR_VARIABLE NO_COMMUNITY_LAYOUTS GET ${QMK_KEYBOARD_INFO_JSON_STRING} community_layouts) + # string(JSON COMMUNITY_LAYOUTS ERROR_VARIABLE NO_COMMUNITY_LAYOUTS GET ${QMK_KEYBOARD_INFO_JSON_STRING} community_layouts) - if(${NO_COMMUNITY_LAYOUTS} STREQUAL "NOTFOUND") - string(JSON NUM_LAYOUTS LENGTH ${COMMUNITY_LAYOUTS}) - math(EXPR MAX "${NUM_LAYOUTS} - 1") - foreach(IDX RANGE ${MAX}) - string(JSON LAYOUT GET ${COMMUNITY_LAYOUTS} ${IDX}) + # if(${NO_COMMUNITY_LAYOUTS} STREQUAL "NOTFOUND") + # string(JSON NUM_LAYOUTS LENGTH ${COMMUNITY_LAYOUTS}) + # math(EXPR MAX "${NUM_LAYOUTS} - 1") + foreach(LAYOUT ${LAYOUTS}) + # foreach(IDX RANGE ${MAX}) + # string(JSON LAYOUT GET ${COMMUNITY_LAYOUTS} ${IDX}) if(EXISTS "${CMAKE_SOURCE_DIR}/layouts/community/${LAYOUT}/${KEYMAP_FOLDER}/keymap.c") set(${KEYMAP_C_STR} "${CMAKE_SOURCE_DIR}/layouts/community/${LAYOUT}/${KEYMAP_FOLDER}/keymap.c" PARENT_SCOPE) return() endif() endforeach() - endif() + # endif() message(FATAL_ERROR "Could not resolve keymap '${KEYMAP_FOLDER}'") endfunction() function(resolve_keyboard_includes KEYBOARD_FOLDER_ABS) if(${IS_KEYBOARDS_FOLDER}) file(RELATIVE_PATH RELATIVE_KEYBOARD_FOLDER ${QMK_KEYBOARDS_FOLDER} ${KEYBOARD_FOLDER_ABS}) - # get the deepest config.h while(NOT ${RELATIVE_KEYBOARD_FOLDER} STREQUAL "") target_include_directories(qmk PUBLIC "${CMAKE_SOURCE_DIR}/keyboards/${RELATIVE_KEYBOARD_FOLDER}") get_filename_component(RELATIVE_KEYBOARD_FOLDER ${RELATIVE_KEYBOARD_FOLDER} DIRECTORY) diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake new file mode 100644 index 00000000000..3b4b91d8d4f --- /dev/null +++ b/cmake/Utils.cmake @@ -0,0 +1,25 @@ +macro(json_get_with_default KEY_STR JSON_STR DEFAULT) + # message(STATUS "Getting ${ARGN} for ${KEY_STR}") + string(JSON ${KEY_STR} ERROR_VARIABLE JSON_ERROR GET ${JSON_STR} ${ARGN}) + if(NOT ${JSON_ERROR} STREQUAL "NOTFOUND") + set(${KEY_STR} ${DEFAULT}) + endif() +endmacro() + +macro(json_get KEY_STR JSON_STR) + # message(STATUS "Getting ${ARGN} for ${KEY_STR}") + string(JSON ${KEY_STR} ERROR_VARIABLE JSON_ERROR GET ${JSON_STR} ${ARGN}) + if(NOT ${JSON_ERROR} STREQUAL "NOTFOUND") + unset(${KEY_STR}) + endif() +endmacro() + +macro(parent_list ACTION LIST_STR) + set(ARGS ${ARGN}) + string(REPLACE ";" " " ARGS ${ARGS}) + set(LOCAL_LIST ${${LIST_STR}}) + list(${ACTION} LOCAL_LIST ${ARGS}) + # set in current scope too + set(${LIST_STR} ${LOCAL_LIST}) + set(${LIST_STR} ${LOCAL_LIST} PARENT_SCOPE) +endmacro() \ No newline at end of file diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson index 46108e6fe6a..f82b706ef65 100644 --- a/data/mappings/info_config.hjson +++ b/data/mappings/info_config.hjson @@ -129,7 +129,7 @@ "TAPPING_FORCE_HOLD": {"info_key": "tapping.force_hold", "value_type": "bool", "deprecated": true}, "TAPPING_FORCE_HOLD_PER_KEY": {"info_key": "tapping.force_hold_per_key", "value_type": "bool", "deprecated": true}, "IGNORE_MOD_TAP_INTERRUPT": {"info_key": "_deprecated.ignore_mod_tap_interrupt", "value_type": "bool", "deprecated": true}, - "IGNORE_MOD_TAP_INTERRUPT_PER_KEY": {"info_key": "_invalid.ignore_mod_tap_interrupt_per_key", "invalid": true} + "IGNORE_MOD_TAP_INTERRUPT_PER_KEY": {"info_key": "_invalid.ignore_mod_tap_interrupt_per_key", "invalid": true}, // USB params, need to mark as failure when specified in config.h, rather than deprecated "PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex", "deprecated": true, "replace_with": "`usb.pid` in info.json"},