1LOCAL_MAKEFILE:=$(MAKEFILE_LIST)
2
3# macros used all over the build system
4include make/macros.mk
5
6BUILDROOT ?= .
7
8# 'make spotless' is a special rule that skips most of the rest of the build system and
9# simply deletes everything in build-*
10ifeq ($(MAKECMDGOALS),spotless)
11spotless:
12	rm -rf -- "$(BUILDROOT)"/build-*
13else
14
15ifndef LKROOT
16$(error please define LKROOT to the root of the lk build system)
17endif
18
19# any local environment overrides can optionally be placed in local.mk
20-include local.mk
21
22# If one of our goals (from the commandline) happens to have a
23# matching project/goal.mk, then we should re-invoke make with
24# that project name specified...
25
26project-name := $(firstword $(MAKECMDGOALS))
27
28ifneq ($(project-name),)
29ifneq ($(strip $(foreach d,$(LKINC),$(wildcard $(d)/project/$(project-name).mk))),)
30do-nothing := 1
31$(MAKECMDGOALS) _all: make-make
32	@:
33make-make:
34	@PROJECT=$(project-name) $(MAKE) -rR -f $(LOCAL_MAKEFILE) $(filter-out $(project-name), $(MAKECMDGOALS))
35
36.PHONY: make-make
37endif # expansion of project-name
38endif # project-name == null
39
40# some additional rules to print some help
41include make/help.mk
42
43ifeq ($(do-nothing),)
44
45ifeq ($(PROJECT),)
46
47ifneq ($(DEFAULT_PROJECT),)
48PROJECT := $(DEFAULT_PROJECT)
49else
50$(error No project specified. Use 'make list' for a list of projects or 'make help' for additional help)
51endif # DEFAULT_PROJECT == something
52
53endif # PROJECT == null
54
55DEBUG ?= 2
56
57BUILDDIR := $(BUILDROOT)/build-$(PROJECT)
58OUTBIN := $(BUILDDIR)/lk.bin
59OUTELF := $(BUILDDIR)/lk.elf
60CONFIGHEADER := $(BUILDDIR)/config.h
61
62GLOBAL_INCLUDES := $(BUILDDIR) $(addsuffix /include,$(LKINC))
63GLOBAL_OPTFLAGS ?= $(ARCH_OPTFLAGS)
64GLOBAL_COMPILEFLAGS := -g -include $(CONFIGHEADER)
65GLOBAL_COMPILEFLAGS += -Wextra -Wall -Werror=return-type -Wshadow -Wdouble-promotion
66GLOBAL_COMPILEFLAGS += -Wno-multichar -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wno-nonnull-compare
67GLOBAL_COMPILEFLAGS += -fno-common
68GLOBAL_CFLAGS := --std=gnu11 -Werror-implicit-function-declaration -Wstrict-prototypes -Wwrite-strings
69GLOBAL_CPPFLAGS := --std=c++14 -fno-exceptions -fno-rtti -fno-threadsafe-statics
70GLOBAL_ASMFLAGS := -DASSEMBLY
71GLOBAL_LDFLAGS :=
72
73# flags that are sometimes nice to enable to catch problems but too strict to have on all the time
74#GLOBAL_COMPILEFLAGS += -Wmissing-declarations
75
76# if WERROR is set, add to the compile args
77ifeq (true,$(call TOBOOL,$(WERROR)))
78GLOBAL_COMPILEFLAGS += -Werror
79endif
80
81GLOBAL_LDFLAGS += $(addprefix -L,$(LKINC))
82
83# Architecture specific compile flags
84ARCH_COMPILEFLAGS :=
85ARCH_CFLAGS :=
86ARCH_CPPFLAGS :=
87ARCH_ASMFLAGS :=
88ARCH_LDFLAGS :=
89
90# top level rule
91all:: $(OUTBIN) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).sym.sorted $(OUTELF).size $(OUTELF).dump $(BUILDDIR)/srcfiles.txt $(BUILDDIR)/include_paths.txt
92
93# master module object list
94ALLOBJS_MODULE :=
95
96# master object list (for dep generation)
97ALLOBJS :=
98
99# master source file list
100ALLSRCS :=
101
102# a linker script needs to be declared in one of the project/target/platform files
103LINKER_SCRIPT :=
104
105# anything you add here will be deleted in make clean
106GENERATED := $(CONFIGHEADER)
107
108# anything added to GLOBAL_DEFINES will be put into $(BUILDDIR)/config.h
109GLOBAL_DEFINES := LK=1
110
111# Anything added to GLOBAL_SRCDEPS will become a dependency of every source file in the system.
112# Useful for header files that may be included by one or more source files.
113GLOBAL_SRCDEPS := $(CONFIGHEADER)
114
115# these need to be filled out by the project/target/platform rules.mk files
116TARGET :=
117PLATFORM :=
118ARCH :=
119ALLMODULES :=
120
121# add any external module dependencies
122MODULES := $(EXTERNAL_MODULES)
123
124# any .mk specified here will be included before build.mk
125EXTRA_BUILDRULES :=
126
127# any rules you put here will also be built by the system before considered being complete
128EXTRA_BUILDDEPS :=
129
130# any rules you put here will be depended on in clean builds
131EXTRA_CLEANDEPS :=
132
133# any objects you put here get linked with the final image
134EXTRA_OBJS :=
135
136# any extra linker scripts to be put on the command line
137EXTRA_LINKER_SCRIPTS :=
138
139# if someone defines this, the build id will be pulled into lib/version
140BUILDID ?=
141
142# comment out or override if you want to see the full output of each command
143NOECHO ?= @
144
145# try to include the project file
146-include project/$(PROJECT).mk
147ifndef TARGET
148$(error couldn't find project or project doesn't define target)
149endif
150include target/$(TARGET)/rules.mk
151ifndef PLATFORM
152$(error couldn't find target or target doesn't define platform)
153endif
154include platform/$(PLATFORM)/rules.mk
155
156ifndef ARCH
157$(error couldn't find arch or platform doesn't define arch)
158endif
159include arch/$(ARCH)/rules.mk
160ifndef TOOLCHAIN_PREFIX
161$(error TOOLCHAIN_PREFIX not set in the arch rules.mk)
162endif
163
164$(info PROJECT = $(PROJECT))
165$(info PLATFORM = $(PLATFORM))
166$(info TARGET = $(TARGET))
167$(info ARCH = $(ARCH))
168$(info TOOLCHAIN_PREFIX = $(TOOLCHAIN_PREFIX))
169$(info DEBUG = $(DEBUG))
170
171# include the top level module that includes basic always-there modules
172include top/rules.mk
173
174# recursively include any modules in the MODULE variable, leaving a trail of included
175# modules in the ALLMODULES list
176include make/recurse.mk
177
178# add some automatic configuration defines
179GLOBAL_DEFINES += \
180	PROJECT_$(PROJECT)=1 \
181	PROJECT=\"$(PROJECT)\" \
182	TARGET_$(TARGET)=1 \
183	TARGET=\"$(TARGET)\" \
184	PLATFORM_$(PLATFORM)=1 \
185	PLATFORM=\"$(PLATFORM)\" \
186	ARCH_$(ARCH)=1 \
187	ARCH=\"$(ARCH)\" \
188	$(addsuffix =1,$(addprefix WITH_,$(ALLMODULES)))
189
190# debug build?
191ifneq ($(DEBUG),)
192GLOBAL_DEFINES += \
193	LK_DEBUGLEVEL=$(DEBUG)
194endif
195
196# allow additional defines from outside the build system
197ifneq ($(EXTERNAL_DEFINES),)
198GLOBAL_DEFINES += $(EXTERNAL_DEFINES)
199$(info EXTERNAL_DEFINES = $(EXTERNAL_DEFINES))
200endif
201
202
203# prefix all of the paths in GLOBAL_INCLUDES with -I
204GLOBAL_INCLUDES := $(addprefix -I,$(GLOBAL_INCLUDES))
205
206# test for some old variables
207ifneq ($(INCLUDES),)
208$(error INCLUDES variable set, please move to GLOBAL_INCLUDES: $(INCLUDES))
209endif
210ifneq ($(DEFINES),)
211$(error DEFINES variable set, please move to GLOBAL_DEFINES: $(DEFINES))
212endif
213
214# default to no ccache
215CCACHE ?=
216CC := $(CCACHE) $(TOOLCHAIN_PREFIX)gcc
217LD := $(TOOLCHAIN_PREFIX)ld
218OBJDUMP := $(TOOLCHAIN_PREFIX)objdump
219OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy
220CPPFILT := $(TOOLCHAIN_PREFIX)c++filt
221SIZE := $(TOOLCHAIN_PREFIX)size
222NM := $(TOOLCHAIN_PREFIX)nm
223STRIP := $(TOOLCHAIN_PREFIX)strip
224
225# try to have the compiler output colorized error messages if available
226export GCC_COLORS ?= 1
227
228# the logic to compile and link stuff is in here
229include make/build.mk
230
231DEPS := $(ALLOBJS:%o=%d)
232
233# put all of the global build flags in config.h to force a rebuild if any change
234GLOBAL_DEFINES += GLOBAL_INCLUDES=\"$(subst $(SPACE),_,$(GLOBAL_INCLUDES))\"
235GLOBAL_DEFINES += GLOBAL_COMPILEFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_COMPILEFLAGS))\"
236GLOBAL_DEFINES += GLOBAL_OPTFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_OPTFLAGS))\"
237GLOBAL_DEFINES += GLOBAL_CFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CFLAGS))\"
238GLOBAL_DEFINES += GLOBAL_CPPFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CPPFLAGS))\"
239GLOBAL_DEFINES += GLOBAL_ASMFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_ASMFLAGS))\"
240GLOBAL_DEFINES += GLOBAL_LDFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_LDFLAGS))\"
241GLOBAL_DEFINES += ARCH_COMPILEFLAGS=\"$(subst $(SPACE),_,$(ARCH_COMPILEFLAGS))\"
242GLOBAL_DEFINES += ARCH_CFLAGS=\"$(subst $(SPACE),_,$(ARCH_CFLAGS))\"
243GLOBAL_DEFINES += ARCH_CPPFLAGS=\"$(subst $(SPACE),_,$(ARCH_CPPFLAGS))\"
244GLOBAL_DEFINES += ARCH_ASMFLAGS=\"$(subst $(SPACE),_,$(ARCH_ASMFLAGS))\"
245GLOBAL_DEFINES += ARCH_LDFLAGS=\"$(subst $(SPACE),_,$(ARCH_LDFLAGS))\"
246GLOBAL_DEFINES += TOOLCHAIN_PREFIX=\"$(subst $(SPACE),_,$(TOOLCHAIN_PREFIX))\"
247
248ifneq ($(OBJS),)
249$(warning OBJS=$(OBJS))
250$(error OBJS is not empty, please convert to new module format)
251endif
252ifneq ($(OPTFLAGS),)
253$(warning OPTFLAGS=$(OPTFLAGS))
254$(error OPTFLAGS is not empty, please use GLOBAL_OPTFLAGS or MODULE_OPTFLAGS)
255endif
256ifneq ($(CFLAGS),)
257$(warning CFLAGS=$(CFLAGS))
258$(error CFLAGS is not empty, please use GLOBAL_CFLAGS or MODULE_CFLAGS)
259endif
260ifneq ($(CPPFLAGS),)
261$(warning CPPFLAGS=$(CPPFLAGS))
262$(error CPPFLAGS is not empty, please use GLOBAL_CPPFLAGS or MODULE_CPPFLAGS)
263endif
264
265$(info LIBGCC = $(LIBGCC))
266$(info GLOBAL_COMPILEFLAGS = $(GLOBAL_COMPILEFLAGS))
267$(info GLOBAL_OPTFLAGS = $(GLOBAL_OPTFLAGS))
268
269# make all object files depend on any targets in GLOBAL_SRCDEPS
270$(ALLOBJS): $(GLOBAL_SRCDEPS)
271
272# any extra top level build dependencies that someone declared.
273# build.mk may add to EXTRA_BUILDDEPS, this must be evalauted after build.mk.
274all:: $(EXTRA_BUILDDEPS)
275
276clean: $(EXTRA_CLEANDEPS)
277	rm -f $(ALLOBJS) $(DEPS) $(GENERATED) $(OUTBIN) $(OUTELF) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).sym.sorted $(OUTELF).size $(OUTELF).hex $(OUTELF).dump
278
279install: all
280	scp $(OUTBIN) 192.168.0.4:/tftproot
281
282list-arch:
283	@echo ARCH = ${ARCH}
284
285list-toolchain:
286	@echo TOOLCHAIN_PREFIX = ${TOOLCHAIN_PREFIX}
287
288.PHONY: all clean install list-arch list-toolchain
289
290# generate a config.h file with all of the GLOBAL_DEFINES laid out in #define format
291configheader:
292
293$(CONFIGHEADER): configheader
294	@$(call MAKECONFIGHEADER,$@,GLOBAL_DEFINES)
295
296.PHONY: configheader
297
298# Empty rule for the .d files. The above rules will build .d files as a side
299# effect. Only works on gcc 3.x and above, however.
300%.d:
301
302ifeq ($(filter $(MAKECMDGOALS), clean), )
303-include $(DEPS)
304endif
305
306endif # do-nothing = 1
307
308endif # make spotless
309