From c89c681a9f065e66ce817a024fda24abeed9519f Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Fri, 24 Jan 2014 01:05:30 -0800 Subject: [PATCH] Rework makefiles. Add proper dependency checking. --- py/mkenv.mk | 52 +++++++++++++++++++++++++++ py/mkrules.mk | 92 +++++++++++++++++++++++++++++++++++++++++++++++ py/py.mk | 92 +++++++++++------------------------------------ py/qstr.c | 2 +- py/qstr.h | 2 +- stm/Makefile | 55 +++++++--------------------- teensy/Makefile | 49 ++++++------------------- unix-cpy/Makefile | 25 ++----------- unix/Makefile | 27 ++------------ 9 files changed, 195 insertions(+), 201 deletions(-) create mode 100644 py/mkenv.mk create mode 100644 py/mkrules.mk diff --git a/py/mkenv.mk b/py/mkenv.mk new file mode 100644 index 000000000..ed4e22096 --- /dev/null +++ b/py/mkenv.mk @@ -0,0 +1,52 @@ +ifneq ($(lastword a b),b) +$(error These Makefiles require make 3.81 or newer) +endif + +# Set TOP to be the path to get from the current directory (where make was +# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns +# the name of this makefile relative to where make was invoked. +# +# We assume that this file is in the py directory so we use $(dir ) twice +# to get to the top of the tree. + +THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) +TOP := $(patsubst %/py/mkenv.mk,%,$(THIS_MAKEFILE)) + +# Turn on increased build verbosity by defining BUILD_VERBOSE in your main +# Makefile or in your environment. You can also use V=1 on the make command +# line. + +ifeq ("$(origin V)", "command line") +BUILD_VERBOSE=$(V) +endif +ifndef BUILD_VERBOSE +BUILD_VERBOSE = 0 +endif +ifeq ($(BUILD_VERBOSE),0) +Q = @ +else +Q = +endif +# Since this is a new feature, advertise it +ifeq ($(BUILD_VERBOSE),0) +$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) +endif + +# default settings; can be overriden in main Makefile + +PY_SRC ?= $(TOP)/py +BUILD ?= build + +RM = rm +ECHO = @echo + +AS = $(CROSS_COMPILE)as +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy +SIZE = $(CROSS_COMPILE)size + +all: +.PHONY: all + +MKENV_INCLUDED = 1 diff --git a/py/mkrules.mk b/py/mkrules.mk new file mode 100644 index 000000000..4c1ea0833 --- /dev/null +++ b/py/mkrules.mk @@ -0,0 +1,92 @@ +ifneq ($(MKENV_INCLUDED),1) +# We assume that mkenv is in the same directory as this file. +THIS_MAKEFILE = $(lastword $(MAKEFILE_LIST)) +include $(dir $(THIS_MAKEFILE))mkenv.mk +endif + +# This file expects that OBJ contains a list of all of the object files. +# The directory portion of each object file is used to locate the source +# and should not contain any ..'s but rather be relative to the top of the +# tree. +# +# So for example, py/map.c would have an object file name py/map.o +# The object files will go into the build directory and mantain the same +# directory structure as the source tree. So the final dependency will look +# like this: +# +# build/py/map.o: py/map.c +# +# We set vpath to point to the top of the tree so that the source files +# can be located. By following this scheme, it allows a single build rule +# to be used to compile all .c files. + +vpath %.S . $(TOP) +$(BUILD)/%.o: %.S + $(ECHO) "CC $<" + $(Q)$(CC) $(CFLAGS) -c -o $@ $< + +vpath %.s . $(TOP) +$(BUILD)/%.o: %.s + $(ECHO) "AS $<" + $(Q)$(AS) -o $@ $< + +define compile_c +$(ECHO) "CC $<" +$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< +@# The following fixes the dependency file. +@# See http://make.paulandlesley.org/autodep.html for details. +@cp $(@:.o=.d) $(@:.o=.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ + rm -f $(@:.o=.d) +endef + +vpath %.c . $(TOP) +$(BUILD)/%.o: %.c + $(call compile_c) + +# The following rule uses | to create an order only prereuisite. Order only +# prerequisites only get built if they don't exist. They don't cause timestamp +# checkng to be performed. +# +# $(sort $(var)) removes duplicates +# +# The net effect of this, is it causes the objects to depend on the +# object directories (but only for existance), and the object directories +# will be created if they don't exist. +OBJ_DIRS = $(sort $(dir $(OBJ))) +$(OBJ): | $(OBJ_DIRS) +$(OBJ_DIRS): + mkdir -p $@ + +ifneq ($(PROG),) +# Build a standalone executable (unix and unix-cpy do this) + +all: $(PROG) + +$(PROG): $(OBJ) + $(ECHO) "LINK $<" + $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) +ifndef DEBUG + $(Q)strip $(PROG) +endif + $(Q)size $(PROG) + +clean: clean-prog +clean-prog: + $(RM) -f $(PROG) + +.PHONY: clean-prog +endif + +clean: + $(RM) -rf $(BUILD) +.PHONY: clean + +print-cfg: + $(ECHO) "PY_SRC = $(PY_SRC)" + $(ECHO) "BUILD = $(BUILD)" + $(ECHO) "OBJ = $(OBJ)" +.PHONY: print-cfg + +-include $(OBJ:.o=.P) diff --git a/py/py.mk b/py/py.mk index 75394b361..d4946e283 100644 --- a/py/py.mk +++ b/py/py.mk @@ -1,48 +1,11 @@ -########## -# The following should eventually go into a more central location -# when a reorg is done. -# -# Turn on increased build verbosity by defining BUILD_VERBOSE in your main -# Makefile or in your environment. You can also use V=1 on the make command -# line. -ifeq ("$(origin V)", "command line") -BUILD_VERBOSE=$(V) -endif -ifndef BUILD_VERBOSE -BUILD_VERBOSE = 0 -endif -ifeq ($(BUILD_VERBOSE),0) -Q = @ -else -Q = -endif -# Since this is a new feature, advertise it -ifeq ($(BUILD_VERBOSE),0) -$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) -endif -# -######### - -# default settings; can be overriden in main Makefile - -PY_SRC ?= ../py -BUILD ?= build - -# to create the build directory - -$(BUILD): - $(Q)mkdir -p $@ - # where py object files go (they have a name prefix to prevent filename clashes) - -PY_BUILD = $(BUILD)/py. +PY_BUILD = $(BUILD)/py # file containing qstr defs for the core Python bit PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h # py object files - PY_O_BASENAME = \ nlrx86.o \ nlrx64.o \ @@ -108,50 +71,37 @@ PY_O_BASENAME = \ repl.o \ # prepend the build destination prefix to the py object files - -PY_O = $(addprefix $(PY_BUILD), $(PY_O_BASENAME)) +PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) # qstr data -$(PY_BUILD)qstr.o: $(PY_BUILD)qstrdefs.generated.h - -$(PY_BUILD)qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py +# Adding an order only dependency on $(PY_BUILD) causes $(PY_BUILD) to get +# created before we run the script to generate the .h +$(PY_BUILD)/qstrdefs.generated.h: | $(PY_BUILD) +$(PY_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py $(ECHO) "makeqstrdata $(PY_QSTR_DEFS) $(QSTR_DEFS)" $(Q)python $(PY_SRC)/makeqstrdata.py $(PY_QSTR_DEFS) $(QSTR_DEFS) > $@ +# We don't know which source files actually need the generated.h (since +# it is #included from str.h). The compiler generated dependencies will cause +# the right .o's to get recompiled if the generated.h file changes. Adding +# an order-only dependendency to all of the .o's will cause the generated .h +# to get built before we try to compile any of them. +$(PY_O): | $(PY_BUILD)/qstrdefs.generated.h + # emitters -$(PY_BUILD)emitnx64.o: $(PY_SRC)/emitnative.c $(PY_SRC)/emit.h mpconfigport.h - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -DN_X64 -c -o $@ $< +$(PY_BUILD)/emitnx64.o: CFLAGS += -DN_X64 +$(PY_BUILD)/emitnx64.o: py/emitnative.c + $(call compile_c) -$(PY_BUILD)emitnthumb.o: $(PY_SRC)/emitnative.c $(PY_SRC)/emit.h mpconfigport.h - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -DN_THUMB -c -o $@ $< - -# general source files - -$(PY_BUILD)%.o: $(PY_SRC)/%.S - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(PY_BUILD)%.o: $(PY_SRC)/%.c mpconfigport.h $(PY_SRC)/qstr.h $(PY_QSTR_DEFS) $(QSTR_DEFS) - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(PY_BUILD)/emitnthumb.o: CFLAGS += -DN_THUMB +$(PY_BUILD)/emitnthumb.o: py/emitnative.c + $(call compile_c) # optimising gc for speed; 5ms down to 4ms on pybv2 -$(PY_BUILD)gc.o: $(PY_SRC)/gc.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -O3 -c -o $@ $< +$(PY_BUILD)gc.o: CFLAGS += -O3 # optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster) -$(PY_BUILD)vm.o: $(PY_SRC)/vm.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -O3 -c -o $@ $< +$(PY_BUILD)vm.o: CFLAGS += -O3 -# header dependencies - -$(PY_BUILD)parse.o: $(PY_SRC)/grammar.h -$(PY_BUILD)compile.o: $(PY_SRC)/grammar.h -$(PY_BUILD)emitcpy.o: $(PY_SRC)/emit.h -$(PY_BUILD)emitbc.o: $(PY_SRC)/emit.h diff --git a/py/qstr.c b/py/qstr.c index 268b3bafc..f12cbceff 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -55,7 +55,7 @@ const static qstr_pool_t const_pool = { (const byte*) "\0\0\0\0", // empty qstr #define Q(id, str) str, // TODO having 'build/' here is a bit of a hack, should take config variable from Makefile -#include "build/py.qstrdefs.generated.h" +#include "build/py/qstrdefs.generated.h" #undef Q }, }; diff --git a/py/qstr.h b/py/qstr.h index 271e2117c..9224d48a1 100644 --- a/py/qstr.h +++ b/py/qstr.h @@ -9,7 +9,7 @@ enum { MP_QSTR_ = 1, // the empty qstr #define Q(id, str) MP_QSTR_##id, // TODO having 'build/py.' here is a bit of a hack, should take config variable from Makefile -#include "build/py.qstrdefs.generated.h" +#include "build/py/qstrdefs.generated.h" #undef Q MP_QSTR_number_of, } category_t; diff --git a/stm/Makefile b/stm/Makefile index ab6910958..60a97594f 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -1,5 +1,4 @@ -# define main target -all: all2 +include ../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h @@ -7,10 +6,6 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - CMSIS=cmsis STMSRC=lib #STMOTGSRC=usbhost @@ -18,11 +13,7 @@ FATFSSRC=fatfs CC3KSRC=cc3k DFU=../tools/dfu.py -AS = arm-none-eabi-as -CC = arm-none-eabi-gcc -LD = arm-none-eabi-ld -OBJCOPY = arm-none-eabi-objcopy -SIZE = arm-none-eabi-size +CROSS_COMPILE = arm-none-eabi- CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS = -I. -I$(PY_SRC) -I$(FATFSSRC) -I$(CMSIS) -I$(STMSRC) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) @@ -71,11 +62,12 @@ SRC_S = \ startup_stm32f40xx.s \ gchelper.s \ -SRC_FATFS = \ +SRC_FATFS = $(addprefix $(FATFSSRC)/,\ ff.c \ diskio.c \ + ) -SRC_STM = \ +SRC_STM = $(addprefix $(STMSRC)/,\ stm32f4xx_rcc.c \ stm32f4xx_syscfg.c \ stm_misc.c \ @@ -111,8 +103,9 @@ SRC_STM = \ usbd_msc_data.c \ usbd_msc_scsi.c \ usbd_storage_msd.c \ + ) -#SRC_STM_OTG = \ +#SRC_STM_OTG = $(addprefix $(STMSRC)/,\ usb_hcd.c \ usb_hcd_int.c \ usbh_core.c \ @@ -124,8 +117,9 @@ SRC_STM = \ usbh_hid_mouse.c \ usbh_hid_keybd.c \ # usb_otg.c \ + ) -SRC_CC3K = \ +SRC_CC3K = $(addprefix $(CC3KSRC)/,\ cc3000_common.c \ evnt_handler.c \ hci.c \ @@ -136,11 +130,12 @@ SRC_CC3K = \ wlan.c \ ccspi.c \ pybcc3k.c \ + ) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(SRC_FATFS:.c=.o) $(SRC_STM:.c=.o)) # $(SRC_CC3K:.c=.o)) #OBJ += $(addprefix $(BUILD)/, $(SRC_STM_OTG:.c=.o)) -all2: $(BUILD) $(BUILD)/flash.dfu +all: $(BUILD) $(BUILD)/flash.dfu $(BUILD)/flash.dfu: $(BUILD)/flash0.bin $(BUILD)/flash1.bin $(ECHO) "Create $@" @@ -157,31 +152,5 @@ $(BUILD)/flash.elf: $(OBJ) $(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ -$(BUILD)/%.o: %.s - $(ECHO) "AS $<" - $(Q)$(AS) -o $@ $< +include ../py/mkrules.mk -$(BUILD)/%.o: %.c $(QSTR_DEFS) - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: $(FATFSSRC)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: $(STMSRC)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -#$(BUILD)/%.o: $(STMOTGSRC)/%.c -# $(ECHO) "CC $<" -# $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: $(CC3KSRC)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -clean: - $(RM) -rf $(BUILD) - -.PHONY: all all2 clean diff --git a/teensy/Makefile b/teensy/Makefile index e25f81481..0cd7272e7 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -1,30 +1,20 @@ -# define main target -all: all2 +include ../py/mkenv.mk # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - ifeq ($(ARDUINO),) $(error Please define ARDUINO (where TeensyDuino is installed)) endif TOOLS_PATH = $(ARDUINO)/hardware/tools COMPILER_PATH = $(TOOLS_PATH)/arm-none-eabi/bin CORE_PATH = $(ARDUINO)/hardware/teensy/cores/teensy3 -TARGET=TEENSY -AS = $(COMPILER_PATH)/arm-none-eabi-as -CC = $(COMPILER_PATH)/arm-none-eabi-gcc -LD = $(COMPILER_PATH)/arm-none-eabi-ld -OBJCOPY = $(COMPILER_PATH)/arm-none-eabi-objcopy -SIZE = $(COMPILER_PATH)/arm-none-eabi-size +CROSS_COMPILE = $(COMPILER_PATH)/arm-none-eabi- CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -fsingle-precision-constant -Wdouble-promotion $(CFLAGS_TEENSY) -CFLAGS = -I. -I$(PY_SRC) -I$(CORE_PATH) -Wall -ansi -std=gnu99 +CFLAGS = -I. -I$(PY_SRC) -I$(CORE_PATH) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) LDFLAGS = -nostdlib -T mk20dx256.ld LIBS = -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc @@ -35,9 +25,6 @@ else CFLAGS += -Os #-DNDEBUG endif -# if order is not important for these, move them up -CFLAGS += $(CFLAGS_CORTEX_M4) -D$(TARGET) - SRC_C = \ main.c \ lcd.c \ @@ -47,13 +34,15 @@ SRC_C = \ memzip.c \ usb.c \ -STM_SRC_C = \ +STM_SRC_C = $(addprefix stm/,\ malloc0.c \ printf.c \ string0.c \ + ) -STM_SRC_S = \ +STM_SRC_S = $(addprefix stm/,\ gchelper.s \ + ) SRC_TEENSY = \ mk20dx128.c \ @@ -70,7 +59,7 @@ OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o # the following is needed for BSD #LIB += -ltermcap -all2: $(BUILD) hex +all: hex hex: $(BUILD)/micropython-mz.hex post_compile: $(BUILD)/micropython-mz.hex @@ -100,25 +89,7 @@ $(BUILD)/%.hex: $(BUILD)/%.elf $(ECHO) "HEX $<" $(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@" -$(BUILD)/%.o: %.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: ../stm/%.s - $(ECHO) "AS $<" - $(Q)$(AS) -o $@ $< - -$(BUILD)/%.o: ../stm/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - $(BUILD)/%.o: $(CORE_PATH)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< + $(call compile_c) -$(BUILD)/main.o: mpconfigport.h - -clean: - $(RM) -rf $(BUILD) - -.PHONY: all all2 clean +include ../py/mkrules.mk diff --git a/unix-cpy/Makefile b/unix-cpy/Makefile index f8ab73c35..84fc581e3 100644 --- a/unix-cpy/Makefile +++ b/unix-cpy/Makefile @@ -1,16 +1,12 @@ +include ../py/mkenv.mk + # define main target PROG = cpy -all: $(PROG) # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - # compiler settings -CC = gcc CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -DUNIX LDFLAGS = -lm @@ -28,20 +24,5 @@ SRC_C = \ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) LIB = -$(PROG): $(BUILD) $(OBJ) - $(ECHO) "LINK $<" - $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) - $(Q)strip $(PROG) - $(Q)size $(PROG) +include ../py/mkrules.mk -$(BUILD)/%.o: %.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/main.o: mpconfigport.h - -clean: - $(RM) -f $(PROG) - $(RM) -rf $(BUILD) - -.PHONY: all clean diff --git a/unix/Makefile b/unix/Makefile index 7a4ce3e16..3db6ae9df 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -1,6 +1,7 @@ +include ../py/mkenv.mk + # define main target PROG = micropython -all: $(PROG) # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h @@ -8,12 +9,7 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - # compiler settings -CC = gcc CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -DUNIX LDFLAGS = -lm @@ -35,22 +31,5 @@ LIB = -lreadline # the following is needed for BSD #LIB += -ltermcap -$(PROG): $(BUILD) $(OBJ) - $(ECHO) "LINK $<" - $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) -ifndef DEBUG - $(Q)strip $(PROG) -endif - $(Q)size $(PROG) +include ../py/mkrules.mk -$(BUILD)/%.o: %.c $(QSTR_DEFS) - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/main.o: mpconfigport.h - -clean: - $(RM) -f $(PROG) - $(RM) -rf $(BUILD) - -.PHONY: all clean