summaryrefslogtreecommitdiff
path: root/Makefile
blob: a8b282c61309c76a73c3fc95d3e0e1556b60bcad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
# Copyright 2011 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Embedded Controller firmware build system
#

# Allow for masking of some targets based on the build architecture. When
# building using a portage package (such as chromeos-ec), this variable will
# already be set. To support the typical developer workflow a default value is
# provided matching the typical architecture of developer workstations. Note
# that amd64 represents the entire x84_64 architecture including intel CPUs.
# This is used to exclude build targets that depend on sanitizers such as
# fuzzers on architectures that don't support sanitizers yet (e.g. arm).
ARCH?=amd64
BOARD ?= elm

# Directory where the board is configured (includes /$(BOARD) at the end)
BDIR:=$(wildcard board/$(BOARD))
# Private board directory
PBDIR:=$(wildcard private-*/board/$(BOARD))

# We need either public, or private board directory, or both.
ifeq (,$(BDIR)$(PBDIR))
$(error unable to locate BOARD $(BOARD))
endif

# Setup PDIR (private directory root).
ifneq (,$(PBDIR))
ifneq (1,$(words $(PBDIR)))
$(error multiple private definitions for BOARD $(BOARD): $(PBDIR))
endif

PDIR:=$(subst /board/$(BOARD),,$(PBDIR))
endif

# If only private is present, use that as BDIR.
ifeq (,$(BDIR))
BDIR:=$(PBDIR)
endif

PROJECT?=ec

# An empty string.
# "-DMACRO" leads to MACRO=1.  Define an empty string "-DMACRO=" to take
# advantage of IS_ENABLED magic macro, which only allows an empty string.
EMPTY=

# Output directory for build objects
ifdef CTS_MODULE
# CTS builds need different directories per board per suite.
out?=build/$(BOARD)/cts_$(CTS_MODULE)
else ifdef TEST_COVERAGE
out?=build/coverage/initial-$(BOARD)
else
out?=build/$(BOARD)
endif

# File containing configuration information
config=$(out)/.config

# If no key file is provided, use the default dev key
PEM ?= $(BDIR)/dev_key.pem

# Port for flash_ec. Defaults to 9999.
PORT ?= 9999

# If CONFIG_TOUCHPAD_HASH_FW is set, include hashes of a touchpad firmware in
# the EC image (if no touchpad firmware is provided, just output blank hashes).
TOUCHPAD_FW ?=

# If TEST_FUZZ is set make sure at least one sanitizer is enabled.
ifeq ($(TEST_FUZZ)_$(TEST_ASAN)$(TEST_MSAN)$(TEST_UBSAN),y_)
override TEST_ASAN:=y
endif

include Makefile.toolchain

# Define the traditional first target. The dependencies of this are near the
# bottom as they can be altered by chip and board files.
.PHONY: all
all:

# Returns the opposite of a configuration variable
# y  ->
# ro -> rw
# rw -> ro
#    -> y
# usage: common-$(call not_cfg,$(CONFIG_FOO))+=bar.o
not_cfg = $(subst ro rw,y,$(filter-out $(1:y=ro rw),ro rw))

# The board makefile sets $CHIP and the chip makefile sets $CORE.
# Include those now, since they must be defined for _flag_cfg below.
include $(BDIR)/build.mk

ifneq ($(ENV_VARS),)
# Let's make sure $(out)/env_config.h changes if value any of the above
# variables has changed since the prvious make invocation. This in turn will
# make sure that relevant object files are re-built.
current_set = $(foreach env_flag, $(ENV_VARS), $(env_flag)=$($(env_flag)))
$(shell util/env_changed.sh "$(out)/env_config.h" "$(current_set)")
endif

# Baseboard directory
ifneq (,$(BASEBOARD))
BASEDIR:=baseboard/$(BASEBOARD)
CFLAGS_BASEBOARD=-DHAS_BASEBOARD=$(EMPTY) -DBASEBOARD_$(UC_BASEBOARD)=$(EMPTY)
include $(BASEDIR)/build.mk
else
# If BASEBOARD is not defined, then assign BASEDIR to BDIR. This avoids
# the need to have so many conditional checks wherever BASEDIR is used
# below.
BASEDIR:=$(BDIR)
CFLAGS_BASEBOARD=
endif
include chip/$(CHIP)/build.mk

# The toolchain must be set before referencing any toolchain-related variables
# (CC, CPP, CXX, etc.) so that the correct toolchain is used. The CORE variable
# is set in the CHIP build file, so this include must come after including the
# CHIP build file.
include core/$(CORE)/toolchain.mk

# Create uppercase config variants, to avoid mixed case constants.
# Also translate '-' to '_', so 'cortex-m' turns into 'CORTEX_M'.  This must
# be done before evaluating config.h.
uppercase = $(shell echo $(1) | tr '[:lower:]-' '[:upper:]_')
UC_BASEBOARD:=$(call uppercase,$(BASEBOARD))
UC_BOARD:=$(call uppercase,$(BOARD))
UC_CHIP:=$(call uppercase,$(CHIP))
UC_CHIP_FAMILY:=$(call uppercase,$(CHIP_FAMILY))
UC_CHIP_VARIANT:=$(call uppercase,$(CHIP_VARIANT))
UC_CORE:=$(call uppercase,$(CORE))
UC_PROJECT:=$(call uppercase,$(PROJECT))

# Transform the configuration into make variables.  This must be done after
# the board/baseboard/project/chip/core variables are defined, since some of
# the configs are dependent on particular configurations.
includes=include core/$(CORE)/include include/driver $(dirs) $(out) fuzz test third_party
ifdef CTS_MODULE
includes+=cts/$(CTS_MODULE) cts
endif
ifeq "$(TEST_BUILD)" "y"
	_tsk_lst_file:=ec.tasklist
	_tsk_lst_flags:=$(if $(TEST_FUZZ),-Ifuzz,-Itest) -DTEST_BUILD=$(EMPTY) \
			-imacros $(PROJECT).tasklist
else ifdef CTS_MODULE
	_tsk_lst_file:=ec.tasklist
	_tsk_lst_flags:=-I cts/$(CTS_MODULE) -Icts -DCTS_MODULE=$(CTS_MODULE) \
			-imacros cts.tasklist
else
	_tsk_lst_file:=$(PROJECT).tasklist
	_tsk_lst_flags:=
endif

_tsk_lst_flags+=-I$(BDIR) -DBOARD_$(UC_BOARD)=$(EMPTY) -I$(BASEDIR) \
		-DBASEBOARD_$(UC_BASEBOARD)=$(EMPTY) \
		-D_MAKEFILE=$(EMPTY) -imacros $(_tsk_lst_file)
-include private/task_list_flags.mk

_tsk_lst_ro:=$(shell $(CPP) -P -DSECTION_IS_RO=$(EMPTY) \
	$(_tsk_lst_flags) include/task_filter.h)
_tsk_lst_rw:=$(shell $(CPP) -P -DSECTION_IS_RW=$(EMPTY) \
	$(_tsk_lst_flags) include/task_filter.h)

_tsk_cfg_ro:=$(foreach t,$(_tsk_lst_ro) ,HAS_TASK_$(t))
_tsk_cfg_rw:=$(foreach t,$(_tsk_lst_rw) ,HAS_TASK_$(t))

_tsk_cfg:= $(filter $(_tsk_cfg_ro), $(_tsk_cfg_rw))
_tsk_cfg_ro:= $(filter-out $(_tsk_cfg), $(_tsk_cfg_ro))
_tsk_cfg_rw:= $(filter-out $(_tsk_cfg), $(_tsk_cfg_rw))

CPPFLAGS_RO+=$(foreach t,$(_tsk_cfg_ro),-D$(t)=$(EMPTY)) \
		$(foreach t,$(_tsk_cfg_rw),-D$(t)_RW=$(EMPTY))
CPPFLAGS_RW+=$(foreach t,$(_tsk_cfg_rw),-D$(t)=$(EMPTY)) \
		$(foreach t,$(_tsk_cfg_ro),-D$(t)_RO=$(EMPTY))
CPPFLAGS+=$(foreach t,$(_tsk_cfg),-D$(t)=$(EMPTY))
ifneq ($(ENV_VARS),)
CPPFLAGS += -DINCLUDE_ENV_CONFIG=$(EMPTY)
CFLAGS += -I$(realpath $(out))
endif
# Get the CONFIG_ and VARIANT_ options that are defined for this target and make
# them into variables available to this build script
_flag_cfg_ro:=$(shell $(CPP) $(CPPFLAGS) -P -dM -Ichip/$(CHIP) \
	-I$(BASEDIR) -I$(BDIR) -DSECTION_IS_RO=$(EMPTY) include/config.h | \
	grep -o "\#define \(CONFIG\|VARIANT\)_[A-Z0-9_]*" | cut -c9- | sort)
_flag_cfg_rw:=$(_tsk_cfg_rw) $(shell $(CPP) $(CPPFLAGS) -P -dM -Ichip/$(CHIP) \
	-I$(BASEDIR) -I$(BDIR) -DSECTION_IS_RW=$(EMPTY) include/config.h | \
	grep -o "\#define \(CONFIG\|VARIANT\)_[A-Z0-9_]*" | cut -c9- | sort)

_flag_cfg:= $(filter $(_flag_cfg_ro), $(_flag_cfg_rw))
_flag_cfg_ro:= $(filter-out $(_flag_cfg), $(_flag_cfg_ro))
_flag_cfg_rw:= $(filter-out $(_flag_cfg), $(_flag_cfg_rw))

$(foreach c,$(_tsk_cfg_rw) $(_flag_cfg_rw),$(eval $(c)=rw))
$(foreach c,$(_tsk_cfg_ro) $(_flag_cfg_ro),$(eval $(c)=ro))
$(foreach c,$(_tsk_cfg) $(_flag_cfg),$(eval $(c)=y))

# Fetch list of mocks from .mocklist files for tests and fuzzers.
# The following will transform the the list of mocks into
# HAS_MOCK_<NAME> for use in the build systems and CPP,
# similar to task definitions.
_mock_lst_flags := $(if $(TEST_FUZZ),-Ifuzz,-Itest) -DTEST_BUILD=$(EMPTY) \
	-imacros $(PROJECT).mocklist                                      \
	-I$(BDIR) -DBOARD_$(UC_BOARD)=$(EMPTY) -I$(BASEDIR)               \
	-DBASEBOARD_$(UC_BASEBOARD)=$(EMPTY)                              \
	-D_MAKEFILE=$(EMPTY)
_mock_file := $(if $(TEST_FUZZ),fuzz,test)/$(PROJECT).mocklist

# If test/fuzz build and mockfile exists, source the list of
# mocks from mockfile.
_mock_lst :=
ifneq ($(and $(TEST_BUILD),$(wildcard $(_mock_file))),)
	_mock_lst += $(shell $(CPP) -P $(_mock_lst_flags) \
		include/mock_filter.h)
endif

_mock_cfg := $(foreach t,$(_mock_lst) ,HAS_MOCK_$(t))
CPPFLAGS += $(foreach t,$(_mock_cfg),-D$(t)=$(EMPTY))
$(foreach c,$(_mock_cfg),$(eval $(c)=y))

ifneq ($(CONFIG_COMMON_RUNTIME),y)
ifneq ($(CONFIG_DFU_BOOTMANAGER_MAIN),ro)
	_irq_list:=$(shell $(CPP) $(CPPFLAGS) -P -Ichip/$(CHIP) -I$(BASEDIR) \
		-I$(BDIR) -D"ENABLE_IRQ(x)=EN_IRQ x" \
		-imacros chip/$(CHIP)/registers.h \
		- < $(BDIR)/ec.irqlist | grep "EN_IRQ .*" | cut -c8-)
	CPPFLAGS+=$(foreach irq,$(_irq_list),\
		    -D"irq_$(irq)_handler_optional=irq_$(irq)_handler")
endif
endif

# Compute RW firmware size and offset
_rw_off_str:=$(shell echo "CONFIG_RW_MEM_OFF" | $(CPP) $(CPPFLAGS) -P \
	-Ichip/$(CHIP) -I$(BASEDIR) -I$(BDIR) -imacros include/config.h -)
_rw_off:=$(shell echo "$$(($(_rw_off_str)))")
_rw_size_str:=$(shell echo "CONFIG_RW_SIZE" | $(CPP) $(CPPFLAGS) -P \
	-Ichip/$(CHIP) -I$(BASEDIR) -I$(BDIR) -imacros include/config.h -)
_rw_size:=$(shell echo "$$(($(_rw_size_str)))")
_program_memory_base_str:=$(shell echo "CONFIG_PROGRAM_MEMORY_BASE" | \
	$(CPP) $(CPPFLAGS) -P \
	-Ichip/$(CHIP) -I$(BDIR) -I$(BASEDIR) -imacros include/config.h -)
_program_memory_base=$(shell echo "$$(($(_program_memory_base_str)))")

$(eval BASEBOARD_$(UC_BASEBOARD)=y)
$(eval BOARD_$(UC_BOARD)=y)
$(eval CHIP_$(UC_CHIP)=y)
$(eval CHIP_VARIANT_$(UC_CHIP_VARIANT)=y)
$(eval CHIP_FAMILY_$(UC_CHIP_FAMILY)=y)

# Private subdirectories may call this from their build.mk
# First arg is the path to be prepended to configured *.o files.
# Second arg is the config variable (ie, "FOO" to select with $(FOO-$3)).
# Third arg is the config variable value ("y" for configuration options
#   that are set for both RO and RW, "rw" for RW-only configuration options)
objs_from_dir_p=$(foreach obj, $($(2)-$(3)), $(1)/$(obj))
objs_from_dir=$(call objs_from_dir_p,$(1),$(2),y)

# Get build configuration from sub-directories
# Note that this re-includes the board and chip makefiles

ifdef CTS_MODULE
include cts/build.mk
endif
include $(BASEDIR)/build.mk
ifneq ($(BASEDIR),$(BDIR))
include $(BDIR)/build.mk
endif
ifeq ($(USE_BUILTIN_STDLIB), 1)
include builtin/build.mk
else
include libc/build.mk
endif
include chip/$(CHIP)/build.mk
include core/build.mk
include core/$(CORE)/build.mk
include common/build.mk
include driver/build.mk
include fuzz/build.mk
include power/build.mk
-include private/build.mk
-include private-kandou/build.mk
ifneq ($(PDIR),)
include $(PDIR)/build.mk
endif
ifneq ($(PBDIR),)
include $(PBDIR)/build.mk
endif
include test/build.mk
include util/build.mk
include util/lock/build.mk

includes+=$(includes-y)

# Wrapper for fetching all the sources relevant to this build
# target.
# First arg is "y" indicating sources for all segments,
#   or "rw" indicating sources for rw segment.
define get_sources =
# Get sources to build for this target
all-obj-$(1)+=$(call objs_from_dir_p,core/$(CORE),core,$(1))
all-obj-$(1)+=$(call objs_from_dir_p,chip/$(CHIP),chip,$(1))
all-obj-$(1)+=$(call objs_from_dir_p,$(BASEDIR),baseboard,$(1))
all-obj-$(1)+=$(call objs_from_dir_p,$(BDIR),board,$(1))
all-obj-$(1)+=$(call objs_from_dir_p,private,private,$(1))
all-obj-$(1)+=$(call objs_from_dir_p,private-kandou,private-kandou,$(1))
ifneq ($(PDIR),)
all-obj-$(1)+=$(call objs_from_dir_p,$(PDIR),$(PDIR),$(1))
endif
ifneq ($(PBDIR),)
all-obj-$(1)+=$(call objs_from_dir_p,$(PBDIR),board-private,$(1))
endif
all-obj-$(1)+=$(call objs_from_dir_p,common,common,$(1))
ifeq ($(USE_BUILTIN_STDLIB), 1)
all-obj-$(1)+=$(call objs_from_dir_p,builtin,builtin,$(1))
else
all-obj-$(1)+=$(call objs_from_dir_p,libc,libc,$(1))
endif
all-obj-$(1)+=$(call objs_from_dir_p,driver,driver,$(1))
all-obj-$(1)+=$(call objs_from_dir_p,power,power,$(1))
ifdef CTS_MODULE
all-obj-$(1)+=$(call objs_from_dir_p,cts,cts,$(1))
endif
ifeq ($(TEST_FUZZ),y)
all-obj-$(1)+=$(call objs_from_dir_p,fuzz,$(PROJECT),$(1))
else
all-obj-$(1)+=$(call objs_from_dir_p,test,$(PROJECT),$(1))
endif
endef

# Get all sources to build
$(eval $(call get_sources,y))
$(eval $(call get_sources,ro))

# The following variables are meant to be initialized in the baseboard or
# board's build.mk. They will later be appended to in util/build.mk with
# utils that should be generated for all boards.
#
# build-util-bin-y - Utils for the system doing the "build".
#                    For example, the 64-bit x86 GNU/Linux running make.
#                    These are often program that are needed by the build
#                    system to generate code for use in firmware.
# host-util-bin-y  - Utils for the target platform on top of the EC.
#                    For example, the 32-bit x86 Chromebook.
# build-util-art-y - Build ?artifacts? for the system doing the "build"
#
# The util targets added to these variable will pickup extra build objects
# from their optional <util_name>-objs make variable.
#
# See commit bc4c1b4 for more context.
build-utils := $(call objs_from_dir,$(out)/util,build-util-bin)
ifeq ($(BOARD),host)
host-utils := $(call objs_from_dir,$(out)/util,host-util-bin)
host-utils-cxx := $(call objs_from_dir,$(out)/util,host-util-bin-cxx)
endif
build-art := $(call objs_from_dir,$(out),build-util-art)
# Use the util_name with an added .c AND the special <util_name>-objs variable.
build-srcs := $(foreach u,$(build-util-bin-y),$(sort $($(u)-objs:%.o=util/%.c) \
                $(wildcard util/$(u).c)))
host-srcs := $(foreach u,$(host-util-bin-y),$(sort $($(u)-objs:%.o=util/%.c) \
               $(wildcard util/$(u).c)))
host-srcs-cxx := $(foreach u,$(host-util-bin-cxx-y), \
	$(sort $($(u)-objs:%.o=util/%.cc) $(wildcard util/$(u).cc)))

dirs=core/$(CORE) chip/$(CHIP) $(BASEDIR) $(BDIR) common fuzz power test \
	cts/common cts/$(CTS_MODULE) $(out)/gen
dirs+= private private-kandou $(PDIR) $(PBDIR)
dirs+=$(shell find common -type d)
dirs+=$(shell find driver -type d)
ifeq ($(USE_BUILTIN_STDLIB), 1)
dirs+=builtin
else
dirs+=libc
endif
common_dirs=util

ifeq ($(custom-ro_objs-y),)
ro-common-objs := $(sort $(foreach obj, $(all-obj-y), $(out)/RO/$(obj)))
ro-only-objs := $(sort $(foreach obj, $(all-obj-ro), $(out)/RO/$(obj)))
ro-objs := $(sort $(ro-common-objs) $(ro-only-objs))
else
ro-objs := $(sort $(foreach obj, $(custom-ro_objs-y), $(out)/RO/$(obj)))
endif

# Add RW-only sources to build
$(eval $(call get_sources,rw))

rw-common-objs := $(sort $(foreach obj, $(all-obj-y), $(out)/RW/$(obj)))
rw-only-objs := $(sort $(foreach obj, $(all-obj-rw), $(out)/RW/$(obj)))
rw-objs := $(sort $(rw-common-objs) $(rw-only-objs))

# Don't include the shared objects in the RO/RW image if we're enabling
# the shared objects library.
ifeq ($(CONFIG_SHAREDLIB),y)
ro-objs := $(filter-out %_sharedlib.o, $(ro-objs))
endif
ro-deps := $(addsuffix .d, $(ro-objs))
rw-deps := $(addsuffix .d, $(rw-objs))

deps := $(ro-deps) $(rw-deps) $(deps-y)

.PHONY: ro rw
$(config): $(out)/$(PROJECT).bin
	@printf '%s=y\n' $(_tsk_cfg) $(_flag_cfg) > $@

def_all_deps:=$(config) $(PROJECT_EXTRA) notice rw size utils
ifeq ($(CONFIG_FW_INCLUDE_RO),y)
def_all_deps+=ro
endif
all_deps?=$(def_all_deps)
all: $(all_deps)
compile-only: $(ro-objs) $(rw-objs)

ro: override BLD:=RO
ro: $(libsharedobjs_elf-y) $(out)/RO/$(PROJECT).RO.flat

rw: override BLD:=RW
rw: $(libsharedobjs_elf-y) $(out)/RW/$(PROJECT).RW.flat

# Shared objects library
SHOBJLIB := libsharedobjs
sharedlib-objs := $(filter %_sharedlib.o, $(all-obj-y))
sharedlib-objs := $(foreach obj, $(sharedlib-objs), $(out)/$(SHOBJLIB)/$(obj))
sharedlib-deps := $(sharedlib-objs:%.o=%.o.d)
deps += $(sharedlib-deps)
def_libsharedobjs_deps := $(sharedlib-objs)
libsharedobjs_deps ?= $(def_libsharedobjs_deps)

libsharedobjs-$(CONFIG_SHAREDLIB) := $(out)/$(SHOBJLIB)/$(SHOBJLIB).flat
libsharedobjs_elf-$(CONFIG_SHAREDLIB) := \
	$(libsharedobjs-$(CONFIG_SHAREDLIB):%.flat=%.elf)
libsharedobjs: $(libsharedobjs-y)

include Makefile.rules
export CROSS_COMPILE CFLAGS CC CPP LD NM AR OBJCOPY OBJDUMP