From eaa673169e2485b4003e3961ccb63f05642d23eb Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Tue, 12 Mar 2013 03:12:24 -0700 Subject: [PATCH] [make] add feature to allow multiple parallel build dirs Using environment variables LKROOT and LKINC you can specify multiple parallel top level directories (outside of the lk root) that are overlayed on top of the build system. This allows for a structure like lk/ testproject/ someotherfirmware/ Where each of these subdirs has an entire overlayed tree of libraries, platforms, targets, and projects. To accomplish this, copy makefile into the root dir and build a lk_inc.mk that sets LKROOT and LKINC. --- engine.mk | 226 +++++++++++++++++++++++++++++++++++++++++++++++++ make/build.mk | 2 +- make/macros.mk | 2 +- makefile | 208 +++------------------------------------------ 4 files changed, 239 insertions(+), 199 deletions(-) create mode 100644 engine.mk diff --git a/engine.mk b/engine.mk new file mode 100644 index 00000000..77151668 --- /dev/null +++ b/engine.mk @@ -0,0 +1,226 @@ +LOCAL_MAKEFILE:=$(MAKEFILE_LIST) + +ifeq ($(MAKECMDGOALS),spotless) +spotless: + rm -rf build-* +else + +ifndef LKROOT +$(error please define LKROOT to the root of the lk build system) +endif + +-include local.mk +include make/macros.mk + +# If one of our goals (from the commandline) happens to have a +# matching project/goal.mk, then we should re-invoke make with +# that project name specified... + +project-name := $(firstword $(MAKECMDGOALS)) + +ifneq ($(project-name),) +ifneq ($(strip $(foreach d,$(LKINC),$(wildcard $(d)/project/$(project-name).mk))),) +do-nothing := 1 +$(MAKECMDGOALS) _all: make-make +make-make: + @PROJECT=$(project-name) $(MAKE) -rR -f $(LOCAL_MAKEFILE) $(filter-out $(project-name), $(MAKECMDGOALS)) + +.PHONY: make-make +endif +endif + +ifeq ($(do-nothing),) + +ifeq ($(PROJECT),) +$(error No project specified. Use "make projectname" or put "PROJECT := projectname" in local.mk) +endif + +DEBUG ?= 2 + +BUILDROOT ?= . +BUILDDIR := $(BUILDROOT)/build-$(PROJECT) +OUTBIN := $(BUILDDIR)/lk.bin +OUTELF := $(BUILDDIR)/lk.elf +CONFIGHEADER := $(BUILDDIR)/config.h + +INCLUDES := -I$(BUILDDIR) -I$(LKROOT)/include $(addsuffix /include,$(addprefix -I,$(LKINC))) +GLOBAL_OPTFLAGS ?= -Os +GLOBAL_COMPILEFLAGS := -g -fno-builtin -finline -W -Wall -Wno-multichar -Wno-unused-parameter -Wno-unused-function -include $(CONFIGHEADER) +GLOBAL_CFLAGS := --std=gnu99 -Werror-implicit-function-declaration +#GLOBAL_CFLAGS += -Werror +GLOBAL_CPPFLAGS := -fno-exceptions -fno-rtti -fno-threadsafe-statics +#GLOBAL_CPPFLAGS += -Weffc++ +GLOBAL_ASMFLAGS := -DASSEMBLY +GLOBAL_LDFLAGS := + +GLOBAL_COMPILEFLAGS += -ffunction-sections -fdata-sections +GLOBAL_LDFLAGS += --gc-sections + +# top level rule +all:: $(OUTBIN) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).size $(OUTELF).hex + +# master module object list +ALLOBJS_MODULE := + +# master object list (for dep generation) +ALLOBJS := + +# a linker script needs to be declared in one of the project/target/platform files +LINKER_SCRIPT := + +# anything you add here will be deleted in make clean +GENERATED := $(CONFIGHEADER) + +# anything added to DEFINES will be put into $(BUILDDIR)/config.h +DEFINES := LK=1 + +# Anything added to SRCDEPS will become a dependency of every source file in the system. +# Useful for header files that may be included by one or more source files. +SRCDEPS := $(CONFIGHEADER) + +# these need to be filled out by the project/target/platform rules.mk files +TARGET := +PLATFORM := +ARCH := +ALLMODULES := + +# add any external module dependencies +MODULES := $(EXTERNAL_MODULES) + +# any rules you put here will also be built by the system before considered being complete +EXTRA_BUILDDEPS := + +# any rules you put here will be depended on in clean builds +EXTRA_CLEANDEPS := + +# any objects you put here get linked with the final image +EXTRA_OBJS := + +# if someone defines this, the build id will be pulled into lib/version +BUILDID ?= + +# try to include the project file +-include project/$(PROJECT).mk +ifndef TARGET +$(error couldn't find project or project doesn't define target) +endif +include target/$(TARGET)/rules.mk +ifndef PLATFORM +$(error couldn't find target or target doesn't define platform) +endif +include platform/$(PLATFORM)/rules.mk + +$(info PROJECT = $(PROJECT)) +$(info PLATFORM = $(PLATFORM)) +$(info TARGET = $(TARGET)) + +include arch/$(ARCH)/rules.mk +include platform/rules.mk +include target/rules.mk +include kernel/rules.mk +include dev/rules.mk +include app/rules.mk + +# recursively include any modules in the MODULE variable, leaving a trail of included +# modules in the ALLMODULES list +include make/recurse.mk + +# any extra top level build dependencies that someone declared +all:: $(EXTRA_BUILDDEPS) + +# add some automatic configuration defines +DEFINES += \ + PROJECT_$(PROJECT)=1 \ + PROJECT=\"$(PROJECT)\" \ + TARGET_$(TARGET)=1 \ + TARGET=\"$(TARGET)\" \ + PLATFORM_$(PLATFORM)=1 \ + PLATFORM=\"$(PLATFORM)\" \ + ARCH_$(ARCH)=1 \ + ARCH=\"$(ARCH)\" \ + $(addsuffix =1,$(addprefix WITH_,$(ALLMODULES))) + +# debug build? +ifneq ($(DEBUG),) +DEFINES += \ + DEBUG=$(DEBUG) +endif + +# allow additional defines from outside the build system +ifneq ($(EXTERNAL_DEFINES),) +DEFINES += $(EXTERNAL_DEFINES) +$(info EXTERNAL_DEFINES = $(EXTERNAL_DEFINES)) +endif + +DEPS := $(ALLOBJS:%o=%d) + +#$(warning DEPS=$(DEPS)) + +# default to no ccache +CCACHE ?= +CC := $(CCACHE) $(TOOLCHAIN_PREFIX)gcc +LD := $(TOOLCHAIN_PREFIX)ld +OBJDUMP := $(TOOLCHAIN_PREFIX)objdump +OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy +CPPFILT := $(TOOLCHAIN_PREFIX)c++filt +SIZE := $(TOOLCHAIN_PREFIX)size +NM := $(TOOLCHAIN_PREFIX)nm + +# put all of the global build flags in config.h to force a rebuild if any change +DEFINES += INCLUDES=\"$(subst $(SPACE),_,$(INCLUDES))\" +DEFINES += GLOBAL_COMPILEFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_COMPILEFLAGS))\" +DEFINES += GLOBAL_OPTFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_OPTFLAGS))\" +DEFINES += GLOBAL_CFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CFLAGS))\" +DEFINES += GLOBAL_CPPFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CPPFLAGS))\" +DEFINES += GLOBAL_ASMFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_ASMFLAGS))\" +DEFINES += GLOBAL_LDFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_LDFLAGS))\" + +# comment out or override if you want to see the full output of each command +NOECHO ?= @ + +#$(warning ALLMODULE_OBJS=$(ALLMODULE_OBJS)) + +ifneq ($(OBJS),) +$(warning OBJS=$(OBJS)) +$(error OBJS is not empty, please convert to new module format) +endif +ifneq ($(OPTFLAGS),) +$(warning OPTFLAGS=$(OPTFLAGS)) +$(error OPTFLAGS is not empty, please use GLOBAL_OPTFLAGS or MODULE_OPTFLAGS) +endif +ifneq ($(CFLAGS),) +$(warning CFLAGS=$(CFLAGS)) +$(error CFLAGS is not empty, please use GLOBAL_CFLAGS or MODULE_CFLAGS) +endif +ifneq ($(CPPFLAGS),) +$(warning CPPFLAGS=$(CPPFLAGS)) +$(error CPPFLAGS is not empty, please use GLOBAL_CPPFLAGS or MODULE_CPPFLAGS) +endif + +# the logic to compile and link stuff is in here +include make/build.mk + +clean: $(EXTRA_CLEANDEPS) + rm -f $(ALLOBJS) $(DEPS) $(GENERATED) $(OUTBIN) $(OUTELF) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).size $(OUTELF).hex + +install: all + scp $(OUTBIN) 192.168.0.4:/tftproot + +# generate a config.h file with all of the DEFINES laid out in #define format +configheader: + +$(CONFIGHEADER): configheader + $(call MAKECONFIGHEADER,$@,DEFINES) + +# Empty rule for the .d files. The above rules will build .d files as a side +# effect. Only works on gcc 3.x and above, however. +%.d: + +ifeq ($(filter $(MAKECMDGOALS), clean), ) +-include $(DEPS) +endif + +.PHONY: configheader +endif + +endif # make spotless diff --git a/make/build.mk b/make/build.mk index 8cbae36c..fd4440f3 100644 --- a/make/build.mk +++ b/make/build.mk @@ -12,7 +12,7 @@ $(OUTELF).hex: $(OUTELF) $(OUTELF): $(ALLMODULE_OBJS) $(EXTRA_OBJS) $(LINKER_SCRIPT) @echo linking $@ - $(NOECHO)$(SIZE) -t $(ALLMODULE_OBJS) + $(NOECHO)$(SIZE) -t --common $(sort $(ALLMODULE_OBJS)) $(NOECHO)$(LD) $(GLOBAL_LDFLAGS) -T $(LINKER_SCRIPT) $(ALLMODULE_OBJS) $(EXTRA_OBJS) $(LIBGCC) -o $@ $(OUTELF).sym: $(OUTELF) diff --git a/make/macros.mk b/make/macros.mk index e23715ea..a6bcc035 100644 --- a/make/macros.mk +++ b/make/macros.mk @@ -20,7 +20,7 @@ define MAKECONFIGHEADER echo \#ifndef __$${LDEF}_H > $1.tmp; \ echo \#define __$${LDEF}_H >> $1.tmp; \ for d in `echo $($2) | tr '[:lower:]' '[:upper:]'`; do \ - echo "#define $$d" | sed "s/=/\ /g;s/-/_/g;s/\//_/g" >> $1.tmp; \ + echo "#define $$d" | sed "s/=/\ /g;s/-/_/g;s/\//_/g;s/\./_/g;s/\//_/g" >> $1.tmp; \ done; \ echo \#endif >> $1.tmp; \ if [ -f "$1" ]; then \ diff --git a/makefile b/makefile index 2ff51ef4..bc38c848 100644 --- a/makefile +++ b/makefile @@ -1,201 +1,15 @@ -ifeq ($(MAKECMDGOALS),spotless) -spotless: - rm -rf build-* -else +# the above include may override LKROOT and LKINC to allow external +# directories to be included in the build +-include lk_inc.mk --include local.mk -include make/macros.mk +LKROOT ?= . +LKINC ?= -# If one of our goals (from the commandline) happens to have a -# matching project/goal.mk, then we should re-invoke make with -# that project name specified... +LKINC := $(LKROOT) $(LKINC) -project-name := $(firstword $(MAKECMDGOALS)) +# vaneer makefile that calls into the engine with lk as the build root +# if we're the top level invocation, call ourselves with additional args +$(MAKECMDGOALS) _top: + LKROOT=$(LKROOT) LKINC="$(LKINC)" $(MAKE) -rR -f $(LKROOT)/engine.mk $(addprefix -I,$(LKINC)) $(MAKECMDGOALS) -ifneq ($(project-name),) -ifneq ($(wildcard project/$(project-name).mk),) -do-nothing := 1 -$(MAKECMDGOALS) _all: make-make -make-make: - @PROJECT=$(project-name) $(MAKE) $(filter-out $(project-name), $(MAKECMDGOALS)) -endif -endif - -ifeq ($(do-nothing),) - -ifeq ($(PROJECT),) -$(error No project specified. Use "make projectname" or put "PROJECT := projectname" in local.mk) -endif - -DEBUG ?= 2 - -BUILDDIR := build-$(PROJECT) -OUTBIN := $(BUILDDIR)/lk.bin -OUTELF := $(BUILDDIR)/lk -CONFIGHEADER := $(BUILDDIR)/config.h - -INCLUDES := -I$(BUILDDIR) -Iinclude -GLOBAL_OPTFLAGS ?= -Os -GLOBAL_COMPILEFLAGS := -g -fno-builtin -finline -W -Wall -Wno-multichar -Wno-unused-parameter -Wno-unused-function -include $(CONFIGHEADER) -GLOBAL_CFLAGS := --std=c99 -Werror-implicit-function-declaration -#GLOBAL_CFLAGS += -Werror -GLOBAL_CPPFLAGS := -fno-exceptions -fno-rtti -fno-threadsafe-statics -#GLOBAL_CPPFLAGS += -Weffc++ -GLOBAL_ASMFLAGS := -DASSEMBLY -GLOBAL_LDFLAGS := - -GLOBAL_COMPILEFLAGS += -ffunction-sections -fdata-sections -GLOBAL_LDFLAGS += -gc-sections - -# top level rule -all:: $(OUTBIN) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).size $(OUTELF).hex - -# master module object list -ALLOBJS_MODULE := - -# master object list (for dep generation) -ALLOBJS := - -# a linker script needs to be declared in one of the project/target/platform files -LINKER_SCRIPT := - -# anything you add here will be deleted in make clean -GENERATED := $(CONFIGHEADER) - -# anything added to DEFINES will be put into $(BUILDDIR)/config.h -DEFINES := LK=1 - -# Anything added to SRCDEPS will become a dependency of every source file in the system. -# Useful for header files that may be included by one or more source files. -SRCDEPS := $(CONFIGHEADER) - -# these need to be filled out by the project/target/platform rules.mk files -TARGET := -PLATFORM := -ARCH := -ALLMODULES := -MODULES := - -# any rules you put here will also be built by the system before considered being complete -EXTRA_BUILDDEPS := - -# any rules you put here will be depended on in clean builds -EXTRA_CLEANDEPS := - -# any objects you put here get linked with the final image -EXTRA_OBJS := - -include project/$(PROJECT).mk -include target/$(TARGET)/rules.mk -include platform/$(PLATFORM)/rules.mk - -$(info PROJECT = $(PROJECT)) -$(info PLATFORM = $(PLATFORM)) -$(info TARGET = $(TARGET)) - -include arch/$(ARCH)/rules.mk -include platform/rules.mk -include target/rules.mk -include kernel/rules.mk -include dev/rules.mk -include app/rules.mk - -# recursively include any modules in the MODULE variable, leaving a trail of included -# modules in the ALLMODULES list -include make/recurse.mk - -# any extra top level build dependencies that someone declared -all:: $(EXTRA_BUILDDEPS) - -# add some automatic configuration defines -DEFINES += \ - PROJECT_$(PROJECT)=1 \ - TARGET_$(TARGET)=1 \ - PLATFORM_$(PLATFORM)=1 \ - ARCH_$(ARCH)=1 \ - $(addsuffix =1,$(addprefix WITH_,$(ALLMODULES))) - -# debug build? -ifneq ($(DEBUG),) -DEFINES += \ - DEBUG=$(DEBUG) -endif - -# allow additional defines from outside the build system -ifneq ($(EXTERNAL_DEFINES),) -DEFINES += $(EXTERNAL_DEFINES) -$(info EXTERNAL_DEFINES = $(EXTERNAL_DEFINES)) -endif - -DEPS := $(ALLOBJS:%o=%d) - -#$(warning DEPS=$(DEPS)) - -# default to no ccache -CCACHE ?= -CC := $(CCACHE) $(TOOLCHAIN_PREFIX)gcc -LD := $(TOOLCHAIN_PREFIX)ld -OBJDUMP := $(TOOLCHAIN_PREFIX)objdump -OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy -CPPFILT := $(TOOLCHAIN_PREFIX)c++filt -SIZE := $(TOOLCHAIN_PREFIX)size -NM := $(TOOLCHAIN_PREFIX)nm - -# put all of the global build flags in config.h to force a rebuild if any change -DEFINES += INCLUDES=\"$(subst $(SPACE),_,$(INCLUDES))\" -DEFINES += GLOBAL_COMPILEFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_COMPILEFLAGS))\" -DEFINES += GLOBAL_OPTFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_OPTFLAGS))\" -DEFINES += GLOBAL_CFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CFLAGS))\" -DEFINES += GLOBAL_CPPFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CPPFLAGS))\" -DEFINES += GLOBAL_ASMFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_ASMFLAGS))\" -DEFINES += GLOBAL_LDFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_LDFLAGS))\" - -# comment out or override if you want to see the full output of each command -NOECHO ?= @ - -#$(warning ALLMODULE_OBJS=$(ALLMODULE_OBJS)) - -ifneq ($(OBJS),) -$(warning OBJS=$(OBJS)) -$(error OBJS is not empty, please convert to new module format) -endif -ifneq ($(OPTFLAGS),) -$(warning OPTFLAGS=$(OPTFLAGS)) -$(error OPTFLAGS is not empty, please use GLOBAL_OPTFLAGS or MODULE_OPTFLAGS) -endif -ifneq ($(CFLAGS),) -$(warning CFLAGS=$(CFLAGS)) -$(error CFLAGS is not empty, please use GLOBAL_CFLAGS or MODULE_CFLAGS) -endif -ifneq ($(CPPFLAGS),) -$(warning CPPFLAGS=$(CPPFLAGS)) -$(error CPPFLAGS is not empty, please use GLOBAL_CPPFLAGS or MODULE_CPPFLAGS) -endif - -# the logic to compile and link stuff is in here -include make/build.mk - -clean: $(EXTRA_CLEANDEPS) - rm -f $(ALLOBJS) $(DEPS) $(GENERATED) $(OUTBIN) $(OUTELF) $(OUTELF).lst $(OUTELF).hex - -install: all - scp $(OUTBIN) 192.168.0.4:/tftproot - -# generate a config.h file with all of the DEFINES laid out in #define format -configheader: - -$(CONFIGHEADER): configheader - $(call MAKECONFIGHEADER,$@,DEFINES) - -# Empty rule for the .d files. The above rules will build .d files as a side -# effect. Only works on gcc 3.x and above, however. -%.d: - -ifeq ($(filter $(MAKECMDGOALS), clean), ) --include $(DEPS) -endif - -.PHONY: configheader -endif - -endif # make spotless +.PHONY: _top