]> git.donarmstrong.com Git - qmk_firmware.git/blobdiff - tmk_core/rules.mk
Force compilation and linking when options changes
[qmk_firmware.git] / tmk_core / rules.mk
index 2bf2a109fb4747e9639218fb1d73cbdea5146f21..ebcd372cacf7816ae384ae77f764e54d8d4016d5 100644 (file)
 # 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 %.hpp $(VPATH_SRC)
+vpath %.S $(VPATH_SRC)
+VPATH :=
+
 
 # Output format. (can be srec, ihex, binary)
 FORMAT = ihex
@@ -71,7 +81,7 @@ BUILD_CMD = LOG=$$($(CMD) 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR); elif [
 #     Each directory must be seperated by a space.
 #     Use forward slashes for directory separators.
 #     For a directory that has spaces, enclose it in quotes.
-EXTRAINCDIRS += $(subst :, ,$(VPATH))
+EXTRAINCDIRS += $(subst :, ,$(VPATH_SRC))
 
 
 # Compiler flag to set the C Standard level.
@@ -253,6 +263,14 @@ MSG_SUBMODULE_DIRTY = $(WARN_COLOR)WARNING:$(NO_COLOR)\n \
 
 # Define all object files.
 OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC))))
+# The files in the lib folder are shared between all keymaps, so generate that folder name by removing
+# the keymap from the name
+KBOBJDIR=$(subst _$(KEYMAP),,$(OBJDIR))
+# And fixup the object files to match
+LIBOBJ = $(foreach v,$(OBJ),$(if $(findstring /lib/,$v),$v))
+NONLIBOBJ := $(filter-out $(LIBOBJ),$(OBJ))
+LIBOBJ := $(subst _$(KEYMAP)/,/,$(LIBOBJ))
+OBJ := $(LIBOBJ) $(NONLIBOBJ)
 
 # Define all listing files.
 LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst %.S,$(OBJDIR)/%.lst,$(SRC))))
@@ -260,16 +278,18 @@ LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst
 
 # Compiler flags to generate dependency files.
 #GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
-GENDEPFLAGS = -MMD -MP -MF $(BUILD_DIR)/.dep/$(subst /,_,$(subst $(BUILD_DIR)/,,$@)).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) $(GENDEPFLAGS) $(EXTRAFLAGS)
-ALL_CPPFLAGS = $(MCUFLAGS) -x c++ $(CPPFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
+ALL_CFLAGS = $(MCUFLAGS) $(CFLAGS) $(EXTRAFLAGS)
+ALL_CPPFLAGS = $(MCUFLAGS) -x c++ $(CPPFLAGS) $(EXTRAFLAGS)
 ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
 
+MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
+
 # Default target.
 all: build sizeafter
 
@@ -365,25 +385,65 @@ BEGIN = gccversion check_submodule sizebefore
 # Link: create ELF output file from object files.
 .SECONDARY : $(BUILD_DIR)/$(TARGET).elf
 .PRECIOUS : $(OBJ)
-%.elf: $(OBJ) | $(BEGIN)
+# Note the obj.txt depeendency is there to force linking if a source file is deleted
+%.elf: $(OBJ) $(OBJDIR)/cflags.txt $(OBJDIR)/ldflags.txt $(OBJDIR)/obj.txt | $(BEGIN)
        @$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD)
-       $(eval CMD=$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS))
+       $(eval CMD=$(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS))
        @$(BUILD_CMD)
 
+define GEN_OBJRULE
 # Compile: create object files from C source files.
-$(OBJDIR)/%.o : %.c | $(BEGIN)
-       @mkdir -p $(@D)
-       @$(SILENT) || printf "$(MSG_COMPILING) $<" | $(AWK_CMD)
-       $(eval CMD=$(CC) -c $(ALL_CFLAGS) $< -o $@)
-       @$(BUILD_CMD)
+$1/%.o : %.c $1/%.d $1/cflags.txt | $(BEGIN)
+       @mkdir -p $$(@D)
+       @$$(SILENT) || printf "$$(MSG_COMPILING) $$<" | $$(AWK_CMD)
+       $$(eval CMD=$$(CC) -c $$(ALL_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
+       @$$(BUILD_CMD)
 
 # Compile: create object files from C++ source files.
-$(OBJDIR)/%.o : %.cpp | $(BEGIN)
-       @mkdir -p $(@D)
-       @$(SILENT) || printf "$(MSG_COMPILING_CPP) $<" | $(AWK_CMD)
-       $(eval CMD=$(CC) -c $(ALL_CPPFLAGS) $< -o $@)
+$1/%.o : %.cpp $1/%.d $1/cppflags.txt | $(BEGIN)
+       @mkdir -p $$(@D)
+       @$$(SILENT) || printf "$$(MSG_COMPILING_CPP) $$<" | $$(AWK_CMD)
+       $$(eval CMD=$$(CC) -c $$(ALL_CPPFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
        @$(BUILD_CMD)
 
+# Assemble: create object files from assembler source files.
+$1/%.o : %.S $1/asflags.txt | $(BEGIN)
+       @mkdir -p $$(@D)
+       @$(SILENT) || printf "$$(MSG_ASSEMBLING) $$<" | $$(AWK_CMD)
+       $$(eval CMD=$$(CC) -c $$(ALL_ASFLAGS) $$< -o $$@)
+       @$$(BUILD_CMD)
+
+$1/force:
+
+$1/cflags.txt: $1/force
+       echo '$$(ALL_CFLAGS)' | cmp -s - $$@ || echo '$$(ALL_CFLAGS)' > $$@
+
+$1/cppflags.txt: $1/force
+       echo '$$(ALL_CPPFLAGS)' | cmp -s - $$@ || echo '$$(ALL_CPPFLAGS)' > $$@
+
+$1/asflags.txt: $1/force
+       echo '$$(ALL_ASFLAGS)' | cmp -s - $$@ || echo '$$(ALL_ASFLAGS)' > $$@
+
+$1/ldflags.txt: $1/force
+       echo '$$(LDFLAGS)' | cmp -s - $$@ || echo '$$(LDFLAGS)' > $$@
+
+$1/obj.txt: $1/force
+       echo '$$(OBJ)' | cmp -s - $$@ || echo '$$(OBJ)' > $$@
+
+endef
+
+# We have to use static rules for the .d files for some reason
+DEPS = $(patsubst %.o,%.d,$(OBJ))
+# Keep the .d files
+.PRECIOUS: $(DEPS)
+# Empty rule to force recompilation if the .d file is missing
+$(DEPS):
+
+# Since the object files could be in two different folders, generate
+# separate rules for them, rather than having too generic rules
+$(eval $(call GEN_OBJRULE,$(OBJDIR)))
+$(eval $(call GEN_OBJRULE,$(KBOBJDIR)))
+
 # Compile: create assembler files from C source files.
 %.s : %.c | $(BEGIN)
        @$(SILENT) || printf "$(MSG_ASSEMBLING) $<" | $(AWK_CMD)
@@ -396,19 +456,12 @@ $(OBJDIR)/%.o : %.cpp | $(BEGIN)
        $(eval CMD=$(CC) -S $(ALL_CPPFLAGS) $< -o $@)
        @$(BUILD_CMD)
 
-# Assemble: create object files from assembler source files.
-$(OBJDIR)/%.o : %.S | $(BEGIN)
-       @mkdir -p $(@D)
-       @$(SILENT) || printf "$(MSG_ASSEMBLING) $<" | $(AWK_CMD)
-       $(eval CMD=$(CC) -c $(ALL_ASFLAGS) $< -o $@)
-       @$(BUILD_CMD)
-
 # Create preprocessed source for use in sending a bug report.
 %.i : %.c | $(BEGIN)
        $(CC) -E -mmcu=$(MCU) $(CFLAGS) $< -o $@
 
 # Target: clean project.
-clean: 
+clean:
 
 show_path:
        @echo VPATH=$(VPATH)
@@ -486,10 +539,10 @@ $(shell mkdir $(BUILD_DIR) 2>/dev/null)
 
 # Create object files directory
 $(shell mkdir $(OBJDIR) 2>/dev/null)
-
+$(shell mkdir $(KBOBJDIR) 2>/dev/null)
 
 # Include the dependency files.
--include $(shell mkdir $(BUILD_DIR)/.dep 2>/dev/null) $(wildcard $(BUILD_DIR)/.dep/*)
+-include $(patsubst %.o,%.d,$(OBJ))
 
 
 # Listing of phony targets.