diff options
Diffstat (limited to 'builddefs')
| -rw-r--r-- | builddefs/bootloader.mk | 49 | ||||
| -rw-r--r-- | builddefs/build_full_test.mk | 36 | ||||
| -rw-r--r-- | builddefs/build_json.mk | 17 | ||||
| -rw-r--r-- | builddefs/build_keyboard.mk | 469 | ||||
| -rw-r--r-- | builddefs/build_layout.mk | 32 | ||||
| -rw-r--r-- | builddefs/build_test.mk | 84 | ||||
| -rw-r--r-- | builddefs/common_features.mk | 816 | ||||
| -rw-r--r-- | builddefs/common_rules.mk | 523 | ||||
| -rw-r--r-- | builddefs/mcu_selection.mk | 77 | ||||
| -rw-r--r-- | builddefs/message.mk | 10 | ||||
| -rw-r--r-- | builddefs/testlist.mk | 19 | 
11 files changed, 2128 insertions, 4 deletions
diff --git a/builddefs/bootloader.mk b/builddefs/bootloader.mk index ccb92392d9..226213297e 100644 --- a/builddefs/bootloader.mk +++ b/builddefs/bootloader.mk @@ -30,6 +30,7 @@  #     bootloadhid  HIDBootFlash compatible (ATmega32A)  #     usbasploader USBaspLoader (ATmega328P)  # ARM: +#     halfkay      PJRC Teensy  #     kiibohd      Input:Club Kiibohd bootloader (only used on their boards)  #     stm32duino   STM32Duino (STM32F103x8)  #     stm32-dfu    STM32 USB DFU in ROM @@ -37,12 +38,23 @@  # RISC-V:  #     gd32v-dfu    GD32V USB DFU in ROM  # +# If you need to provide your own implementation, you can set inside `rules.mk` +# `BOOTLOADER = custom` -- you'll need to provide your own implementations. See +# the respective file under `platforms/<PLATFORM>/bootloaders/custom.c` to see +# which functions may be overridden. +#  # BOOTLOADER_SIZE can still be defined manually, but it's recommended  # you add any possible configuration to this list +ifeq ($(strip $(BOOTLOADER)), custom) +    OPT_DEFS += -DBOOTLOADER_CUSTOM +    BOOTLOADER_TYPE = custom +endif  ifeq ($(strip $(BOOTLOADER)), atmel-dfu)      OPT_DEFS += -DBOOTLOADER_ATMEL_DFU      OPT_DEFS += -DBOOTLOADER_DFU +    BOOTLOADER_TYPE = dfu +      ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))          BOOTLOADER_SIZE = 4096      endif @@ -53,6 +65,8 @@ endif  ifeq ($(strip $(BOOTLOADER)), lufa-dfu)      OPT_DEFS += -DBOOTLOADER_LUFA_DFU      OPT_DEFS += -DBOOTLOADER_DFU +    BOOTLOADER_TYPE = dfu +      ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))          BOOTLOADER_SIZE ?= 4096      endif @@ -63,6 +77,8 @@ endif  ifeq ($(strip $(BOOTLOADER)), qmk-dfu)      OPT_DEFS += -DBOOTLOADER_QMK_DFU      OPT_DEFS += -DBOOTLOADER_DFU +    BOOTLOADER_TYPE = dfu +      ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))          BOOTLOADER_SIZE ?= 4096      endif @@ -73,10 +89,14 @@ endif  ifeq ($(strip $(BOOTLOADER)), qmk-hid)      OPT_DEFS += -DBOOTLOADER_QMK_HID      OPT_DEFS += -DBOOTLOADER_HID +    BOOTLOADER_TYPE = dfu +      BOOTLOADER_SIZE ?= 4096  endif  ifeq ($(strip $(BOOTLOADER)), halfkay)      OPT_DEFS += -DBOOTLOADER_HALFKAY +    BOOTLOADER_TYPE = halfkay +      ifeq ($(strip $(MCU)), atmega32u4)          BOOTLOADER_SIZE = 512      endif @@ -86,18 +106,26 @@ ifeq ($(strip $(BOOTLOADER)), halfkay)  endif  ifeq ($(strip $(BOOTLOADER)), caterina)      OPT_DEFS += -DBOOTLOADER_CATERINA +    BOOTLOADER_TYPE = caterina +      BOOTLOADER_SIZE = 4096  endif  ifneq (,$(filter $(BOOTLOADER), bootloadhid bootloadHID))      OPT_DEFS += -DBOOTLOADER_BOOTLOADHID +    BOOTLOADER_TYPE = bootloadhid +      BOOTLOADER_SIZE = 4096  endif  ifneq (,$(filter $(BOOTLOADER), usbasploader USBasp))      OPT_DEFS += -DBOOTLOADER_USBASP +    BOOTLOADER_TYPE = usbasploader +      BOOTLOADER_SIZE = 4096  endif  ifeq ($(strip $(BOOTLOADER)), lufa-ms)      OPT_DEFS += -DBOOTLOADER_MS +    BOOTLOADER_TYPE = dfu +      BOOTLOADER_SIZE ?= 8192      FIRMWARE_FORMAT = bin  cpfirmware: lufa_warning @@ -115,6 +143,7 @@ endif  ifeq ($(strip $(BOOTLOADER)), stm32-dfu)      OPT_DEFS += -DBOOTLOADER_STM32_DFU +    BOOTLOADER_TYPE = stm32_dfu      # Options to pass to dfu-util when flashing      DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave @@ -122,6 +151,7 @@ ifeq ($(strip $(BOOTLOADER)), stm32-dfu)  endif  ifeq ($(strip $(BOOTLOADER)), apm32-dfu)      OPT_DEFS += -DBOOTLOADER_APM32_DFU +    BOOTLOADER_TYPE = stm32_dfu      # Options to pass to dfu-util when flashing      DFU_ARGS ?= -d 314B:0106 -a 0 -s 0x08000000:leave @@ -129,6 +159,7 @@ ifeq ($(strip $(BOOTLOADER)), apm32-dfu)  endif  ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)      OPT_DEFS += -DBOOTLOADER_GD32V_DFU +    BOOTLOADER_TYPE = gd32v_dfu      # Options to pass to dfu-util when flashing      DFU_ARGS ?= -d 28E9:0189 -a 0 -s 0x08000000:leave @@ -136,6 +167,8 @@ ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)  endif  ifeq ($(strip $(BOOTLOADER)), kiibohd)      OPT_DEFS += -DBOOTLOADER_KIIBOHD +    BOOTLOADER_TYPE = kiibohd +      ifeq ($(strip $(MCU_ORIG)), MK20DX128)          MCU_LDSCRIPT = MK20DX128BLDR4      endif @@ -151,8 +184,7 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino)      OPT_DEFS += -DBOOTLOADER_STM32DUINO      MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader      BOARD = STM32_F103_STM32DUINO -    # STM32F103 does NOT have an USB bootloader in ROM (only serial), so setting anything here does not make much sense -    STM32_BOOTLOADER_ADDRESS = 0x80000000 +    BOOTLOADER_TYPE = stm32duino      # Options to pass to dfu-util when flashing      DFU_ARGS = -d 1EAF:0003 -a 2 -R @@ -160,4 +192,17 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino)  endif  ifeq ($(strip $(BOOTLOADER)), tinyuf2)      OPT_DEFS += -DBOOTLOADER_TINYUF2 +    BOOTLOADER_TYPE = tinyuf2 +endif +ifeq ($(strip $(BOOTLOADER)), halfkay) +    OPT_DEFS += -DBOOTLOADER_HALFKAY +    BOOTLOADER_TYPE = halfkay +endif +ifeq ($(strip $(BOOTLOADER)), md-boot) +    OPT_DEFS += -DBOOTLOADER_MD_BOOT +    BOOTLOADER_TYPE = md_boot +endif + +ifeq ($(strip $(BOOTLOADER_TYPE)),) +    $(call CATASTROPHIC_ERROR,Invalid BOOTLOADER,No bootloader specified. Please set an appropriate 'BOOTLOADER' in your keyboard's 'rules.mk' file.)  endif diff --git a/builddefs/build_full_test.mk b/builddefs/build_full_test.mk new file mode 100644 index 0000000000..4e4b4e4bfd --- /dev/null +++ b/builddefs/build_full_test.mk @@ -0,0 +1,36 @@ +# Copyright 2017 Fred Sundvik +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +$(TEST)_INC := \ +	tests/test_common/common_config.h + +$(TEST)_SRC := \ +	$(TMK_COMMON_SRC) \ +	$(QUANTUM_SRC) \ +	$(SRC) \ +	tests/test_common/keymap.c \ +	tests/test_common/matrix.c \ +	tests/test_common/test_driver.cpp \ +	tests/test_common/keyboard_report_util.cpp \ +	tests/test_common/test_fixture.cpp \ +	tests/test_common/test_keymap_key.cpp \ +	tests/test_common/test_logger.cpp \ +	$(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp)) + +$(TEST)_DEFS := $(TMK_COMMON_DEFS) $(OPT_DEFS) + +$(TEST)_CONFIG := $(TEST_PATH)/config.h + +VPATH += $(TOP_DIR)/tests/test_common diff --git a/builddefs/build_json.mk b/builddefs/build_json.mk new file mode 100644 index 0000000000..0c034eb2ae --- /dev/null +++ b/builddefs/build_json.mk @@ -0,0 +1,17 @@ +# Look for a json keymap file +ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","") +    KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json +    KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5) +else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","") +    KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json +    KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4) +else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","") +    KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json +    KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3) +else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","") +    KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json +    KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2) +else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","") +    KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json +    KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1) +endif diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk new file mode 100644 index 0000000000..d5efcb4193 --- /dev/null +++ b/builddefs/build_keyboard.mk @@ -0,0 +1,469 @@ +# Determine what keyboard we are building and setup the build environment. +# +# We support folders up to 5 levels deep below `keyboards/`. This file is +# responsible for determining which folder is being used and doing the +# corresponding environment setup. + +ifndef VERBOSE +.SILENT: +endif + +.DEFAULT_GOAL := all + +include paths.mk +include $(BUILDDEFS_PATH)/message.mk + +# Set the qmk cli to use +QMK_BIN ?= qmk + +# Set the filename for the final firmware binary +KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD)) +TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP) +KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE) + +# Force expansion +TARGET := $(TARGET) + +ifneq ($(FORCE_LAYOUT),) +    TARGET := $(TARGET)_$(FORCE_LAYOUT) +endif + +# Object files and generated keymap directory +#     To put object files in current directory, use a dot (.), do NOT make +#     this an empty or blank macro! +KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET) + +ifdef SKIP_VERSION +    OPT_DEFS += -DSKIP_VERSION +endif + +# Generate the version.h file +ifdef SKIP_VERSION +VERSION_H_FLAGS := --skip-all +endif +ifdef SKIP_GIT +VERSION_H_FLAGS := --skip-git +endif + +# Generate the board's version.h file. +$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(KEYMAP_OUTPUT)/src/version.h) + +# Determine which subfolders exist. +KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD) +KEYBOARD_FOLDER_PATH_2 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_1))) +KEYBOARD_FOLDER_PATH_3 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_2))) +KEYBOARD_FOLDER_PATH_4 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_3))) +KEYBOARD_FOLDER_PATH_5 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_4))) +KEYBOARD_FOLDER_1 := $(notdir $(KEYBOARD_FOLDER_PATH_1)) +KEYBOARD_FOLDER_2 := $(notdir $(KEYBOARD_FOLDER_PATH_2)) +KEYBOARD_FOLDER_3 := $(notdir $(KEYBOARD_FOLDER_PATH_3)) +KEYBOARD_FOLDER_4 := $(notdir $(KEYBOARD_FOLDER_PATH_4)) +KEYBOARD_FOLDER_5 := $(notdir $(KEYBOARD_FOLDER_PATH_5)) +KEYBOARD_PATHS := +KEYBOARD_PATH_1 := keyboards/$(KEYBOARD_FOLDER_PATH_1) +KEYBOARD_PATH_2 := keyboards/$(KEYBOARD_FOLDER_PATH_2) +KEYBOARD_PATH_3 := keyboards/$(KEYBOARD_FOLDER_PATH_3) +KEYBOARD_PATH_4 := keyboards/$(KEYBOARD_FOLDER_PATH_4) +KEYBOARD_PATH_5 := keyboards/$(KEYBOARD_FOLDER_PATH_5) + +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/)","") +    KEYBOARD_PATHS += $(KEYBOARD_PATH_5) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/)","") +    KEYBOARD_PATHS += $(KEYBOARD_PATH_4) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/)","") +    KEYBOARD_PATHS += $(KEYBOARD_PATH_3) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/)","") +    KEYBOARD_PATHS += $(KEYBOARD_PATH_2) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/)","") +    KEYBOARD_PATHS += $(KEYBOARD_PATH_1) +endif + + +# Pull in rules.mk files from all our subfolders +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/rules.mk)","") +    include $(KEYBOARD_PATH_5)/rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/rules.mk)","") +    include $(KEYBOARD_PATH_4)/rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/rules.mk)","") +    include $(KEYBOARD_PATH_3)/rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/rules.mk)","") +    include $(KEYBOARD_PATH_2)/rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/rules.mk)","") +    include $(KEYBOARD_PATH_1)/rules.mk +endif + +MAIN_KEYMAP_PATH_1 := $(KEYBOARD_PATH_1)/keymaps/$(KEYMAP) +MAIN_KEYMAP_PATH_2 := $(KEYBOARD_PATH_2)/keymaps/$(KEYMAP) +MAIN_KEYMAP_PATH_3 := $(KEYBOARD_PATH_3)/keymaps/$(KEYMAP) +MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP) +MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP) + +# Pull in rules from info.json +INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_rules.mk) +include $(INFO_RULES_MK) + +# Check for keymap.json first, so we can regenerate keymap.c +include $(BUILDDEFS_PATH)/build_json.mk + +# Pull in keymap level rules.mk +ifeq ("$(wildcard $(KEYMAP_PATH))", "") +    # Look through the possible keymap folders until we find a matching keymap.c +    ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","") +        -include $(MAIN_KEYMAP_PATH_5)/rules.mk +        KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c +        KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5) +    else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","") +        -include $(MAIN_KEYMAP_PATH_4)/rules.mk +        KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c +        KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4) +    else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","") +        -include $(MAIN_KEYMAP_PATH_3)/rules.mk +        KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c +        KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3) +    else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","") +        -include $(MAIN_KEYMAP_PATH_2)/rules.mk +        KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c +        KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2) +    else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","") +        -include $(MAIN_KEYMAP_PATH_1)/rules.mk +        KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c +        KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1) +    else ifneq ($(LAYOUTS),) +        # If we haven't found a keymap yet fall back to community layouts +        include $(BUILDDEFS_PATH)/build_layout.mk +    else +        $(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap) +        # this state should never be reached +    endif +endif + +# Have we found a keymap.json? +ifneq ("$(wildcard $(KEYMAP_JSON))", "") +    KEYMAP_C := $(KEYMAP_OUTPUT)/src/keymap.c +    KEYMAP_H := $(KEYMAP_OUTPUT)/src/config.h + +    # Load the keymap-level rules.mk if exists +    -include $(KEYMAP_PATH)/rules.mk + +    # Load any rules.mk content from keymap.json +    INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --keymap $(KEYMAP) --output $(KEYMAP_OUTPUT)/src/rules.mk) +    include $(INFO_RULES_MK) + +# Add rules to generate the keymap files - indentation here is important +$(KEYMAP_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) +	$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) + +$(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON) +	$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --keymap $(KEYMAP) --output $(KEYMAP_H) + +generated-files: $(KEYMAP_OUTPUT)/src/config.h $(KEYMAP_OUTPUT)/src/keymap.c + +endif + +ifeq ($(strip $(CTPC)), yes) +    CONVERT_TO_PROTON_C=yes +endif + +ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes) +    include platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk +endif + +include $(BUILDDEFS_PATH)/mcu_selection.mk + +# Find all the C source files to be compiled in subfolders. +KEYBOARD_SRC := + +KEYBOARD_C_1 := $(KEYBOARD_PATH_1)/$(KEYBOARD_FOLDER_1).c +KEYBOARD_C_2 := $(KEYBOARD_PATH_2)/$(KEYBOARD_FOLDER_2).c +KEYBOARD_C_3 := $(KEYBOARD_PATH_3)/$(KEYBOARD_FOLDER_3).c +KEYBOARD_C_4 := $(KEYBOARD_PATH_4)/$(KEYBOARD_FOLDER_4).c +KEYBOARD_C_5 := $(KEYBOARD_PATH_5)/$(KEYBOARD_FOLDER_5).c + +ifneq ("$(wildcard $(KEYBOARD_C_5))","") +    KEYBOARD_SRC += $(KEYBOARD_C_5) +endif +ifneq ("$(wildcard $(KEYBOARD_C_4))","") +    KEYBOARD_SRC += $(KEYBOARD_C_4) +endif +ifneq ("$(wildcard $(KEYBOARD_C_3))","") +    KEYBOARD_SRC += $(KEYBOARD_C_3) +endif +ifneq ("$(wildcard $(KEYBOARD_C_2))","") +    KEYBOARD_SRC += $(KEYBOARD_C_2) +endif +ifneq ("$(wildcard $(KEYBOARD_C_1))","") +    KEYBOARD_SRC += $(KEYBOARD_C_1) +endif + +# Generate KEYBOARD_name_subname for all levels of the keyboard folder +KEYBOARD_FILESAFE_1 := $(subst .,,$(subst /,_,$(KEYBOARD_FOLDER_PATH_1))) +KEYBOARD_FILESAFE_2 := $(subst .,,$(subst /,_,$(KEYBOARD_FOLDER_PATH_2))) +KEYBOARD_FILESAFE_3 := $(subst .,,$(subst /,_,$(KEYBOARD_FOLDER_PATH_3))) +KEYBOARD_FILESAFE_4 := $(subst .,,$(subst /,_,$(KEYBOARD_FOLDER_PATH_4))) +KEYBOARD_FILESAFE_5 := $(subst .,,$(subst /,_,$(KEYBOARD_FOLDER_PATH_5))) + +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/)","") +    OPT_DEFS += -DKEYBOARD_$(KEYBOARD_FILESAFE_5) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/)","") +    OPT_DEFS += -DKEYBOARD_$(KEYBOARD_FILESAFE_4) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/)","") +    OPT_DEFS += -DKEYBOARD_$(KEYBOARD_FILESAFE_3) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/)","") +    OPT_DEFS += -DKEYBOARD_$(KEYBOARD_FILESAFE_2) +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/)","") +    OPT_DEFS += -DKEYBOARD_$(KEYBOARD_FILESAFE_1) +endif + +# Setup the define for QMK_KEYBOARD_H. This is used inside of keymaps so +# that the same keymap may be used on multiple keyboards. +# +# We grab the most top-level include file that we can. That file should +# use #ifdef statements to include all the neccesary subfolder includes, +# as described here: +# +#    https://docs.qmk.fm/#/feature_layouts?id=tips-for-making-layouts-keyboard-agnostic +# +QMK_KEYBOARD_H = $(KEYBOARD_OUTPUT)/src/default_keyboard.h +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/$(KEYBOARD_FOLDER_1).h)","") +    QMK_KEYBOARD_H = $(KEYBOARD_FOLDER_1).h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/$(KEYBOARD_FOLDER_2).h)","") +    QMK_KEYBOARD_H = $(KEYBOARD_FOLDER_2).h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/$(KEYBOARD_FOLDER_3).h)","") +    QMK_KEYBOARD_H = $(KEYBOARD_FOLDER_3).h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/$(KEYBOARD_FOLDER_4).h)","") +    QMK_KEYBOARD_H = $(KEYBOARD_FOLDER_4).h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/$(KEYBOARD_FOLDER_5).h)","") +    QMK_KEYBOARD_H = $(KEYBOARD_FOLDER_5).h +endif + +# Determine and set parameters based on the keyboard's processor family. +# We can assume a ChibiOS target When MCU_FAMILY is defined since it's +# not used for LUFA +ifdef MCU_FAMILY +    PLATFORM=CHIBIOS +    PLATFORM_KEY=chibios +    FIRMWARE_FORMAT?=bin +    OPT_DEFS += -DMCU_$(MCU_FAMILY) +else ifdef ARM_ATSAM +    PLATFORM=ARM_ATSAM +    PLATFORM_KEY=arm_atsam +    FIRMWARE_FORMAT=bin +else +    PLATFORM=AVR +    PLATFORM_KEY=avr +    FIRMWARE_FORMAT?=hex +endif + +# Find all of the config.h files and add them to our CONFIG_H define. +CONFIG_H := +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","") +    CONFIG_H += $(KEYBOARD_PATH_5)/config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/config.h)","") +    CONFIG_H += $(KEYBOARD_PATH_4)/config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/config.h)","") +    CONFIG_H += $(KEYBOARD_PATH_3)/config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/config.h)","") +    CONFIG_H += $(KEYBOARD_PATH_2)/config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/config.h)","") +    CONFIG_H += $(KEYBOARD_PATH_1)/config.h +endif + +POST_CONFIG_H := +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/post_config.h)","") +    POST_CONFIG_H += $(KEYBOARD_PATH_1)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/post_config.h)","") +    POST_CONFIG_H += $(KEYBOARD_PATH_2)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/post_config.h)","") +    POST_CONFIG_H += $(KEYBOARD_PATH_3)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/post_config.h)","") +    POST_CONFIG_H += $(KEYBOARD_PATH_4)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","") +    POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h +endif + +# Pull in stuff from info.json +INFO_JSON_FILES := +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/info.json)","") +    INFO_JSON_FILES += $(KEYBOARD_PATH_1)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/info.json)","") +    INFO_JSON_FILES += $(KEYBOARD_PATH_2)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/info.json)","") +    INFO_JSON_FILES += $(KEYBOARD_PATH_3)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/info.json)","") +    INFO_JSON_FILES += $(KEYBOARD_PATH_4)/info.json +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","") +    INFO_JSON_FILES += $(KEYBOARD_PATH_5)/info.json +endif + +CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/layouts.h + +$(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES) +	$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h + +$(KEYBOARD_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES) +	$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h + +$(KEYBOARD_OUTPUT)/src/layouts.h: $(INFO_JSON_FILES) +	$(QMK_BIN) generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h + +generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h + +.INTERMEDIATE : generated-files + +# Userspace setup and definitions +ifeq ("$(USER_NAME)","") +    USER_NAME := $(KEYMAP) +endif +USER_PATH := users/$(USER_NAME) + +# Pull in user level rules.mk +-include $(USER_PATH)/rules.mk +ifneq ("$(wildcard $(USER_PATH)/config.h)","") +    CONFIG_H += $(USER_PATH)/config.h +endif +ifneq ("$(wildcard $(USER_PATH)/post_config.h)","") +    POST_CONFIG_H += $(USER_PATH)/post_config.h +endif + +# Disable features that a keyboard doesn't support +-include $(BUILDDEFS_PATH)/disable_features.mk + +# Pull in post_rules.mk files from all our subfolders +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/post_rules.mk)","") +    include $(KEYBOARD_PATH_1)/post_rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/post_rules.mk)","") +    include $(KEYBOARD_PATH_2)/post_rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/post_rules.mk)","") +    include $(KEYBOARD_PATH_3)/post_rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/post_rules.mk)","") +    include $(KEYBOARD_PATH_4)/post_rules.mk +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_rules.mk)","") +    include $(KEYBOARD_PATH_5)/post_rules.mk +endif + +ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","") +    CONFIG_H += $(KEYMAP_PATH)/config.h +endif +ifneq ("$(KEYMAP_H)","") +    CONFIG_H += $(KEYMAP_H) +endif + +# project specific files +SRC += \ +    $(KEYBOARD_SRC) \ +    $(KEYMAP_C) \ +    $(QUANTUM_SRC) \ +    $(QUANTUM_DIR)/main.c \ + +# Optimize size but this may cause error "relocation truncated to fit" +#EXTRALDFLAGS = -Wl,--relax + +# Search Path +VPATH += $(KEYMAP_PATH) +VPATH += $(USER_PATH) +VPATH += $(KEYBOARD_PATHS) +VPATH += $(COMMON_VPATH) +VPATH += $(KEYBOARD_OUTPUT)/src +VPATH += $(KEYMAP_OUTPUT)/src + +include $(BUILDDEFS_PATH)/common_features.mk +include $(BUILDDEFS_PATH)/generic_features.mk +include $(TMK_PATH)/protocol.mk +include $(PLATFORM_PATH)/common.mk +include $(BUILDDEFS_PATH)/bootloader.mk + +SRC += $(patsubst %.c,%.clib,$(LIB_SRC)) +SRC += $(patsubst %.c,%.clib,$(QUANTUM_LIB_SRC)) +SRC += $(TMK_COMMON_SRC) +OPT_DEFS += $(TMK_COMMON_DEFS) +EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS) + +SKIP_COMPILE := no +ifneq ($(REQUIRE_PLATFORM_KEY),) +    ifneq ($(REQUIRE_PLATFORM_KEY),$(PLATFORM_KEY)) +        SKIP_COMPILE := yes +    endif +endif + +include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk +-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash.mk + +ifneq ($(strip $(PROTOCOL)),) +    include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk +else +    include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk +endif + +# TODO: remove this bodge? +PROJECT_DEFS := $(OPT_DEFS) +PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS) +PROJECT_CONFIG := $(CONFIG_H) + +CONFIG_H += $(POST_CONFIG_H) +ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H) + +OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT) +$(KEYMAP_OUTPUT)_SRC := $(SRC) +$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \ +-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(QMK_KEYBOARD_H)\" \ +-DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\" +$(KEYMAP_OUTPUT)_INC :=  $(VPATH) $(EXTRAINCDIRS) +$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H) +$(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC) +$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS) +$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC) +$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG) + +# Default target. +ifeq ($(SKIP_COMPILE),no) +all: build check-size +else +all: +	echo "skipped" >&2 +endif + +build: elf cpfirmware +check-size: build +check-md5: build +objs-size: build + +include $(BUILDDEFS_PATH)/show_options.mk +include $(BUILDDEFS_PATH)/common_rules.mk + +# Ensure we have generated files available for each of the objects +define GEN_FILES +$1: generated-files +endef +$(foreach O,$(OBJ),$(eval $(call GEN_FILES,$(patsubst %.a,%.o,$(O))))) diff --git a/builddefs/build_layout.mk b/builddefs/build_layout.mk new file mode 100644 index 0000000000..6166bd847c --- /dev/null +++ b/builddefs/build_layout.mk @@ -0,0 +1,32 @@ +LAYOUTS_PATH := layouts +LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/)))) + +define SEARCH_LAYOUTS_REPO +    LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP) +    LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json +    LAYOUT_KEYMAP_C := $$(LAYOUT_KEYMAP_PATH)/keymap.c +    ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_JSON))","") +        -include $$(LAYOUT_KEYMAP_PATH)/rules.mk +        KEYMAP_JSON := $$(LAYOUT_KEYMAP_JSON) +        KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH) +    else ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","") +        -include $$(LAYOUT_KEYMAP_PATH)/rules.mk +        KEYMAP_C := $$(LAYOUT_KEYMAP_C) +        KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH) +    endif +endef + +define SEARCH_LAYOUTS +    $$(foreach LAYOUTS_REPO,$$(LAYOUTS_REPOS),$$(eval $$(call SEARCH_LAYOUTS_REPO))) +endef + +ifneq ($(FORCE_LAYOUT),) +    ifneq (,$(findstring $(FORCE_LAYOUT),$(LAYOUTS))) +        $(info Forcing layout: $(FORCE_LAYOUT)) +        LAYOUTS := $(FORCE_LAYOUT) +    else +        $(call CATASTROPHIC_ERROR,Invalid layout,Forced layout does not exist) +    endif +endif + +$(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS))) diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk new file mode 100644 index 0000000000..7226004aab --- /dev/null +++ b/builddefs/build_test.mk @@ -0,0 +1,84 @@ +ifndef VERBOSE +.SILENT: +endif + +.DEFAULT_GOAL := all + +include paths.mk +include $(BUILDDEFS_PATH)/message.mk + +TARGET=test/$(TEST) + +GTEST_OUTPUT = $(BUILD_DIR)/gtest + +TEST_OBJ = $(BUILD_DIR)/test_obj + +OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT) + +GTEST_INC := \ +	$(LIB_PATH)/googletest/googletest/include \ +	$(LIB_PATH)/googletest/googlemock/include + +GTEST_INTERNAL_INC := \ +	$(LIB_PATH)/googletest/googletest \ +	$(LIB_PATH)/googletest/googlemock + +$(GTEST_OUTPUT)_SRC := \ +	googletest/src/gtest-all.cc\ +	googlemock/src/gmock-all.cc + +$(GTEST_OUTPUT)_DEFS := +$(GTEST_OUTPUT)_INC := $(GTEST_INC) $(GTEST_INTERNAL_INC) + +LDFLAGS += -lstdc++ -lpthread -shared-libgcc +CREATE_MAP := no + +VPATH += \ +	$(LIB_PATH)/googletest \ +	$(LIB_PATH)/googlemock \ +	$(LIB_PATH)/printf + +all: elf + +VPATH += $(COMMON_VPATH) +PLATFORM:=TEST +PLATFORM_KEY:=test +BOOTLOADER_TYPE:=none + +ifeq ($(strip $(DEBUG)), 1) +CONSOLE_ENABLE = yes +endif + +ifneq ($(filter $(FULL_TESTS),$(TEST)),) +include tests/test_common/build.mk +include $(TEST_PATH)/test.mk +endif + +include $(BUILDDEFS_PATH)/common_features.mk +include $(BUILDDEFS_PATH)/generic_features.mk +include $(PLATFORM_PATH)/common.mk +include $(TMK_PATH)/protocol.mk +include $(QUANTUM_PATH)/debounce/tests/rules.mk +include $(QUANTUM_PATH)/encoder/tests/rules.mk +include $(QUANTUM_PATH)/sequencer/tests/rules.mk +include $(PLATFORM_PATH)/test/rules.mk +ifneq ($(filter $(FULL_TESTS),$(TEST)),) +include $(BUILDDEFS_PATH)/build_full_test.mk +endif + +$(TEST)_SRC += \ +	tests/test_common/main.c \ +	$(LIB_PATH)/printf/printf.c \ +	$(QUANTUM_PATH)/logging/print.c + +$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC) +$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC) +$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS) +$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG) + +include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk +include $(BUILDDEFS_PATH)/common_rules.mk + + +$(shell mkdir -p $(BUILD_DIR)/test 2>/dev/null) +$(shell mkdir -p $(TEST_OBJ) 2>/dev/null) diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk new file mode 100644 index 0000000000..08d186d656 --- /dev/null +++ b/builddefs/common_features.mk @@ -0,0 +1,816 @@ +# Copyright 2017 Fred Sundvik +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +QUANTUM_SRC += \ +    $(QUANTUM_DIR)/quantum.c \ +    $(QUANTUM_DIR)/send_string.c \ +    $(QUANTUM_DIR)/bitwise.c \ +    $(QUANTUM_DIR)/led.c \ +    $(QUANTUM_DIR)/action.c \ +    $(QUANTUM_DIR)/action_layer.c \ +    $(QUANTUM_DIR)/action_tapping.c \ +    $(QUANTUM_DIR)/action_util.c \ +    $(QUANTUM_DIR)/eeconfig.c \ +    $(QUANTUM_DIR)/keyboard.c \ +    $(QUANTUM_DIR)/keymap_common.c \ +    $(QUANTUM_DIR)/keycode_config.c \ +    $(QUANTUM_DIR)/sync_timer.c \ +    $(QUANTUM_DIR)/logging/debug.c \ +    $(QUANTUM_DIR)/logging/sendchar.c \ + +VPATH += $(QUANTUM_DIR)/logging +# Fall back to lib/printf if there is no platform provided print +ifeq ("$(wildcard $(PLATFORM_PATH)/$(PLATFORM_KEY)/printf.mk)","") +    include $(QUANTUM_PATH)/logging/print.mk +else +    include $(PLATFORM_PATH)/$(PLATFORM_KEY)/printf.mk +endif + +ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes) +    OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE +    CONSOLE_ENABLE = yes +else ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), api) +    OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE +endif + +AUDIO_ENABLE ?= no +ifeq ($(strip $(AUDIO_ENABLE)), yes) +    ifeq ($(PLATFORM),CHIBIOS) +        AUDIO_DRIVER ?= dac_basic +        ifeq ($(strip $(AUDIO_DRIVER)), dac_basic) +            OPT_DEFS += -DAUDIO_DRIVER_DAC +        else ifeq ($(strip $(AUDIO_DRIVER)), dac_additive) +            OPT_DEFS += -DAUDIO_DRIVER_DAC +        ## stm32f2 and above have a usable DAC unit, f1 do not, and need to use pwm instead +        else ifeq ($(strip $(AUDIO_DRIVER)), pwm_software) +            OPT_DEFS += -DAUDIO_DRIVER_PWM +        else ifeq ($(strip $(AUDIO_DRIVER)), pwm_hardware) +            OPT_DEFS += -DAUDIO_DRIVER_PWM +        endif +    else +        # fallback for all other platforms is pwm +        AUDIO_DRIVER ?= pwm_hardware +        OPT_DEFS += -DAUDIO_DRIVER_PWM +    endif +    OPT_DEFS += -DAUDIO_ENABLE +    MUSIC_ENABLE = yes +    SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c +    SRC += $(QUANTUM_DIR)/process_keycode/process_clicky.c +    SRC += $(QUANTUM_DIR)/audio/audio.c ## common audio code, hardware agnostic +    SRC += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/audio_$(strip $(AUDIO_DRIVER)).c +    SRC += $(QUANTUM_DIR)/audio/voices.c +    SRC += $(QUANTUM_DIR)/audio/luts.c +endif + +ifeq ($(strip $(SEQUENCER_ENABLE)), yes) +    OPT_DEFS += -DSEQUENCER_ENABLE +    MUSIC_ENABLE = yes +    SRC += $(QUANTUM_DIR)/sequencer/sequencer.c +    SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c +endif + +ifeq ($(strip $(MIDI_ENABLE)), yes) +    OPT_DEFS += -DMIDI_ENABLE +    MUSIC_ENABLE = yes +    SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c +endif + +MUSIC_ENABLE ?= no +ifeq ($(MUSIC_ENABLE), yes) +    SRC += $(QUANTUM_DIR)/process_keycode/process_music.c +endif + +ifeq ($(strip $(STENO_ENABLE)), yes) +    OPT_DEFS += -DSTENO_ENABLE +    VIRTSER_ENABLE ?= yes +    SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c +endif + +ifeq ($(strip $(VIRTSER_ENABLE)), yes) +    OPT_DEFS += -DVIRTSER_ENABLE +endif + +ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) +    OPT_DEFS += -DMOUSEKEY_ENABLE +    MOUSE_ENABLE := yes +    SRC += $(QUANTUM_DIR)/mousekey.c +endif + +VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi pmw3360 pmw3389 pimoroni_trackball custom +ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) +    ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid POINTING_DEVICE_DRIVER,POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type) +    else +        OPT_DEFS += -DPOINTING_DEVICE_ENABLE +        MOUSE_ENABLE := yes +        SRC += $(QUANTUM_DIR)/pointing_device.c +        SRC += $(QUANTUM_DIR)/pointing_device_drivers.c +        ifneq ($(strip $(POINTING_DEVICE_DRIVER)), custom) +            SRC += drivers/sensors/$(strip $(POINTING_DEVICE_DRIVER)).c +            OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(shell echo $(POINTING_DEVICE_DRIVER) | tr '[:lower:]' '[:upper:]')) +        endif +        OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(POINTING_DEVICE_DRIVER)) +        ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800) +            OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE +            QUANTUM_LIB_SRC += spi_master.c +        else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick) +            OPT_DEFS += -DSTM32_ADC -DHAL_USE_ADC=TRUE +            LIB_SRC += analog.c +        else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_i2c) +            OPT_DEFS += -DSTM32_I2C -DHAL_USE_I2C=TRUE +            SRC += drivers/sensors/cirque_pinnacle.c +            QUANTUM_LIB_SRC += i2c_master.c +        else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_spi) +            OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE +            SRC += drivers/sensors/cirque_pinnacle.c +            QUANTUM_LIB_SRC += spi_master.c +        else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pimoroni_trackball) +            OPT_DEFS += -DSTM32_SPI -DHAL_USE_I2C=TRUE +            QUANTUM_LIB_SRC += i2c_master.c +        else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3360) +            OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE +            QUANTUM_LIB_SRC += spi_master.c +        else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3389) +            OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE +            QUANTUM_LIB_SRC += spi_master.c +        endif +    endif +endif + +VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi +EEPROM_DRIVER ?= vendor +ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),) +  $(call CATASTROPHIC_ERROR,Invalid EEPROM_DRIVER,EEPROM_DRIVER="$(EEPROM_DRIVER)" is not a valid EEPROM driver) +else +  OPT_DEFS += -DEEPROM_ENABLE +  ifeq ($(strip $(EEPROM_DRIVER)), custom) +    # Custom EEPROM implementation -- only needs to implement init/erase/read_block/write_block +    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_CUSTOM +    COMMON_VPATH += $(DRIVER_PATH)/eeprom +    SRC += eeprom_driver.c +  else ifeq ($(strip $(EEPROM_DRIVER)), i2c) +    # External I2C EEPROM implementation +    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C +    COMMON_VPATH += $(DRIVER_PATH)/eeprom +    QUANTUM_LIB_SRC += i2c_master.c +    SRC += eeprom_driver.c eeprom_i2c.c +  else ifeq ($(strip $(EEPROM_DRIVER)), spi) +    # External SPI EEPROM implementation +    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI +    COMMON_VPATH += $(DRIVER_PATH)/eeprom +    QUANTUM_LIB_SRC += spi_master.c +    SRC += eeprom_driver.c eeprom_spi.c +  else ifeq ($(strip $(EEPROM_DRIVER)), transient) +    # Transient EEPROM implementation -- no data storage but provides runtime area for it +    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT +    COMMON_VPATH += $(DRIVER_PATH)/eeprom +    SRC += eeprom_driver.c eeprom_transient.c +  else ifeq ($(strip $(EEPROM_DRIVER)), vendor) +    # Vendor-implemented EEPROM +    OPT_DEFS += -DEEPROM_VENDOR +    ifeq ($(PLATFORM),AVR) +      # Automatically provided by avr-libc, nothing required +    else ifeq ($(PLATFORM),CHIBIOS) +      ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6 %_GD32VF103xB %_GD32VF103x8, $(MCU_SERIES)_$(MCU_LDSCRIPT)),) +        # Emulated EEPROM +        OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_FLASH_EMULATED +        COMMON_VPATH += $(DRIVER_PATH)/eeprom +        SRC += eeprom_driver.c +        SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c +        SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c +      else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),) +        # True EEPROM on STM32L0xx, L1xx +        OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_L0_L1 +        COMMON_VPATH += $(DRIVER_PATH)/eeprom +        COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom +        SRC += eeprom_driver.c +        SRC += eeprom_stm32_L0_L1.c +      else ifneq ($(filter $(MCU_SERIES),KL2x K20x),) +        # Teensy EEPROM implementations +        OPT_DEFS += -DEEPROM_TEENSY +        SRC += eeprom_teensy.c +      else +        # Fall back to transient, i.e. non-persistent +        OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT +        COMMON_VPATH += $(DRIVER_PATH)/eeprom +        SRC += eeprom_driver.c eeprom_transient.c +      endif +    else ifeq ($(PLATFORM),ARM_ATSAM) +      # arm_atsam EEPROM +      OPT_DEFS += -DEEPROM_SAMD +      SRC += $(PLATFORM_COMMON_DIR)/eeprom_samd.c +    else ifeq ($(PLATFORM),TEST) +      # Test harness "EEPROM" +      OPT_DEFS += -DEEPROM_TEST_HARNESS +      SRC += $(PLATFORM_COMMON_DIR)/eeprom.c +    endif +  endif +endif + +VALID_FLASH_DRIVER_TYPES := spi +FLASH_DRIVER ?= no +ifneq ($(strip $(FLASH_DRIVER)), no) +    ifeq ($(filter $(FLASH_DRIVER),$(VALID_FLASH_DRIVER_TYPES)),) +        $(error FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid FLASH driver) +    else +        OPT_DEFS += -DFLASH_ENABLE +        ifeq ($(strip $(FLASH_DRIVER)), spi) +            OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI +            COMMON_VPATH += $(DRIVER_PATH)/flash +            SRC += flash_spi.c +        endif +    endif +endif + +RGBLIGHT_ENABLE ?= no +VALID_RGBLIGHT_TYPES := WS2812 APA102 custom + +ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) +    RGBLIGHT_DRIVER ?= custom +endif + +ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) +    RGBLIGHT_DRIVER ?= WS2812 + +    ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid RGBLIGHT_DRIVER,RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type) +    else +        COMMON_VPATH += $(QUANTUM_DIR)/rgblight +        POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h +        OPT_DEFS += -DRGBLIGHT_ENABLE +        SRC += $(QUANTUM_DIR)/color.c +        SRC += $(QUANTUM_DIR)/rgblight/rgblight.c +        CIE1931_CURVE := yes +        RGB_KEYCODES_ENABLE := yes +    endif + +    ifeq ($(strip $(RGBLIGHT_DRIVER)), WS2812) +        WS2812_DRIVER_REQUIRED := yes +    endif + +    ifeq ($(strip $(RGBLIGHT_DRIVER)), APA102) +        APA102_DRIVER_REQUIRED := yes +    endif + +    ifeq ($(strip $(RGBLIGHT_DRIVER)), custom) +        OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER +    endif +endif + +LED_MATRIX_ENABLE ?= no +VALID_LED_MATRIX_TYPES := IS31FL3731 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A custom +# TODO: IS31FL3733 IS31FL3737 IS31FL3741 + +ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) +    ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid LED_MATRIX_DRIVER,LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type) +    endif +    OPT_DEFS += -DLED_MATRIX_ENABLE +ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) +    # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines +    OPT_DEFS += -DLIB8_ATTINY +endif +    COMMON_VPATH += $(QUANTUM_DIR)/led_matrix +    COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations +    COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners +    SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c +    SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c +    SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c +    SRC += $(LIB_PATH)/lib8tion/lib8tion.c +    CIE1931_CURVE := yes + +    ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731) +        OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31fl3731-simple.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3742A) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3743A) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3745) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3746A) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +endif + +RGB_MATRIX_ENABLE ?= no + +VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 WS2812 custom +ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) +    ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type) +    endif +    OPT_DEFS += -DRGB_MATRIX_ENABLE +ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) +    # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines +    OPT_DEFS += -DLIB8_ATTINY +endif +    COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix +    COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations +    COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners +    SRC += $(QUANTUM_DIR)/color.c +    SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c +    SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c +    SRC += $(LIB_PATH)/lib8tion/lib8tion.c +    CIE1931_CURVE := yes +    RGB_KEYCODES_ENABLE := yes + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), AW20216) +        OPT_DEFS += -DAW20216 -DSTM32_SPI -DHAL_USE_SPI=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led +        SRC += aw20216.c +        QUANTUM_LIB_SRC += spi_master.c +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731) +        OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31fl3731.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733) +        OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31fl3733.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737) +        OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31fl3737.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741) +        OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31fl3741.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3742A) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3743A) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3745) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +	ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3746A) +        OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led/issi +        SRC += is31flcommon.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001) +        OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE +        COMMON_VPATH += $(DRIVER_PATH)/led +        SRC += ckled2001.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812) +        OPT_DEFS += -DWS2812 +        WS2812_DRIVER_REQUIRED := yes +    endif + +    ifeq ($(strip $(RGB_MATRIX_DRIVER)), APA102) +        OPT_DEFS += -DAPA102 +        APA102_DRIVER_REQUIRED := yes +    endif + +    ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes) +        OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB +    endif + +    ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes) +        OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER +    endif +endif + +ifeq ($(strip $(RGB_KEYCODES_ENABLE)), yes) +    SRC += $(QUANTUM_DIR)/process_keycode/process_rgb.c +endif + +ifeq ($(strip $(PRINTING_ENABLE)), yes) +    OPT_DEFS += -DPRINTING_ENABLE +    SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c +    QUANTUM_LIB_SRC += uart.c +endif + +VARIABLE_TRACE ?= no +ifneq ($(strip $(VARIABLE_TRACE)),no) +    SRC += $(QUANTUM_DIR)/variable_trace.c +    OPT_DEFS += -DNUM_TRACED_VARIABLES=$(strip $(VARIABLE_TRACE)) +    ifneq ($(strip $(MAX_VARIABLE_TRACE_SIZE)),) +        OPT_DEFS += -DMAX_VARIABLE_TRACE_SIZE=$(strip $(MAX_VARIABLE_TRACE_SIZE)) +    endif +endif + +ifeq ($(strip $(SLEEP_LED_ENABLE)), yes) +    SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c +    OPT_DEFS += -DSLEEP_LED_ENABLE + +    NO_SUSPEND_POWER_DOWN := yes +endif + +VALID_BACKLIGHT_TYPES := pwm timer software custom + +BACKLIGHT_ENABLE ?= no +ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes) +    BACKLIGHT_DRIVER ?= software +else +    BACKLIGHT_DRIVER ?= pwm +endif +ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) +    ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid BACKLIGHT_DRIVER,BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type) +    endif + +    COMMON_VPATH += $(QUANTUM_DIR)/backlight +    SRC += $(QUANTUM_DIR)/backlight/backlight.c +    SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c +    OPT_DEFS += -DBACKLIGHT_ENABLE + +    ifeq ($(strip $(BACKLIGHT_DRIVER)), custom) +        OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER +    else +        SRC += $(QUANTUM_DIR)/backlight/backlight_driver_common.c +        ifeq ($(strip $(BACKLIGHT_DRIVER)), pwm) +            SRC += $(QUANTUM_DIR)/backlight/backlight_$(PLATFORM_KEY).c +        else +            SRC += $(QUANTUM_DIR)/backlight/backlight_$(strip $(BACKLIGHT_DRIVER)).c +        endif +    endif +endif + +VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c + +WS2812_DRIVER ?= bitbang +ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes) +    ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid WS2812_DRIVER,WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver) +    endif + +    OPT_DEFS += -DWS2812_DRIVER_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]')) + +    ifeq ($(strip $(WS2812_DRIVER)), bitbang) +        SRC += ws2812.c +    else +        SRC += ws2812_$(strip $(WS2812_DRIVER)).c + +        ifeq ($(strip $(PLATFORM)), CHIBIOS) +            ifeq ($(strip $(WS2812_DRIVER)), pwm) +                OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE +            endif +        endif +    endif + +    # add extra deps +    ifeq ($(strip $(WS2812_DRIVER)), i2c) +        QUANTUM_LIB_SRC += i2c_master.c +    endif +endif + +ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes) +    COMMON_VPATH += $(DRIVER_PATH)/led +    SRC += apa102.c +endif + +ifeq ($(strip $(CIE1931_CURVE)), yes) +    OPT_DEFS += -DUSE_CIE1931_CURVE +    LED_TABLES := yes +endif + +ifeq ($(strip $(LED_TABLES)), yes) +    SRC += $(QUANTUM_DIR)/led_tables.c +endif + +ifeq ($(strip $(TERMINAL_ENABLE)), yes) +    SRC += $(QUANTUM_DIR)/process_keycode/process_terminal.c +    OPT_DEFS += -DTERMINAL_ENABLE +    OPT_DEFS += -DUSER_PRINT +endif + +ifeq ($(strip $(VIA_ENABLE)), yes) +    DYNAMIC_KEYMAP_ENABLE := yes +    RAW_ENABLE := yes +    BOOTMAGIC_ENABLE := yes +    SRC += $(QUANTUM_DIR)/via.c +    OPT_DEFS += -DVIA_ENABLE +endif + +VALID_MAGIC_TYPES := yes +BOOTMAGIC_ENABLE ?= no +ifneq ($(strip $(BOOTMAGIC_ENABLE)), no) +  ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),) +    $(call CATASTROPHIC_ERROR,Invalid BOOTMAGIC_ENABLE,BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic) +  endif +  ifneq ($(strip $(BOOTMAGIC_ENABLE)), no) +      OPT_DEFS += -DBOOTMAGIC_LITE +      QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_lite.c +  endif +endif +COMMON_VPATH += $(QUANTUM_DIR)/bootmagic +QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/magic.c + +VALID_CUSTOM_MATRIX_TYPES:= yes lite no + +CUSTOM_MATRIX ?= no + +ifneq ($(strip $(CUSTOM_MATRIX)), yes) +    ifeq ($(filter $(CUSTOM_MATRIX),$(VALID_CUSTOM_MATRIX_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid CUSTOM_MATRIX,CUSTOM_MATRIX="$(CUSTOM_MATRIX)" is not a valid custom matrix type) +    endif + +    # Include common stuff for all non custom matrix users +    QUANTUM_SRC += $(QUANTUM_DIR)/matrix_common.c + +    # if 'lite' then skip the actual matrix implementation +    ifneq ($(strip $(CUSTOM_MATRIX)), lite) +        # Include the standard or split matrix code if needed +        QUANTUM_SRC += $(QUANTUM_DIR)/matrix.c +    endif +endif + +# Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually. +DEBOUNCE_TYPE ?= sym_defer_g +ifneq ($(strip $(DEBOUNCE_TYPE)), custom) +    QUANTUM_SRC += $(QUANTUM_DIR)/debounce/$(strip $(DEBOUNCE_TYPE)).c +endif + +ifeq ($(strip $(SPLIT_KEYBOARD)), yes) +    POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h +    OPT_DEFS += -DSPLIT_KEYBOARD +    CRC_ENABLE := yes + +    # Include files used by all split keyboards +    QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_util.c + +    # Determine which (if any) transport files are required +    ifneq ($(strip $(SPLIT_TRANSPORT)), custom) +        QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \ +                       $(QUANTUM_DIR)/split_common/transactions.c + +        OPT_DEFS += -DSPLIT_COMMON_TRANSACTIONS + +        # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called. +        # Unused functions are pruned away, which is why we can add multiple drivers here without bloat. +        ifeq ($(PLATFORM),AVR) +            ifneq ($(NO_I2C),yes) +                QUANTUM_LIB_SRC += i2c_master.c \ +                                   i2c_slave.c +            endif +        endif + +        SERIAL_DRIVER ?= bitbang +        OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]')) +        ifeq ($(strip $(SERIAL_DRIVER)), bitbang) +            QUANTUM_LIB_SRC += serial.c +        else +            QUANTUM_LIB_SRC += serial_$(strip $(SERIAL_DRIVER)).c +        endif +    endif +    COMMON_VPATH += $(QUANTUM_PATH)/split_common +endif + +ifeq ($(strip $(CRC_ENABLE)), yes) +    OPT_DEFS += -DCRC_ENABLE +    SRC += crc.c +endif + +ifeq ($(strip $(HAPTIC_ENABLE)),yes) +    COMMON_VPATH += $(DRIVER_PATH)/haptic + +    ifneq ($(filter DRV2605L, $(HAPTIC_DRIVER)), ) +        SRC += DRV2605L.c +        QUANTUM_LIB_SRC += i2c_master.c +        OPT_DEFS += -DDRV2605L +    endif + +    ifneq ($(filter SOLENOID, $(HAPTIC_DRIVER)), ) +        SRC += solenoid.c +        OPT_DEFS += -DSOLENOID_ENABLE +    endif +endif + +ifeq ($(strip $(HD44780_ENABLE)), yes) +    SRC += platforms/avr/drivers/hd44780.c +    OPT_DEFS += -DHD44780_ENABLE +endif + +VALID_OLED_DRIVER_TYPES := SSD1306 custom +OLED_DRIVER ?= SSD1306 +ifeq ($(strip $(OLED_ENABLE)), yes) +    ifeq ($(filter $(OLED_DRIVER),$(VALID_OLED_DRIVER_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid OLED_DRIVER,OLED_DRIVER="$(OLED_DRIVER)" is not a valid OLED driver) +    else +        OPT_DEFS += -DOLED_ENABLE +        COMMON_VPATH += $(DRIVER_PATH)/oled + +        OPT_DEFS += -DOLED_DRIVER_$(strip $(shell echo $(OLED_DRIVER) | tr '[:lower:]' '[:upper:]')) +        ifeq ($(strip $(OLED_DRIVER)), SSD1306) +            SRC += ssd1306_sh1106.c +            QUANTUM_LIB_SRC += i2c_master.c +        endif +    endif +endif + +ifeq ($(strip $(ST7565_ENABLE)), yes) +    OPT_DEFS += -DST7565_ENABLE +    COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h +    COMMON_VPATH += $(DRIVER_PATH)/lcd +    QUANTUM_LIB_SRC += spi_master.c +    SRC += st7565.c +endif + +ifeq ($(strip $(UCIS_ENABLE)), yes) +    OPT_DEFS += -DUCIS_ENABLE +    UNICODE_COMMON := yes +    SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c +endif + +ifeq ($(strip $(UNICODEMAP_ENABLE)), yes) +    OPT_DEFS += -DUNICODEMAP_ENABLE +    UNICODE_COMMON := yes +    SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c +endif + +ifeq ($(strip $(UNICODE_ENABLE)), yes) +    OPT_DEFS += -DUNICODE_ENABLE +    UNICODE_COMMON := yes +    SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c +endif + +ifeq ($(strip $(UNICODE_COMMON)), yes) +    OPT_DEFS += -DUNICODE_COMMON_ENABLE +    SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c +endif + +MAGIC_ENABLE ?= yes +ifeq ($(strip $(MAGIC_ENABLE)), yes) +    SRC += $(QUANTUM_DIR)/process_keycode/process_magic.c +    OPT_DEFS += -DMAGIC_KEYCODE_ENABLE +endif + +ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes) +    SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c +    OPT_DEFS += -DAUTO_SHIFT_ENABLE +    ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes) +        OPT_DEFS += -DAUTO_SHIFT_MODIFIERS +    endif +endif + +ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes) +    PS2_ENABLE := yes +    SRC += ps2_mouse.c +    OPT_DEFS += -DPS2_MOUSE_ENABLE +    OPT_DEFS += -DMOUSE_ENABLE +endif + +ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes) +    PS2_ENABLE := yes +    SRC += ps2_busywait.c +    SRC += ps2_io.c +    OPT_DEFS += -DPS2_USE_BUSYWAIT +endif + +ifeq ($(strip $(PS2_USE_INT)), yes) +    PS2_ENABLE := yes +    SRC += ps2_interrupt.c +    SRC += ps2_io.c +    OPT_DEFS += -DPS2_USE_INT +endif + +ifeq ($(strip $(PS2_USE_USART)), yes) +    PS2_ENABLE := yes +    SRC += ps2_usart.c +    SRC += ps2_io.c +    OPT_DEFS += -DPS2_USE_USART +endif + +ifeq ($(strip $(PS2_ENABLE)), yes) +    COMMON_VPATH += $(DRIVER_PATH)/ps2 +    COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/ps2 +    OPT_DEFS += -DPS2_ENABLE +endif + +JOYSTICK_ENABLE ?= no +VALID_JOYSTICK_TYPES := analog digital +JOYSTICK_DRIVER ?= analog +ifeq ($(strip $(JOYSTICK_ENABLE)), yes) +    ifeq ($(filter $(JOYSTICK_DRIVER),$(VALID_JOYSTICK_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid JOYSTICK_DRIVER,JOYSTICK_DRIVER="$(JOYSTICK_DRIVER)" is not a valid joystick driver) +    endif +    OPT_DEFS += -DJOYSTICK_ENABLE +    SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c +    SRC += $(QUANTUM_DIR)/joystick.c + +    ifeq ($(strip $(JOYSTICK_DRIVER)), analog) +        OPT_DEFS += -DANALOG_JOYSTICK_ENABLE +        SRC += analog.c +    endif +    ifeq ($(strip $(JOYSTICK_DRIVER)), digital) +        OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE +    endif +endif + +USBPD_ENABLE ?= no +VALID_USBPD_DRIVER_TYPES = custom vendor +USBPD_DRIVER ?= vendor +ifeq ($(strip $(USBPD_ENABLE)), yes) +    ifeq ($(filter $(strip $(USBPD_DRIVER)),$(VALID_USBPD_DRIVER_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid USBPD_DRIVER,USBPD_DRIVER="$(USBPD_DRIVER)" is not a valid USBPD driver) +    else +        OPT_DEFS += -DUSBPD_ENABLE +        ifeq ($(strip $(USBPD_DRIVER)), vendor) +            # Vendor-specific implementations +            OPT_DEFS += -DUSBPD_VENDOR +            ifeq ($(strip $(MCU_SERIES)), STM32G4xx) +                OPT_DEFS += -DUSBPD_STM32G4 +                SRC += usbpd_stm32g4.c +            else +                $(call CATASTROPHIC_ERROR,Invalid USBPD_DRIVER,There is no vendor-provided USBPD driver available) +            endif +        else ifeq ($(strip $(USBPD_DRIVER)), custom) +            OPT_DEFS += -DUSBPD_CUSTOM +            # Board designers can add their own driver to $(SRC) +        endif +    endif +endif + +BLUETOOTH_ENABLE ?= no +VALID_BLUETOOTH_DRIVER_TYPES := BluefruitLE RN42 custom +ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) +    ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),) +        $(call CATASTROPHIC_ERROR,Invalid BLUETOOTH_DRIVER,BLUETOOTH_DRIVER="$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type) +    endif +    OPT_DEFS += -DBLUETOOTH_ENABLE +    NO_USB_STARTUP_CHECK := yes +    COMMON_VPATH += $(DRIVER_PATH)/bluetooth +    SRC += outputselect.c + +    ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE) +        OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE +        SRC += analog.c +        SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp +        QUANTUM_LIB_SRC += spi_master.c +    endif + +    ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42) +        OPT_DEFS += -DBLUETOOTH_RN42 +        SRC += $(DRIVER_PATH)/bluetooth/rn42.c +        QUANTUM_LIB_SRC += uart.c +    endif +endif diff --git a/builddefs/common_rules.mk b/builddefs/common_rules.mk new file mode 100644 index 0000000000..b303a87919 --- /dev/null +++ b/builddefs/common_rules.mk @@ -0,0 +1,523 @@ +# Hey Emacs, this is a -*- makefile -*- +#---------------------------------------------------------------------------- +# WinAVR Makefile Template written by Eric B. Weddington, Jg Wunsch, et al. +# +# Released to the Public Domain +# +# Additional material for this makefile was written by: +# Peter Fleury +# Tim Henigan +# Colin O'Flynn +# Reiner Patommel +# Markus Pfaff +# Sander Pool +# Frederik Rouleau +# Carlos Lamas +# + +# Enable vpath seraching for source files only +# Without this, output files, could be read from the wrong .build directories +VPATH_SRC := $(VPATH) +vpath %.c $(VPATH_SRC) +vpath %.h $(VPATH_SRC) +vpath %.cpp $(VPATH_SRC) +vpath %.cc $(VPATH_SRC) +vpath %.hpp $(VPATH_SRC) +vpath %.S $(VPATH_SRC) +VPATH := + +# Convert all SRC to OBJ +define OBJ_FROM_SRC +$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$(patsubst %.clib,$1/%.a,$($1_SRC)))))) +endef +$(foreach OUTPUT,$(OUTPUTS),$(eval $(OUTPUT)_OBJ +=$(call OBJ_FROM_SRC,$(OUTPUT)))) + +# Define a list of all objects +OBJ := $(foreach OUTPUT,$(OUTPUTS),$($(OUTPUT)_OBJ)) +NO_LTO_OBJ := $(filter %.a,$(OBJ)) + +MASTER_OUTPUT := $(firstword $(OUTPUTS)) + + + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + +# Optimization level, can be [0, 1, 2, 3, s]. +#     0 = turn off optimization. s = optimize for size. +#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT ?= s + +# Compiler flag to set the C Standard level. +#     c89   = "ANSI" C +#     gnu89 = c89 plus GCC extensions +#     c99   = ISO C99 standard (not yet fully implemented) +#     gnu99 = c99 plus GCC extensions +CSTANDARD = -std=gnu99 + + +# Place -D or -U options here for C sources +#CDEFS += + + +# Place -D or -U options here for ASM sources +#ADEFS += + + +# Place -D or -U options here for C++ sources +#CXXDEFS += -D__STDC_LIMIT_MACROS +#CXXDEFS += -D__STDC_CONSTANT_MACROS +#CXXDEFS += + +# Speed up recompilations by opt-in usage of ccache +USE_CCACHE ?= no +ifneq ($(USE_CCACHE),no) +    CC_PREFIX ?= ccache +endif + +#---------------- Compiler Options C ---------------- +#  -g*:          generate debugging information +#  -O*:          optimization level +#  -f...:        tuning, see GCC manual and avr-libc documentation +#  -Wall...:     warning level +#  -Wa,...:      tell GCC to pass this to the assembler. +ifeq ($(strip $(LTO_ENABLE)), yes) +    ifeq ($(PLATFORM),CHIBIOS) +        $(info Enabling LTO on ChibiOS-targeting boards is known to have a high likelihood of failure.) +        $(info If unsure, set LTO_ENABLE = no.) +    endif +    CDEFS += -flto +    CDEFS += -DLTO_ENABLE +endif + +DEBUG_ENABLE ?= yes +ifeq ($(strip $(SKIP_DEBUG_INFO)),yes) +  DEBUG_ENABLE=no +endif + +ifeq ($(strip $(DEBUG_ENABLE)),yes) +  CFLAGS += -g$(DEBUG) +endif +CFLAGS += $(CDEFS) +CFLAGS += -O$(OPT) +# add color +ifeq ($(COLOR),true) +ifeq ("$(shell echo "int main(){}" | $(CC) -fdiagnostics-color -x c - -o /dev/null 2>&1)", "") +	CFLAGS+= -fdiagnostics-color +endif +endif +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +ifneq ($(strip $(ALLOW_WARNINGS)), yes) +    CFLAGS += -Werror +endif +#CFLAGS += -mshort-calls +#CFLAGS += -fno-unit-at-a-time +#CFLAGS += -Wundef +#CFLAGS += -Wunreachable-code +#CFLAGS += -Wsign-compare +CFLAGS += $(CSTANDARD) + +# This fixes lots of keyboards linking errors but SHOULDN'T BE A FINAL SOLUTION +# Fixing of multiple variable definitions must be made. +CFLAGS += -fcommon + +#---------------- Compiler Options C++ ---------------- +#  -g*:          generate debugging information +#  -O*:          optimization level +#  -f...:        tuning, see GCC manual and avr-libc documentation +#  -Wall...:     warning level +#  -Wa,...:      tell GCC to pass this to the assembler. +ifeq ($(strip $(DEBUG_ENABLE)),yes) +  CXXFLAGS += -g$(DEBUG) +endif +CXXFLAGS += $(CXXDEFS) +CXXFLAGS += -O$(OPT) +# to supress "warning: only initialized variables can be placed into program memory area" +CXXFLAGS += -w +CXXFLAGS += -Wall +CXXFLAGS += -Wundef + +ifneq ($(strip $(ALLOW_WARNINGS)), yes) +    CXXFLAGS += -Werror +endif +#CXXFLAGS += -mshort-calls +#CXXFLAGS += -fno-unit-at-a-time +#CXXFLAGS += -Wstrict-prototypes +#CXXFLAGS += -Wunreachable-code +#CXXFLAGS += -Wsign-compare +#CXXFLAGS += $(CSTANDARD) + +#---------------- Assembler Options ---------------- +ASFLAGS += $(ADEFS) +ifeq ($(VERBOSE_AS_CMD),yes) +	ASFLAGS += -v +endif + +#---------------- Library Options ---------------- +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +# If this is left blank, then it will use the Standard printf version. +PRINTF_LIB = +#PRINTF_LIB = $(PRINTF_LIB_MIN) +#PRINTF_LIB = $(PRINTF_LIB_FLOAT) + + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +# If this is left blank, then it will use the Standard scanf version. +SCANF_LIB = +#SCANF_LIB = $(SCANF_LIB_MIN) +#SCANF_LIB = $(SCANF_LIB_FLOAT) + + +MATH_LIB = -lm +CREATE_MAP ?= yes + + +#---------------- Linker Options ---------------- +#  -Wl,...:     tell GCC to pass this to linker. +#    -Map:      create map file +#    --cref:    add cross reference to  map file +# +# Comennt out "--relax" option to avoid a error such: +# 	(.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12' +# + +ifeq ($(CREATE_MAP),yes) +	LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref +endif +ifeq ($(VERBOSE_LD_CMD),yes) +	LDFLAGS += -v +endif +#LDFLAGS += -Wl,--relax +LDFLAGS += $(EXTMEMOPTS) +LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) +LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) +#LDFLAGS += -T linker_script.x +# You can give EXTRALDFLAGS at 'make' command line. +LDFLAGS += $(EXTRALDFLAGS) + +#---------------- Assembler Listings ---------------- +#  -Wa,...:   tell GCC to pass this to the assembler. +#  -adhlns:   create listing +#  -gstabs:   have the assembler create line number information; note that +#             for use in COFF files, additional information about filenames +#             and function names needs to be present in the assembler source +#             files -- see avr-libc docs [FIXME: not yet described there] +#  -listing-cont-lines: Sets the maximum number of continuation lines of hex +#       dump that will be displayed for a given single line of source input. + +ADHLNS_ENABLE ?= no +ifeq ($(ADHLNS_ENABLE),yes) +  # Avoid "Options to '-Xassembler' do not match" - only specify assembler options at LTO link time +  ifeq ($(strip $(LTO_ENABLE)), yes) +    LDFLAGS += -Wa,-adhlns=$(BUILD_DIR)/$(TARGET).lst +  else +    CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) +    CXXFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) +    ifeq ($(strip $(DEBUG_ENABLE)),yes) +      ASFLAGS = -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100 +    else +      ASFLAGS = -Wa,-adhlns=$(@:%.o=%.lst),--listing-cont-lines=100 +    endif +  endif +endif + +# Define programs and commands. +SHELL = sh +SED = sed +REMOVE = rm -f +REMOVEDIR = rmdir +COPY = cp +WINSHELL = cmd +SECHO = $(SILENT) || echo +MD5SUM ?= md5sum +ifneq ($(filter Darwin FreeBSD,$(shell uname -s)),) +  MD5SUM = md5 +endif + +# UF2 format settings +# To produce a UF2 file in your build, add to your keyboard's rules.mk: +#      FIRMWARE_FORMAT = uf2 +UF2CONV = $(TOP_DIR)/util/uf2conv.py +UF2_FAMILY ?= 0x0 + +# Compiler flags to generate dependency files. +#GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d +GENDEPFLAGS = -MMD -MP -MF $(patsubst %.o,%.td,$@) + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +# You can give extra flags at 'make' command line like: make EXTRAFLAGS=-DFOO=bar +ALL_CFLAGS = $(MCUFLAGS) $(CFLAGS) $(EXTRAFLAGS) +ALL_CXXFLAGS = $(MCUFLAGS) -x c++ $(CXXFLAGS) $(EXTRAFLAGS) +ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS) + +define NO_LTO +$(patsubst %.a,%.o,$1): NOLTO_CFLAGS += -fno-lto +endef +$(foreach LOBJ, $(NO_LTO_OBJ), $(eval $(call NO_LTO,$(LOBJ)))) + +MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@) + +# For a ChibiOS build, ensure that the board files have the hook overrides injected +define BOARDSRC_INJECT_HOOKS +$(KEYBOARD_OUTPUT)/$(patsubst %.c,%.o,$(patsubst ./%,%,$1)): INIT_HOOK_CFLAGS += -include $(TOP_DIR)/tmk_core/protocol/chibios/init_hooks.h +endef +$(foreach LOBJ, $(BOARDSRC), $(eval $(call BOARDSRC_INJECT_HOOKS,$(LOBJ)))) + +# Add QMK specific flags +DFU_SUFFIX ?= dfu-suffix +DFU_SUFFIX_ARGS ?= + + +elf: $(BUILD_DIR)/$(TARGET).elf +hex: $(BUILD_DIR)/$(TARGET).hex +uf2: $(BUILD_DIR)/$(TARGET).uf2 +cpfirmware: $(FIRMWARE_FORMAT) +	$(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD) +	$(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK) +eep: $(BUILD_DIR)/$(TARGET).eep +lss: $(BUILD_DIR)/$(TARGET).lss +sym: $(BUILD_DIR)/$(TARGET).sym +LIBNAME=lib$(TARGET).a +lib: $(LIBNAME) + +# Display size of file, modifying the output so people don't mistakenly grab the hex output +BINARY_SIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(SED) -e 's/\.build\/.*$$/$(TARGET).$(FIRMWARE_FORMAT)/g' + +sizebefore: +	@if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO) $(MSG_SIZE_BEFORE); $(SILENT) || $(BINARY_SIZE); \ +	2>/dev/null; $(SECHO); fi + +sizeafter: $(BUILD_DIR)/$(TARGET).hex +	@if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO); $(SECHO) $(MSG_SIZE_AFTER); $(SILENT) || $(BINARY_SIZE); \ +	2>/dev/null; $(SECHO); fi + +# Display compiler version information. +gccversion : +	@$(SILENT) || $(CC) --version + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf +	$(eval CMD=$(HEX) $< $@) +	#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" +	@$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD) +	@$(BUILD_CMD) + +%.uf2: %.hex +	$(eval CMD=$(UF2CONV) $(BUILD_DIR)/$(TARGET).hex -o $(BUILD_DIR)/$(TARGET).uf2 -c -f $(UF2_FAMILY) >/dev/null 2>&1) +	#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" +	@$(SILENT) || printf "$(MSG_UF2) $@" | $(AWK_CMD) +	@$(BUILD_CMD) + +%.eep: %.elf +	$(eval CMD=$(EEP) $< $@ || exit 0) +	#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" +	@$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD) +	@$(BUILD_CMD) + +# Create extended listing file from ELF output file. +%.lss: %.elf +	$(eval CMD=$(OBJDUMP) -h -S -z $< > $@) +	#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" +	@$(SILENT) || printf "$(MSG_EXTENDED_LISTING) $@" | $(AWK_CMD) +	@$(BUILD_CMD) + +# Create a symbol table from ELF output file. +%.sym: %.elf +	$(eval CMD=$(NM) -n $< > $@ ) +	#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" +	@$(SILENT) || printf "$(MSG_SYMBOL_TABLE) $@" | $(AWK_CMD) +	@$(BUILD_CMD) + +%.bin: %.elf +	$(eval CMD=$(BIN) $< $@ || exit 0) +	#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" +	@$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD) +	@$(BUILD_CMD) +	if [ ! -z "$(DFU_SUFFIX_ARGS)" ]; then \ +		$(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null ;\ +	fi +	#$(SILENT) || printf "$(MSG_EXECUTING) '$(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null':\n" ;\ +	$(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin; + +BEGIN = gccversion sizebefore + +# Link: create ELF output file from object files. +.SECONDARY : $(BUILD_DIR)/$(TARGET).elf +.PRECIOUS : $(OBJ) +# Note the obj.txt depeendency is there to force linking if a source file is deleted +%.elf: $(OBJ) $(MASTER_OUTPUT)/cflags.txt $(MASTER_OUTPUT)/ldflags.txt $(MASTER_OUTPUT)/obj.txt | $(BEGIN) +	@$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD) +	$(eval CMD=MAKE=$(MAKE) $(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS)) +	@$(BUILD_CMD) + + +define GEN_OBJRULE +$1_INCFLAGS := $$(patsubst %,-I%,$$($1_INC)) +ifdef $1_CONFIG +$1_CONFIG_FLAGS += $$(patsubst %,-include %,$$($1_CONFIG)) +endif +$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS) +$1_CXXFLAGS = $$(ALL_CXXFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS) +$1_ASFLAGS = $$(ALL_ASFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) + +# Compile: create object files from C source files. +$1/%.o : %.c $1/%.d $1/cflags.txt $1/compiler.txt | $(BEGIN) +	@mkdir -p $$(@D) +	@$$(SILENT) || printf "$$(MSG_COMPILING) $$<" | $$(AWK_CMD) +	$$(eval CC_EXEC := $$(CC)) +    ifneq ($$(VERBOSE_C_CMD),) +	$$(if $$(filter $$(notdir $$(VERBOSE_C_CMD)),$$(notdir $$<)),$$(eval CC_EXEC += -v)) +    endif +    ifneq ($$(VERBOSE_C_INCLUDE),) +	$$(if $$(filter $$(notdir $$(VERBOSE_C_INCLUDE)),$$(notdir $$<)),$$(eval CC_EXEC += -H)) +    endif +	$$(eval CMD := $$(CC_EXEC) -c $$($1_CFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP)) +	@$$(BUILD_CMD) +    ifneq ($$(DUMP_C_MACROS),) +	$$(eval CMD := $$(CC) -E -dM $$($1_CFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$<) +	@$$(if $$(filter $$(notdir $$(DUMP_C_MACROS)),$$(notdir $$<)),$$(BUILD_CMD)) +    endif + +# Compile: create object files from C++ source files. +$1/%.o : %.cpp $1/%.d $1/cxxflags.txt $1/compiler.txt | $(BEGIN) +	@mkdir -p $$(@D) +	@$$(SILENT) || printf "$$(MSG_COMPILING_CXX) $$<" | $$(AWK_CMD) +	$$(eval CMD=$$(CC) -c $$($1_CXXFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP)) +	@$$(BUILD_CMD) + +$1/%.o : %.cc $1/%.d $1/cxxflags.txt $1/compiler.txt | $(BEGIN) +	@mkdir -p $$(@D) +	@$$(SILENT) || printf "$$(MSG_COMPILING_CXX) $$<" | $$(AWK_CMD) +	$$(eval CMD=$$(CC) -c $$($1_CXXFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP)) +	@$$(BUILD_CMD) + +# Assemble: create object files from assembler source files. +$1/%.o : %.S $1/asflags.txt $1/compiler.txt | $(BEGIN) +	@mkdir -p $$(@D) +	@$(SILENT) || printf "$$(MSG_ASSEMBLING) $$<" | $$(AWK_CMD) +	$$(eval CMD=$$(CC) -c $$($1_ASFLAGS) $$< -o $$@) +	@$$(BUILD_CMD) + +$1/%.a : $1/%.o +	@mkdir -p $$(@D) +	@$(SILENT) || printf "Archiving: $$<" | $$(AWK_CMD) +	$$(eval CMD=$$(AR) rcs $$@ $$<) +	@$$(BUILD_CMD) + +$1/force: + +$1/cflags.txt: $1/force +	echo '$$($1_CFLAGS)' | cmp -s - $$@ || echo '$$($1_CFLAGS)' > $$@ + +$1/cxxflags.txt: $1/force +	echo '$$($1_CXXFLAGS)' | cmp -s - $$@ || echo '$$($1_CXXFLAGS)' > $$@ + +$1/asflags.txt: $1/force +	echo '$$($1_ASFLAGS)' | cmp -s - $$@ || echo '$$($1_ASFLAGS)' > $$@ + +$1/compiler.txt: $1/force +	$$(CC) --version | cmp -s - $$@ || $$(CC) --version > $$@ +endef + +.PRECIOUS: $(MASTER_OUTPUT)/obj.txt +$(MASTER_OUTPUT)/obj.txt: $(MASTER_OUTPUT)/force +	echo '$(OBJ)' | cmp -s - $@ || echo '$(OBJ)' > $@ + +.PRECIOUS: $(MASTER_OUTPUT)/ldflags.txt +$(MASTER_OUTPUT)/ldflags.txt: $(MASTER_OUTPUT)/force +	echo '$(LDFLAGS)' | cmp -s - $@ || echo '$(LDFLAGS)' > $@ + + +# We have to use static rules for the .d files for some reason +DEPS = $(patsubst %.o,%.d,$(patsubst %.a,%.o,$(OBJ))) +# Keep the .d files +.PRECIOUS: $(DEPS) +# Empty rule to force recompilation if the .d file is missing +$(DEPS): + + +$(foreach OUTPUT,$(OUTPUTS),$(eval $(call GEN_OBJRULE,$(OUTPUT)))) + +# Create preprocessed source for use in sending a bug report. +%.i : %.c | $(BEGIN) +	$(CC) -E -mmcu=$(MCU) $(CFLAGS) $< -o $@ + +# Target: clean project. +clean: +	$(foreach OUTPUT,$(OUTPUTS), $(REMOVE) -r $(OUTPUT) 2>/dev/null) +	$(REMOVE) $(BUILD_DIR)/$(TARGET).* + +show_path: +	@echo VPATH=$(VPATH) +	@echo SRC=$(SRC) +	@echo OBJ=$(OBJ) + +dump_vars: ERROR_IF_EMPTY="" +dump_vars: ERROR_IF_NONBOOL="" +dump_vars: ERROR_IF_UNSET="" +dump_vars: +	@$(foreach V,$(sort $(.VARIABLES)),$(if $(filter-out environment% default automatic,$(origin $V)),$(info $V=$($V)))) + +objs-size: +	for i in $(OBJ); do echo $$i; done | sort | xargs $(SIZE) + +ifeq ($(findstring avr-gcc,$(CC)),avr-gcc) +SIZE_MARGIN = 1024 + +check-size: +	$(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) platforms/avr/bootloader_size.c 2> /dev/null | $(SED) -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) +	$(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi)) +	$(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE))) +	$(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE))) +	$(eval PERCENT_SIZE=$(shell expr $(CURRENT_SIZE) \* 100 / $(MAX_SIZE))) +	if [ $(MAX_SIZE) -gt 0 ] && [ $(CURRENT_SIZE) -gt 0 ]; then \ +		$(SILENT) || printf "$(MSG_CHECK_FILESIZE)" | $(AWK_CMD); \ +		if [ $(CURRENT_SIZE) -gt $(MAX_SIZE) ]; then \ +		    printf "\n * $(MSG_FILE_TOO_BIG)"; $(PRINT_ERROR_PLAIN); \ +		else \ +		    if [ $(FREE_SIZE) -lt $(SIZE_MARGIN) ]; then \ +			$(PRINT_WARNING_PLAIN); printf " * $(MSG_FILE_NEAR_LIMIT)"; \ +		    else \ +			$(PRINT_OK); $(SILENT) || printf " * $(MSG_FILE_JUST_RIGHT)"; \ +		    fi ; \ +		fi ; \ +	fi +else +check-size: +	$(SILENT) || echo "$(MSG_CHECK_FILESIZE_SKIPPED)" +endif + +check-md5: +	$(MD5SUM) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) + +# Create build directory +$(shell mkdir -p $(BUILD_DIR) 2>/dev/null) + +# Create object files directory +$(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null))) + +# Include the dependency files. +-include $(patsubst %.o,%.d,$(patsubst %.a,%.o,$(OBJ))) + + +# Listing of phony targets. +.PHONY : all dump_vars finish sizebefore sizeafter qmkversion \ +gccversion build elf hex uf2 eep lss sym coff extcoff \ +clean clean_list debug gdb-config show_path \ +program teensy dfu dfu-ee dfu-start \ +flash dfu-split-left dfu-split-right \ +avrdude-split-left avrdude-split-right \ +avrdude-loop usbasp diff --git a/builddefs/mcu_selection.mk b/builddefs/mcu_selection.mk index 46d34aabe4..9fdd22c3b6 100644 --- a/builddefs/mcu_selection.mk +++ b/builddefs/mcu_selection.mk @@ -143,6 +143,9 @@ ifneq ($(findstring STM32F042, $(MCU)),)    # This ensures that the EEPROM page buffer fits into RAM    USE_PROCESS_STACKSIZE = 0x600    USE_EXCEPTIONS_STACKSIZE = 0x300 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFFC400  endif  ifneq ($(findstring STM32F072, $(MCU)),) @@ -175,6 +178,9 @@ ifneq ($(findstring STM32F072, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32F0 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFFC800  endif  ifneq ($(findstring STM32F103, $(MCU)),) @@ -239,6 +245,9 @@ ifneq ($(findstring STM32F303, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32F3 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFFD800  endif  ifneq ($(findstring STM32F401, $(MCU)),) @@ -276,6 +285,9 @@ ifneq ($(findstring STM32F401, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32F4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring STM32F405, $(MCU)),) @@ -308,6 +320,9 @@ ifneq ($(findstring STM32F405, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32F4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring STM32F407, $(MCU)),) @@ -340,6 +355,9 @@ ifneq ($(findstring STM32F407, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32F4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring STM32F411, $(MCU)),) @@ -377,6 +395,9 @@ ifneq ($(findstring STM32F411, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32F4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring STM32F446, $(MCU)),) @@ -406,6 +427,9 @@ ifneq ($(findstring STM32F446, $(MCU)),)    BOARD ?= GENERIC_STM32_F446XE    USE_FPU ?= yes + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring STM32G431, $(MCU)),) @@ -438,6 +462,9 @@ ifneq ($(findstring STM32G431, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32G4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring STM32G474, $(MCU)),) @@ -470,6 +497,46 @@ ifneq ($(findstring STM32G474, $(MCU)),)    # UF2 settings    UF2_FAMILY ?= STM32G4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000 +endif + +ifneq (,$(filter $(MCU),STM32L432 STM32L442)) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = STM32 +  MCU_SERIES = STM32L4xx + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= STM32L432xC + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= stm32l4xx + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= GENERIC_STM32_L432XC + +  PLATFORM_NAME ?= platform_l432 + +  USE_FPU ?= yes + +  # UF2 settings +  UF2_FAMILY ?= STM32L4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq (,$(filter $(MCU),STM32L433 STM32L443)) @@ -504,6 +571,9 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443))    # UF2 settings    UF2_FAMILY ?= STM32L4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq (,$(filter $(MCU),STM32L412 STM32L422)) @@ -538,6 +608,9 @@ ifneq (,$(filter $(MCU),STM32L412 STM32L422))    # UF2 settings    UF2_FAMILY ?= STM32L4 + +  # Bootloader address for STM32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000  endif  ifneq ($(findstring WB32F3G71, $(MCU)),) @@ -567,6 +640,10 @@ ifneq ($(findstring WB32F3G71, $(MCU)),)    BOARD ?= GENERIC_WB32_F3G71XX    USE_FPU ?= no + +  # Bootloader address for WB32 DFU +  STM32_BOOTLOADER_ADDRESS ?= 0x1FFFE000 +  WB32_BOOTLOADER_ADDRESS ?= 0x1FFFE000  endif  ifneq ($(findstring GD32VF103, $(MCU)),) diff --git a/builddefs/message.mk b/builddefs/message.mk index cb4ef43719..d441f560be 100644 --- a/builddefs/message.mk +++ b/builddefs/message.mk @@ -87,6 +87,7 @@ define GENERATE_MSG_AVAILABLE_KEYMAPS  endef  MSG_AVAILABLE_KEYMAPS = $(eval $(call GENERATE_MSG_AVAILABLE_KEYMAPS))$(MSG_AVAILABLE_KEYMAPS_ACTUAL) +MSG_BOOTLOADER_NOT_FOUND_BASE = Bootloader not found. Make sure the board is in bootloader mode. See https://docs.qmk.fm/\#/newbs_flashing\n  MSG_CHECK_FILESIZE = Checking file size of $(TARGET).$(FIRMWARE_FORMAT)  MSG_CHECK_FILESIZE_SKIPPED = (Firmware size check does not yet support $(MCU_ORIG); skipping)  MSG_FILE_TOO_BIG = $(ERROR_COLOR)The firmware is too large!$(NO_COLOR) $(CURRENT_SIZE)/$(MAX_SIZE) ($(OVER_SIZE) bytes over)\n @@ -97,6 +98,11 @@ MSG_PYTHON_MISSING = $(ERROR_COLOR)ERROR:$(NO_COLOR) Cannot run \"qmk hello\"!\n  	Please run $(BOLD)qmk setup$(NO_COLOR) to install all the dependencies QMK requires.\n\n  MSG_FLASH_BOOTLOADER = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's bootloader is not specified or is not supported by the \":flash\" target at this time.\n\n  MSG_FLASH_ARCH = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's architecture is not supported by the \":flash\" target at this time.\n\n -MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) Bootloader not found. Trying again in 5s (Ctrl+C to cancel)\n +MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) $(MSG_BOOTLOADER_NOT_FOUND_BASE) Trying again in 5s (Ctrl+C to cancel)\n  BOOTLOADER_RETRY_TIME ?= 0.5 -MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY = Bootloader not found. Trying again every $(BOOTLOADER_RETRY_TIME)s (Ctrl+C to cancel) +MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY = $(MSG_BOOTLOADER_NOT_FOUND_BASE) Trying again every $(BOOTLOADER_RETRY_TIME)s (Ctrl+C to cancel) + +define CATASTROPHIC_ERROR +    $(shell printf "\n * %-99s $(ERROR_STRING)\n" "$2" >&2) +    $(error $1) +endef
\ No newline at end of file diff --git a/builddefs/testlist.mk b/builddefs/testlist.mk new file mode 100644 index 0000000000..86da5668ac --- /dev/null +++ b/builddefs/testlist.mk @@ -0,0 +1,19 @@ +TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f -name test.mk))) +FULL_TESTS := $(notdir $(TEST_LIST)) + +include $(QUANTUM_PATH)/debounce/tests/testlist.mk +include $(QUANTUM_PATH)/sequencer/tests/testlist.mk +include $(PLATFORM_PATH)/test/testlist.mk + +define VALIDATE_TEST_LIST +    ifneq ($1,) +        ifeq ($$(findstring -,$1),-) +            $$(call CATASTROPHIC_ERROR,Invalid test name,Test names can't contain '-', but '$1' does.) +        else +            $$(eval $$(call VALIDATE_TEST_LIST,$$(firstword $2),$$(wordlist 2,9999,$2))) +        endif +    endif +endef + + +$(eval $(call VALIDATE_TEST_LIST,$(firstword $(TEST_LIST)),$(wordlist 2,9999,$(TEST_LIST))))  | 
