[make] better modularize the build system

-Each module's rules.mk defines a seperate linkage unit. Each
module can have a private set of CFLAGS, DEFINES, INCLUDES, and so
forth.
-Files to be compiled are now added by source, not object.

Most rules.mk files can be converted easily by following these steps:

1) add 'MODULE := $(LOCAL_DIR)' near the top of the file
2) change OBJS += to MODULE_SRCS += and list source files instead of .os
3) add 'include make/module.mk' at the bottom of the file

See make/module.mk for directions.
This commit is contained in:
Travis Geiselbrecht
2012-08-29 14:51:23 -07:00
parent 9c0f307ce6
commit 734f32b143
8 changed files with 259 additions and 98 deletions

View File

@@ -1,35 +0,0 @@
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(THUMBCFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(THUMBCFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
ifneq ($(THUMB_ONLY),true)
# to override thumb setting, mark the .o file as .Ao
$(BUILDDIR)/%.Ao: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.Ao: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# assembly is always compiled in ARM mode at the moment
$(BUILDDIR)/%.Ao: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
endif

View File

@@ -1,16 +0,0 @@
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@

View File

@@ -1,16 +1,19 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULES += \
MODULE := $(LOCAL_DIR)
MODULE_DEPS := \
lib/libc \
lib/debug \
lib/heap
OBJS += \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/dpc.o \
$(LOCAL_DIR)/event.o \
$(LOCAL_DIR)/main.o \
$(LOCAL_DIR)/mutex.o \
$(LOCAL_DIR)/thread.o \
$(LOCAL_DIR)/timer.o
MODULE_OBJS := \
debug.o \
dpc.o \
event.o \
main.o \
mutex.o \
thread.o \
timer.o
include make/module.mk

View File

@@ -6,9 +6,10 @@ $(OUTBIN): $(OUTELF)
$(NOECHO)$(SIZE) $<
$(NOCOPY)$(OBJCOPY) -O binary $< $@
$(OUTELF): $(ALLOBJS) $(LINKER_SCRIPT)
$(OUTELF): $(ALLMODULE_OBJS) $(LINKER_SCRIPT)
@echo linking $@
$(NOECHO)$(LD) $(LDFLAGS) -T $(LINKER_SCRIPT) $(ALLOBJS) $(LIBGCC) -o $@
$(NOECHO)$(SIZE) -t $(ALLMODULE_OBJS)
$(NOECHO)$(LD) $(GLOBAL_LDFLAGS) -T $(LINKER_SCRIPT) $(ALLMODULE_OBJS) $(LIBGCC) -o $@
$(OUTELF).sym: $(OUTELF)
@echo generating symbols: $@
@@ -26,5 +27,5 @@ $(OUTELF).size: $(OUTELF)
@echo generating size map: $@
$(NOECHO)$(NM) -S --size-sort $< > $@
include arch/$(ARCH)/compile.mk
#include arch/$(ARCH)/compile.mk

83
make/compile.mk Normal file
View File

@@ -0,0 +1,83 @@
# create a separate list of objects per source type
MODULE_CSRCS := $(filter %.c,$(MODULE_SRCS))
MODULE_CPPSRCS := $(filter %.cpp,$(MODULE_SRCS))
MODULE_ASMSRCS := $(filter %.S,$(MODULE_SRCS))
MODULE_COBJS := $(call TOBUILDDIR,$(patsubst %.c,%.o,$(MODULE_CSRCS)))
MODULE_CPPOBJS := $(call TOBUILDDIR,$(patsubst %.cpp,%.o,$(MODULE_CPPSRCS)))
MODULE_ASMOBJS := $(call TOBUILDDIR,$(patsubst %.S,%.o,$(MODULE_ASMSRCS)))
# do the same thing for files specified in arm override mode
MODULE_ARM_CSRCS := $(filter %.c,$(MODULE_ARM_OVERRIDE_SRCS))
MODULE_ARM_CPPSRCS := $(filter %.cpp,$(MODULE_ARM_OVERRIDE_SRCS))
MODULE_ARM_ASMSRCS := $(filter %.S,$(MODULE_ARM_OVERRIDE_SRCS))
MODULE_ARM_COBJS := $(call TOBUILDDIR,$(patsubst %.c,%.o,$(MODULE_ARM_CSRCS)))
MODULE_ARM_CPPOBJS := $(call TOBUILDDIR,$(patsubst %.cpp,%.o,$(MODULE_ARM_CPPSRCS)))
MODULE_ARM_ASMOBJS := $(call TOBUILDDIR,$(patsubst %.S,%.o,$(MODULE_ARM_ASMSRCS)))
MODULE_OBJS := $(MODULE_COBJS) $(MODULE_CPPOBJS) $(MODULE_ASMOBJS) $(MODULE_ARM_COBJS) $(MODULE_ARM_CPPOBJS) $(MODULE_ARM_ASMOBJS)
#$(info MODULE_SRCS = $(MODULE_SRCS))
#$(info MODULE_CSRCS = $(MODULE_CSRCS))
#$(info MODULE_CPPSRCS = $(MODULE_CPPSRCS))
#$(info MODULE_ASMSRCS = $(MODULE_ASMSRCS))
#$(info MODULE_OBJS = $(MODULE_OBJS))
#$(info MODULE_COBJS = $(MODULE_COBJS))
#$(info MODULE_CPPOBJS = $(MODULE_CPPOBJS))
#$(info MODULE_ASMOBJS = $(MODULE_ASMOBJS))
$(MODULE_OBJS): MODULE_OPTFLAGS:=$(MODULE_OPTFLAGS)
$(MODULE_OBJS): MODULE_COMPILEFLAGS:=$(MODULE_COMPILEFLAGS)
$(MODULE_OBJS): MODULE_CFLAGS:=$(MODULE_CFLAGS)
$(MODULE_OBJS): MODULE_CPPFLAGS:=$(MODULE_CPPFLAGS)
$(MODULE_OBJS): MODULE_ASMFLAGS:=$(MODULE_ASMFLAGS)
$(MODULE_OBJS): MODULE_SRCDEPS:=$(MODULE_SRCDEPS)
$(MODULE_OBJS): SRCDEPS:=$(SRCDEPS)
$(MODULE_OBJS): $(MODULE_SRCDEPS) $(SRCDEPS)
$(MODULE_COBJS): $(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(GLOBAL_OPTFLAGS) $(MODULE_OPTFLAGS) $(GLOBAL_COMPILEFLAGS) $(MODULE_COMPILEFLAGS) $(GLOBAL_CFLAGS) $(MODULE_CFLAGS) $(THUMBCFLAGS) $(INCLUDES) $(MODULE_INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(MODULE_CPPOBJS): $(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(GLOBAL_OPTFLAGS) $(MODULE_OPTFLAGS) $(GLOBAL_COMPILEFLAGS) $(MODULE_COMPILEFLAGS) $(GLOBAL_CPPFLAGS) $(MODULE_CPPFLAGS) $(THUMBCFLAGS) $(INCLUDES) $(MODULE_INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(MODULE_ASMOBJS): $(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(GLOBAL_OPTFLAGS) $(MODULE_OPTFLAGS) $(GLOBAL_COMPILEFLAGS) $(MODULE_COMPILEFLAGS) $(GLOBAL_ASMFLAGS) $(MODULE_ASMFLAGS) $(THUMBCFLAGS) $(INCLUDES) $(MODULE_INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# overridden arm versions
$(MODULE_ARM_COBJS): $(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(GLOBAL_OPTFLAGS) $(MODULE_OPTFLAGS) $(GLOBAL_COMPILEFLAGS) $(MODULE_COMPILEFLAGS) $(GLOBAL_CFLAGS) $(MODULE_CFLAGS) $(INCLUDES) $(MODULE_INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(MODULE_ARM_CPPOBJS): $(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(GLOBAL_OPTFLAGS) $(MODULE_OPTFLAGS) $(GLOBAL_COMPILEFLAGS) $(MODULE_COMPILEFLAGS) $(GLOBAL_CPPFLAGS) $(MODULE_CPPFLAGS) $(INCLUDES) $(MODULE_INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(MODULE_ARM_ASMOBJS): $(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(GLOBAL_OPTFLAGS) $(MODULE_OPTFLAGS) $(GLOBAL_COMPILEFLAGS) $(MODULE_COMPILEFLAGS) $(GLOBAL_ASMFLAGS) $(MODULE_ASMFLAGS) $(INCLUDES) $(MODULE_INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# clear some variables we set here
MODULE_CSRCS :=
MODULE_CPPSRCS :=
MODULE_ASMSRCS :=
MODULE_COBJS :=
MODULE_CPPOBJS :=
MODULE_ASMOBJS :=
# MODULE_OBJS is passed back
#MODULE_OBJS :=

View File

@@ -3,3 +3,29 @@ GET_LOCAL_DIR = $(patsubst %/,%,$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKE
# makes sure the target dir exists
MKDIR = if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
# prepends the BUILD_DIR var to each item in the list
TOBUILDDIR = $(addprefix $(BUILDDIR)/,$(1))
# generate a header file at $1 with an expanded variable in $2
define MAKECONFIGHEADER
@$(MKDIR)
@echo generating $1
@rm -f $1.tmp; \
LDEF=`echo $1 | tr '/\\.-' '_'`; \
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; \
done; \
echo \#endif >> $1.tmp; \
if [ -f "$1" ]; then \
if cmp "$1.tmp" "$1"; then \
rm -f $1.tmp; \
else \
mv $1.tmp $1; \
fi \
else \
mv $1.tmp $1; \
fi
endef

97
make/module.mk Normal file
View File

@@ -0,0 +1,97 @@
# modules
#
# args:
# MODULE : module name (required)
# MODULE_SRCS : list of source files, local path (required)
# MODULE_DEPS : other modules that this one depends on
# MODULE_DEFINES : #defines local to this module
# MODULE_OPTFLAGS : OPTFLAGS local to this module
# MODULE_COMPILEFLAGS : COMPILEFLAGS local to this module
# MODULE_CFLAGS : CFLAGS local to this module
# MODULE_CPPFLAGS : CPPFLAGS local to this module
# MODULE_ASMFLAGS : ASMFLAGS local to this module
# MODULE_SRCDEPS : extra dependencies that all of this module's files depend on
# MODULE_ARM_OVERRIDE_SRCS : list of source files, local path that should be force compiled with ARM (if applicable)
# the minimum module rules.mk file is as follows:
#
# LOCAL_DIR := $(GET_LOCAL_DIR)
# MODULE := $(LOCAL_DIR)
#
# MODULE_SRCS := $(LOCAL_DIR)/at_least_one_source_file.c
#
# include make/module.mk
# test for old style rules.mk
ifneq ($(MODULE_OBJS),)
$(warning MODULE_OBJS = $(MODULE_OBJS))
$(error MODULE $(MODULE) is setting MODULE_OBJS, change to MODULE_SRCS)
endif
ifneq ($(OBJS),)
$(warning OBJS = $(OBJS))
$(error MODULE $(MODULE) is probably setting OBJS, change to MODULE_SRCS)
endif
MODULE_SRCDIR := $(MODULE)
MODULE_BUILDDIR := $(call TOBUILDDIR,$(MODULE_SRCDIR))
# add the listed module deps to the global list
MODULES += $(MODULE_DEPS)
#$(info module $(MODULE))
#$(info MODULE_SRCDIR $(MODULE_SRCDIR))
#$(info MODULE_BUILDDIR $(MODULE_BUILDDIR))
#$(info MODULE_DEPS $(MODULE_DEPS))
#$(info MODULE_SRCS $(MODULE_SRCS))
# generate a per-module config.h file
MODULE_CONFIG := $(MODULE_BUILDDIR)/module_config.h
$(MODULE_CONFIG): MODULE_DEFINES:=$(MODULE_DEFINES)
$(MODULE_CONFIG): configheader
$(call MAKECONFIGHEADER,$@,MODULE_DEFINES)
GENERATED += $(MODULE_CONFIG)
MODULE_COMPILEFLAGS += --include $(MODULE_CONFIG)
MODULE_SRCDEPS += $(MODULE_CONFIG)
# include the rules to compile the module's object files
include make/compile.mk
# MODULE_OBJS is passed back from compile.mk
#$(info MODULE_OBJS = $(MODULE_OBJS))
# build a ld -r style combined object
MODULE_OBJECT := $(call TOBUILDDIR,$(MODULE_SRCDIR).mod.o)
$(MODULE_OBJECT): $(MODULE_OBJS)
@$(MKDIR)
@echo linking $@
$(NOECHO)$(LD) -r $^ -o $@
# track all the objects built
ALLOBJS += $(MODULE_OBJS)
# make the rest of the build depend on our output
ALLMODULE_OBJS := $(ALLMODULE_OBJS) $(MODULE_OBJECT)
# empty out any vars set here
MODULE :=
MODULE_SRCDIR :=
MODULE_BUILDDIR :=
MODULE_DEPS :=
MODULE_SRCS :=
MODULE_OBJS :=
MODULE_DEFINES :=
MODULE_OPTFLAGS :=
MODULE_COMPILEFLAGS :=
MODULE_CFLAGS :=
MODULE_CPPFLAGS :=
MODULE_ASMFLAGS :=
MODULE_SRCDEPS :=
MODULE_CONFIG :=
MODULE_OBJECT :=
MODULE_ARM_OVERRIDE_SRCS :=

View File

@@ -35,22 +35,26 @@ OUTELF := $(BUILDDIR)/lk
CONFIGHEADER := $(BUILDDIR)/config.h
INCLUDES := -I$(BUILDDIR) -Iinclude
CFLAGS := -O2 -g -fno-builtin -finline -W -Wall -Wno-multichar -Wno-unused-parameter -Wno-unused-function -include $(CONFIGHEADER)
CFLAGS += -Werror-implicit-function-declaration
#CFLAGS += -Werror
CPPFLAGS := -fno-exceptions -fno-rtti -fno-threadsafe-statics
#CPPFLAGS += -Weffc++
ASMFLAGS := -DASSEMBLY
LDFLAGS :=
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 :=
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -gc-sections
GLOBAL_COMPILEFLAGS += -ffunction-sections -fdata-sections
GLOBAL_LDFLAGS += -gc-sections
# top level rule
all:: $(OUTBIN) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).size
# master object list
OBJS :=
# 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 :=
@@ -95,10 +99,6 @@ include make/recurse.mk
# any extra top level build dependencies that someone declared
all:: $(EXTRA_BUILDDEPS)
ALLOBJS := \
$(BOOTOBJS) \
$(OBJS)
# add some automatic configuration defines
DEFINES += \
PROJECT_$(PROJECT)=1 \
@@ -113,10 +113,10 @@ DEFINES += \
DEBUG=$(DEBUG)
endif
ALLOBJS := $(addprefix $(BUILDDIR)/,$(ALLOBJS))
DEPS := $(ALLOBJS:%o=%d)
#$(warning DEPS=$(DEPS))
# default to no ccache
CCACHE ?=
CC := $(CCACHE) $(TOOLCHAIN_PREFIX)gcc
@@ -130,6 +130,25 @@ NM := $(TOOLCHAIN_PREFIX)nm
# 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
@@ -143,24 +162,7 @@ install: all
configheader:
$(CONFIGHEADER): configheader
@$(MKDIR)
@echo generating $@
@rm -f $(CONFIGHEADER).tmp; \
echo \#ifndef __CONFIG_H > $(CONFIGHEADER).tmp; \
echo \#define __CONFIG_H >> $(CONFIGHEADER).tmp; \
for d in `echo $(DEFINES) | tr [:lower:] [:upper:]`; do \
echo "#define $$d" | sed "s/=/\ /g;s/-/_/g;s/\//_/g" >> $(CONFIGHEADER).tmp; \
done; \
echo \#endif >> $(CONFIGHEADER).tmp; \
if [ -f "$(CONFIGHEADER)" ]; then \
if cmp "$(CONFIGHEADER).tmp" "$(CONFIGHEADER)"; then \
rm -f $(CONFIGHEADER).tmp; \
else \
mv $(CONFIGHEADER).tmp $(CONFIGHEADER); \
fi \
else \
mv $(CONFIGHEADER).tmp $(CONFIGHEADER); \
fi
$(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.