802 lines
27 KiB
Makefile
802 lines
27 KiB
Makefile
# -*- makefile -*-
|
|
# vim: set filetype=make :
|
|
# Copyright 2012 The Chromium OS Authors. All rights reserved.
|
|
# 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 - common targets
|
|
#
|
|
|
|
FLATSIZE_FILE ?= .sizes.txt
|
|
BUILD_DIR := $(firstword $(subst /, ,$(out)))
|
|
|
|
build-utils := $(foreach u,$(build-util-bin),$(out)/util/$(u))
|
|
host-utils := $(foreach u,$(host-util-bin),$(out)/util/$(u))
|
|
build-art := $(foreach u,$(build-util-art),$(out)/$(u))
|
|
build-srcs := $(foreach u,$(build-util-bin),$(sort $($(u)-objs:%.o=util/%.c) $(wildcard util/$(u).c)))
|
|
host-srcs := $(foreach u,$(host-util-bin),$(sort $($(u)-objs:%.o=util/%.c) $(wildcard util/$(u).c)))
|
|
|
|
# Don't do a build test on the following boards:
|
|
skip_boards = OWNERS host kevin gru
|
|
boards := $(filter-out $(skip_boards),$(notdir $(wildcard board/* private*/board/*)))
|
|
|
|
# Create output directories if necessary
|
|
_common_dir_create := $(foreach d,$(common_dirs),$(shell [ -d $(out)/$(d) ] || \
|
|
mkdir -p $(out)/$(d)))
|
|
_sharedlib_dir_create := $(foreach d,$(dirs),$(shell \
|
|
[ -d $(out)/$(SHOBJLIB)/$(d) ] || mkdir -p $(out)/$(SHOBJLIB)/$(d)))
|
|
_dir_create := $(foreach d,$(dirs) $(dirs-y),\
|
|
$(shell [ -d $(out)/$(BLD)/$(d) ] || mkdir -p $(out)/RO/$(d); \
|
|
mkdir -p $(out)/RW/$(d); mkdir -p $(out)/gen/$(d)))
|
|
|
|
# V unset for normal output, V=1 for verbose output, V=0 for silent build
|
|
# (warnings/errors only). Use echo thus: $(call echo,"stuff to echo")
|
|
# Note: if cmd_* includes a $(MAKE) invocation, use the '+' prefix
|
|
# to inherit parallel make execution: "+$(call quiet,...)"
|
|
ifeq ($(V),0)
|
|
Q := @
|
|
echo = echo -n;
|
|
quiet = echo -n; $(cmd_$(1))
|
|
silent = 1>/dev/null
|
|
silent_err = 2>/dev/null
|
|
else
|
|
echo = echo $(1);
|
|
ifeq ($(V),)
|
|
Q := @
|
|
quiet = @echo ' $(2)' $(patsubst $(out)/%,%,$@) ; $(cmd_$(1))
|
|
silent = 1>/dev/null
|
|
silent_err = 2>/dev/null
|
|
else
|
|
Q :=
|
|
quiet = $(cmd_$(1))
|
|
endif
|
|
endif
|
|
|
|
# commands to build all targets
|
|
cmd_libec = $(LD) -r $^ -o $@.1.o ${silent_err} && \
|
|
$(OBJCOPY) --localize-hidden $@.1.o $@.2.o ${silent_err} && \
|
|
$(AR) scr $@ $@.2.o ${silent_err}
|
|
cmd_lds = $(CPP) -P -C -MMD -MF $@.d -MT $@ $(CPPFLAGS) $< -o $@
|
|
cmd_lds_b = $(cmd_lds) -DRW_B_LDS=$(EMPTY)
|
|
# Allow obj_to_bin to be overridden by board or chip specific commands
|
|
cmd_obj_to_bin ?= $(OBJCOPY) --gap-fill=0xff -O binary $^ $(out)/$*.bin.tmp
|
|
cmd_flat_to_obj = $(CC) -Wl,-T $(out)/firmware_image.lds -nostdlib $(CFLAGS) \
|
|
-Wl,--build-id=none -o $@ $<
|
|
# Allow the .roshared section to overlap other sections (itself)
|
|
cmd_ec_elf_to_flat ?= $(OBJCOPY) --set-section-flags .roshared=share -R .dram* \
|
|
-O binary $< $@
|
|
cmd_ec_elf_to_flat_dram ?= $(OBJCOPY) -j .dram* -O binary $< $@
|
|
cmd_elf_to_signed ?= $(SIGNER) --key=util/signer/$(3) \
|
|
--b --input=$< --format=bin --output=$@.signed $(SIGNER_EXTRAS) \
|
|
&& sudo chown $(shell whoami) $@.signed && mv $@.signed $@
|
|
cmd_elf_to_dis = $(OBJDUMP) -D $< > $@
|
|
cmd_elf_to_bin = $(OBJCOPY) -O binary $< $@
|
|
cmd_elf_to_hex = $(OBJCOPY) -O ihex $< $@
|
|
cmd_bin_to_hex = $(OBJCOPY) -I binary -O ihex \
|
|
--change-addresses $(_program_memory_base) $^ $@
|
|
cmd_smap = $(NM) $< | sort > $@
|
|
cmd_elf = $(CC) $(objs) $(libsharedobjs_elf-y) $(LDFLAGS) \
|
|
-o $@ -Wl,-T,$< -Wl,-Map,$(patsubst %.elf,%.map,$@)
|
|
cmd_fuzz_exe = $(CXX) $^ $(HOST_TEST_LDFLAGS) $(LDFLAGS_EXTRA) -o $@
|
|
cmd_run_fuzz = build/host/$*/$*.exe -seed=1 -runs=1 $(silent) \
|
|
$(silent_err) || (echo "Test $* failed!" && false)
|
|
cmd_exe = $(CC) $(ro-objs) $(HOST_TEST_LDFLAGS) $(LDFLAGS_EXTRA) -o $@
|
|
cmd_c_to_o = $(CC) $(C_WARN) $(CFLAGS) -MMD -MP -MF $@.d -c $< -o $(@D)/$(@F)
|
|
cmd_cxx_to_o = $(CXX) -std=c++11 $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $@.d -c $< \
|
|
-o $(@D)/$(@F)
|
|
cmd_c_to_build = $(BUILDCC) $(BUILD_CFLAGS) \
|
|
$(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.c)) $(wildcard $*.c)) \
|
|
$(BUILD_LDFLAGS) \
|
|
-MMD -MF $@.d -o $@
|
|
cmd_c_to_vif = $(BUILDCC) $(BUILD_CFLAGS) $(STANDALONE_FLAGS) \
|
|
-MMD -MF $@.d -c $< -flto -o $@
|
|
cmd_c_to_host = $(HOSTCC) $(HOST_CFLAGS) -MMD -MF $@.d -o $@ \
|
|
$(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.c)) $(wildcard $*.c)) $(HOST_LDFLAGS)
|
|
cmd_cxx_to_host = $(HOSTCXX) -std=c++0x $(COMMON_WARN) $(HOST_CXXFLAGS)\
|
|
-I ./$($(notdir $@)_ROOT) -o $@ $(filter %.cc,$^) $($(notdir $@)_LIBS)
|
|
cmd_o_to_a = $(AR) rcs $@ $^
|
|
cmd_host_test = $(MAKE) --no-print-directory BOARD=host PROJECT=$* \
|
|
V=$(V) out=build/host/$* TEST_BUILD=y EMU_BUILD=y CROSS_COMPILE= \
|
|
$(if $(TEST_SCRIPT),TEST_SCRIPT=$(TEST_SCRIPT)) $(TEST_FLAG) \
|
|
build/host/$*/$*.exe
|
|
cmd_run_host_test = ./util/run_host_test $* $(silent)
|
|
# generate new version.h, compare if it changed and replace if so
|
|
cmd_version = ./util/getversion.sh > $@.tmp && \
|
|
cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@
|
|
cmd_vif = $(out)/util/genvif -b $(BOARD) -o $(out)
|
|
cmd_mv_from_tmp = mv $(out)/$*.bin.tmp $(out)/$*.bin
|
|
cmd_extractrw-y = dd if=$(out)/$(PROJECT).bin.tmp of=$(out)/$(PROJECT).RW.bin \
|
|
bs=1 count=$(_rw_size) skip=$(_rw_off) $(silent_err)
|
|
cmd_copyrw-y = cd $(out) && cp RW/$(PROJECT).RW.flat RW/$(PROJECT).RW.bin
|
|
cmd_sharedlib_elf = $(CC) $(libsharedobjs_deps) \
|
|
-Wl,-T,common/ec.$(SHOBJLIB).ld $(LDFLAGS) \
|
|
-o $(out)/$(SHOBJLIB)/$(SHOBJLIB).elf \
|
|
-Wl,-Map,$(out)/$(SHOBJLIB)/$(SHOBJLIB).map
|
|
cmd_c_to_taskinfo = $(BUILDCC) \
|
|
$(filter-out -DSECTION_IS_$(BLD)=$(EMPTY),$(BUILD_CFLAGS)) \
|
|
-DSECTION_IS_$(3)=$(EMPTY) -MMD -MF $@.d -c $< -flto -o $@
|
|
cmd_link_taskinfo = $(BUILDCC) $(BUILD_CFLAGS) --shared -fPIC $^ \
|
|
$(BUILD_LDFLAGS) -flto -o $@
|
|
cmd_proto_to_cxx = $(PROTOC) -I. --cpp_out=$(out)/gen $^
|
|
|
|
cmd_tp_hash = $(out)/util/gen_touchpad_hash \
|
|
$(if $(TOUCHPAD_FW),-f $(TOUCHPAD_FW)) -o $@
|
|
|
|
cmd_emmc_bootblock = $(out)/util/gen_emmc_transfer_data \
|
|
$(if $(BOOTBLOCK),-i $(BOOTBLOCK)) -o $@
|
|
|
|
cmd_ipi_table = $(out)/util/gen_ipi_table $@
|
|
cmd_cp_script = cp "$<" "$@" && chmod +x "$@"
|
|
|
|
# commands for RSA signature: rwsig does not need to sign the whole image
|
|
# (it signs the RW part separately). usbpd1 type needs to sign the final image.
|
|
ifeq ($(CONFIG_RWSIG_TYPE_RWSIG),)
|
|
cmd_rsasign = futility sign --type usbpd1 --pem $(PEM) $(out)/$*.bin.tmp
|
|
else
|
|
cmd_rsasign =
|
|
endif
|
|
|
|
cmd_key_extract = futility create $(PEM) $(out)/$* $(silent)
|
|
|
|
cmd_rsasign_rwsig = futility sign --type rwsig \
|
|
--prikey $(out)/key.vbprik2 $< $@
|
|
|
|
# commands to build optional xref files
|
|
cmd_deps_to_list = cat $(deps) | tr -d ':\\' | tr ' ' '\012' \
|
|
| egrep '\.[chS]$$' | sort | uniq > $@
|
|
cmd_etags = etags -o $@ $(shell cat $<)
|
|
cmd_ctags = ctags -o $@ $(shell cat $<)
|
|
targ_if_prog = $(if $(shell which $(1) 2>/dev/null),$(2),)
|
|
|
|
# If outputing to tty and column command exists, pipe into column.
|
|
# Otherwise, print in newline format.
|
|
cmd_pretty_print_list = @echo $(1) \
|
|
| tr ' ' '\n' \
|
|
| { [ -t 1 ] \
|
|
&& which column 1>/dev/null 2>&1 \
|
|
&& column || cat ; }
|
|
|
|
# By default, the "build_boards" and "try_build_boards" targets will build all
|
|
# of the boards listed in $(boards). However, the invoker can provide a
|
|
# different list via the BOARDS variable. Providing an empty value for BOARDS
|
|
# is not allowed.
|
|
BOARDS ?= $(boards)
|
|
ifeq ($(BOARDS),)
|
|
$(error BOARDS must be non-empty)
|
|
endif
|
|
|
|
FAILED_BOARDS_DIR = .failedboards
|
|
# When building with -j, it's easy to miss errors. If you don't have your shell
|
|
# configured to warn you about nonzero exit, you may not even notice that "make
|
|
# buildall -j" failed. To make it more obvious, we'll do one level of recursion
|
|
# here.
|
|
.PHONY: try_build_boards
|
|
try_build_boards: $(foreach b, $(BOARDS), proj-$(b))
|
|
|
|
.PHONY: build_boards
|
|
build_boards: | $(FAILED_BOARDS_DIR)
|
|
@rm -f $(FAILED_BOARDS_DIR)/*
|
|
$(MAKE) try_build_boards
|
|
|
|
.PHONY: buildall
|
|
buildall: build_boards build_cros_ec_commands
|
|
$(MAKE) build_cts
|
|
$(MAKE) buildfuzztests
|
|
$(MAKE) runtests
|
|
@touch .tests-passed
|
|
@echo "$@ completed successfully!"
|
|
$(call cmd_stats,RO)
|
|
$(call cmd_stats,RW)
|
|
@echo "Tightest boards' RW RAM images, bytes free:"
|
|
@grep . build/*/RW/space_free_ram.txt | \
|
|
sed 's,build/\([^/]*\)/RW/space_free_ram.txt:\(.*\)$$,\2 \1,' | \
|
|
sort -n | head -3 | while read size board; do \
|
|
printf "%-10s: %6d\n" $$board $$size; \
|
|
done
|
|
|
|
.PHONY: try_build_tests
|
|
try_build_tests: $(foreach b, $(BOARDS), tests-$(b))
|
|
|
|
.PHONY: buildalltests
|
|
buildalltests: | $(FAILED_BOARDS_DIR)
|
|
$(MAKE) try_build_tests
|
|
@echo "$@ completed successfully!"
|
|
|
|
.PHONY: print-boards
|
|
print-boards:
|
|
$(call cmd_pretty_print_list,\
|
|
$(sort $(boards)))
|
|
|
|
# Print any important notices at the end of the build.
|
|
.PHONY: notice
|
|
notice: $(config)
|
|
ifeq ($(CONFIG_EXPERIMENTAL_CONSOLE),y)
|
|
ifeq ($(TEST_BUILD),)
|
|
@echo "*** NOTE: The experimental console is ENABLED. ***"
|
|
@echo "You will need to run the EC-3PO interactive console in the util"
|
|
@echo "directory! Otherwise, you won't be able to enter any commands."
|
|
endif # not a TEST_BUILD
|
|
endif # CONFIG_EXPERIMENTAL_CONSOLE=y
|
|
|
|
proj-%: | $(FAILED_BOARDS_DIR)
|
|
@touch $(FAILED_BOARDS_DIR)/$*
|
|
@echo "======= building $*"
|
|
$(MAKE) --no-print-directory BOARD=$* V=$(V)
|
|
@rm $(FAILED_BOARDS_DIR)/$*
|
|
|
|
tests-%:
|
|
@echo "======= building $* tests"
|
|
$(MAKE) --no-print-directory BOARD=$* V=$(V) tests
|
|
|
|
dis-y := $(out)/RW/$(PROJECT).RW.dis
|
|
dis-$(CONFIG_FW_INCLUDE_RO) += $(out)/RO/$(PROJECT).RO.dis
|
|
dis-$(CONFIG_SHAREDLIB) += $(out)/$(SHOBJLIB)/$(SHOBJLIB).dis
|
|
dis: $(dis-y)
|
|
.PHONY: dis
|
|
|
|
hex-y := $(out)/RO/$(PROJECT).RO.hex $(out)/RW/$(PROJECT).RW.hex $(out)/$(PROJECT).hex
|
|
hex-$(CONFIG_RW_B) += $(out)/RW/$(PROJECT).RW_B.hex
|
|
hex: $(hex-y)
|
|
.PHONY: hex
|
|
|
|
.PHONY: utils-art
|
|
utils-art: $(build-art)
|
|
|
|
.PHONY: utils-host
|
|
utils-host: $(host-utils)
|
|
|
|
.PHONY: utils-build
|
|
utils-build: $(build-utils)
|
|
|
|
.PHONY: utils
|
|
utils: utils-host utils-build utils-art
|
|
|
|
# On board test binaries
|
|
test-targets=$(foreach t,$(test-list-y),test-$(t))
|
|
.PHONY: $(test-targets)
|
|
|
|
ifeq "$(CONFIG_COMMON_RUNTIME)" "y"
|
|
$(test-targets): test-%:
|
|
@set -e ; \
|
|
$(call echo," BUILD $(out)/$*") \
|
|
$(MAKE) --no-print-directory BOARD=$(BOARD) PROJECT=$* \
|
|
V=$(V) out=$(out)/$* TEST_BUILD=y; \
|
|
cp $(out)/$*/$*.bin $(out)/test-$*.bin
|
|
endif
|
|
|
|
.PHONY: tests
|
|
tests: $(test-targets)
|
|
|
|
.PHONY: print-tests
|
|
print-tests:
|
|
$(call cmd_pretty_print_list, \
|
|
$(sort $(test-targets)))
|
|
|
|
# Emulator test executables
|
|
host-test-targets=$(foreach t,$(test-list-host),host-$(t))
|
|
run-test-targets=$(foreach t,$(test-list-host),run-$(t))
|
|
.PHONY: $(host-test-targets) $(run-test-targets)
|
|
|
|
$(host-test-targets): host-%: | $(FAILED_BOARDS_DIR)
|
|
@touch $(FAILED_BOARDS_DIR)/test-$*
|
|
+$(call quiet,host_test,BUILD )
|
|
|
|
$(run-test-targets): run-%: host-%
|
|
$(call quiet,run_host_test,TEST )
|
|
@rm -f $(FAILED_BOARDS_DIR)/test-$*
|
|
|
|
.PHONY: print-host-tests
|
|
print-host-tests:
|
|
$(call cmd_pretty_print_list, \
|
|
$(sort $(host-test-targets) $(run-test-targets)))
|
|
|
|
# Fuzzing tests
|
|
|
|
fuzz-test-targets=$(foreach t,$(fuzz-test-list-host),host-$(t))
|
|
run-fuzz-test-targets=$(foreach t,$(fuzz-test-list-host),run-$(t))
|
|
|
|
.PHONY: $(fuzz-test-targets) $(run-fuzz-test-targets)
|
|
|
|
$(fuzz-test-targets): TEST_FLAG=TEST_FUZZ=y TEST_ASAN=$(TEST_ASAN) \
|
|
TEST_MSAN=$(TEST_MSAN) TEST_UBSAN=$(TEST_UBSAN) \
|
|
CROSS_COMPILE=$(shell echo $(HOSTCC) | grep -v ccache | \
|
|
sed -e 's/[^-]*$$//')
|
|
$(fuzz-test-targets): host-%: | $(FAILED_BOARDS_DIR)
|
|
@touch $(FAILED_BOARDS_DIR)/test-$*
|
|
+$(call quiet,host_test,BUILD )
|
|
$(run-fuzz-test-targets): run-%: host-%
|
|
$(call quiet,run_fuzz,TEST )
|
|
@rm -f $(FAILED_BOARDS_DIR)/test-$*
|
|
|
|
$(FAILED_BOARDS_DIR):
|
|
@mkdir $(FAILED_BOARDS_DIR)
|
|
|
|
.PHONY: print-host-fuzzers
|
|
print-host-fuzzers:
|
|
$(call cmd_pretty_print_list, \
|
|
$(sort $(fuzz-test-targets) $(run-fuzz-test-targets)))
|
|
|
|
.PHONY: buildfuzztests
|
|
buildfuzztests: $(fuzz-test-targets)
|
|
|
|
.PHONY: hosttests runhosttests runfuzztests runtests
|
|
hosttests: $(host-test-targets)
|
|
runhosttests: $(run-test-targets)
|
|
runfuzztests: $(run-fuzz-test-targets)
|
|
runtests: runhosttests runfuzztests
|
|
|
|
# Automatically enumerate all suites.
|
|
cts_excludes := common
|
|
cts_suites := $(filter-out $(cts_excludes), \
|
|
$(shell find cts -maxdepth 1 -mindepth 1 -type d -printf "%f "))
|
|
|
|
# Add boards below as CTS is expanded.
|
|
cts_boards := stm32l476g-eval nucleo-f072rb
|
|
|
|
.PHONY: build_cts
|
|
|
|
# Create CTS rule automatically for given suite and board
|
|
# $1: suite name
|
|
# $2: board name
|
|
define make-cts =
|
|
build_cts: cts-$(1)-$(2)
|
|
cts-$(1)-$(2): | $(FAILED_BOARDS_DIR)
|
|
@touch $(FAILED_BOARDS_DIR)/cts-$(2)-$(1)
|
|
$$(MAKE) CTS_MODULE=$(1) BOARD=$(2)
|
|
@rm -f $(FAILED_BOARDS_DIR)/cts-$(2)-$(1)
|
|
# Do not remove this blank line
|
|
|
|
endef
|
|
|
|
# Create rules for all cts-suite-board combinations. Additionally, we serialize
|
|
# targets per board: cts-x-board -> cts-y-board -> ...
|
|
# If we don't serialize targets, parallel make fails because all suites
|
|
# try to produce ec.bin in the same directory (e.g. build/stm32l476g-eval).
|
|
$(foreach b, $(cts_boards), \
|
|
$(foreach s, $(cts_suites), \
|
|
$(eval $(call make-cts,$(s),$(b))) \
|
|
) \
|
|
)
|
|
|
|
cov-test-targets=$(foreach t,$(test-list-host),build/host/$(t).info)
|
|
bldversion=$(shell (./util/getversion.sh ; echo VERSION) | $(CPP) -P -)
|
|
|
|
# lcov fails when multiple instances run at the same time.
|
|
# We need to run them sequentially by using flock
|
|
cmd_lcov=flock /tmp/ec-lcov-lock -c "lcov -q -o $@ -c -d build/host/$*"
|
|
cmd_report_cov=genhtml -q -o build/host/coverage_rpt -t \
|
|
"EC Unittest "$(bldversion) $^
|
|
|
|
# Unless V is set to 0 we always want the 'size:' target to report its output,
|
|
# there is no point in generating a short form command trace when calculating
|
|
# size.
|
|
# $1: 'RO' or 'RW'
|
|
ifeq ($(V),0)
|
|
cmd_size=
|
|
else
|
|
cmd_size=$(Q)awk '\
|
|
/__image_size =/ {image_size = strtonum($$1)} \
|
|
/^FLASH/ {flash_size = strtonum($$3)} \
|
|
/__ram_free =/ {ram_free = strtonum($$1)} \
|
|
END {room_free = flash_size - image_size; \
|
|
print ram_free > "$(out)/$(1)/space_free_ram.txt"; \
|
|
printf " *** "; \
|
|
if (flash_size > 0) { \
|
|
print room_free > "$(out)/$(1)/space_free_flash.txt"; \
|
|
printf ("%s bytes in flash and ", room_free);\
|
|
} \
|
|
printf ("%s bytes in RAM still available on $(BOARD) $(1) ****\n", \
|
|
ram_free) \
|
|
}' $(out)/$(1)/$(PROJECT).$(1).map
|
|
endif
|
|
|
|
# List the smallest free flash spaces
|
|
# $1: 'RO' or 'RW'
|
|
cmd_stats= \
|
|
$(Q)echo "Smallest free spaces in $(1) flash (bytes):"; \
|
|
grep . build/*/$(1)/space_free_flash.txt | \
|
|
sed 's,build/\([^/]*\)/$(1)/space_free_flash.txt:\(.*\)$$,\2 \1,' | \
|
|
sort -n | head -3 | \
|
|
while read size board; do \
|
|
printf "%-10s: %6d\n" $$board $$size; \
|
|
done
|
|
|
|
build/host/%.info: run-%
|
|
$(call quiet,lcov,COV )
|
|
|
|
.PHONY: coverage
|
|
coverage: TEST_FLAG=TEST_COVERAGE=y
|
|
coverage: $(cov-test-targets)
|
|
$(call quiet,report_cov,REPORT )
|
|
|
|
$(out)/libec.a: $(ro-objs)
|
|
$(call quiet,libec,BUILD )
|
|
|
|
$(out)/firmware_image.lds: common/firmware_image.lds.S
|
|
$(call quiet,lds,LDS )
|
|
$(out)/%.lds: core/$(CORE)/ec.lds.S
|
|
$(call quiet,lds,LDS )
|
|
|
|
$(out)/%_B.lds: core/$(CORE)/ec.lds.S
|
|
$(call quiet,lds_b,LDS_B )
|
|
|
|
$(out)/%.bin: $(out)/%.obj
|
|
$(call quiet,obj_to_bin,OBJCOPY)
|
|
$(if $(wildcard $(PEM)),$(call quiet,rsasign,SIGN ),)
|
|
$(if $(wildcard $(PEM)),$(call quiet,extractrw-y,EXTR_RW), \
|
|
$(call quiet,copyrw-y,COPY_RW))
|
|
$(call quiet,mv_from_tmp,MV )
|
|
|
|
$(out)/$(BOARD)_vif.txt: $(out)/util/genvif
|
|
$(call quiet,vif,VIF )
|
|
|
|
flat-y := $(out)/RW/$(PROJECT).RW.flat
|
|
flat-$(CONFIG_FW_INCLUDE_RO) += $(out)/RO/$(PROJECT).RO.flat
|
|
|
|
deps += $(out)/firmware_image.lds.d $(flat-y:%.flat=%.lds.d)
|
|
|
|
flat-$(CONFIG_DRAM_BASE) += $(out)/RW/$(PROJECT).RW.flat.dram
|
|
|
|
flat-$(CONFIG_RWSIG_TYPE_RWSIG) += $(out)/key.vbpubk2
|
|
flat-$(CONFIG_RWSIG_TYPE_RWSIG) += $(out)/RW/$(PROJECT).RW.flat.sig
|
|
|
|
flat-$(CONFIG_SHAREDLIB) += $(libsharedobjs-y)
|
|
|
|
$(out)/$(PROJECT).obj: common/firmware_image.S $(out)/firmware_image.lds \
|
|
$(flat-y)
|
|
$(call quiet,flat_to_obj,CAT )
|
|
|
|
$(out)/%.dis: $(out)/%.elf
|
|
$(call quiet,elf_to_dis,OBJDUMP)
|
|
|
|
$(out)/RW/%.hex: $(out)/RW/%.elf $(out)/RW/%.smap
|
|
$(call quiet,elf_to_hex,OBJCOPY)
|
|
|
|
ifeq ($(SIGNED_IMAGES),)
|
|
$(out)/%.flat: $(out)/%.elf $(out)/%.smap utils-build
|
|
$(call quiet,ec_elf_to_flat,OBJCOPY)
|
|
|
|
$(out)/%.flat.dram: $(out)/%.elf $(out)/%.smap utils-build
|
|
$(call quiet,ec_elf_to_flat_dram,OBJCOPY)
|
|
|
|
$(out)/RO/%.hex: $(out)/RO/%.elf $(out)/RO/%.smap
|
|
$(call quiet,elf_to_hex,OBJCOPY)
|
|
else
|
|
$(out)/RO/%.flat: $(out)/RO/%.elf $(out)/RO/%.smap
|
|
$(call quiet,elf_to_signed,RO_SIGN,$(CR50_RO_KEY))
|
|
|
|
$(out)/RW/%.flat: $(out)/RW/%.elf $(out)/RW/%.smap
|
|
$(call quiet,elf_to_signed,RW_SIGN,$(CR50_RW_KEY))
|
|
|
|
$(out)/RO/%.hex: $(out)/RO/%.flat
|
|
$(call quiet,bin_to_hex,OBJCOPY)
|
|
endif
|
|
$(out)/$(PROJECT).hex: $(out)/$(PROJECT).bin
|
|
$(call quiet,bin_to_hex,OBJCOPY)
|
|
|
|
$(out)/%.vbprik2 $(out)/%.vbpubk2: $(PEM)
|
|
$(call quiet,key_extract,KEY )
|
|
|
|
$(out)/RW/%.flat.sig: $(out)/RW/%.flat $(out)/key.vbprik2
|
|
$(call quiet,rsasign_rwsig,SIGN )
|
|
|
|
$(out)/RW/%.elf: override BLD:=RW
|
|
$(out)/RW/%.elf: private objs := $(rw-objs)
|
|
$(out)/RW/%.elf: $(out)/RW/%.lds $(rw-objs) $(libsharedobjs_elf-y)
|
|
$(call quiet,elf,LD )
|
|
|
|
$(out)/RO/%.elf: override BLD:=RO
|
|
$(out)/RO/%.elf: private objs := $(ro-objs)
|
|
$(out)/RO/%.elf: $(out)/RO/%.lds $(ro-objs) $(libsharedobjs_elf-y)
|
|
$(call quiet,elf,LD )
|
|
|
|
$(out)/%.elf: $(out)/%.lds $(objs)
|
|
$(call quiet,elf,LD )
|
|
|
|
$(out)/$(SHOBJLIB)/$(SHOBJLIB).elf: $(sharedlib-objs)
|
|
@mkdir -p $(out)/$(SHOBJLIB)
|
|
$(call quiet,sharedlib_elf,LD )
|
|
|
|
$(out)/%.smap: $(out)/%.elf
|
|
$(call quiet,smap,NM )
|
|
|
|
ifeq ($(TEST_FUZZ),y)
|
|
$(out)/$(PROJECT).exe: $(rw-only-objs) $(out)/libec.a
|
|
$(call quiet,fuzz_exe,EXE )
|
|
else ifneq ($(TEST_SCRIPT),)
|
|
$(out)/$(PROJECT).exe: test/$(TEST_SCRIPT) | $(ro-objs)
|
|
$(call quiet,cp_script,CP )
|
|
else
|
|
$(out)/$(PROJECT).exe: $(ro-objs)
|
|
$(call quiet,exe,EXE )
|
|
endif
|
|
|
|
$(out)/RO/%.o.cmd:%.c
|
|
$(file > $@,$(subst .o.cmd,.o,$(cmd_c_to_o)))
|
|
$(out)/RO/%.o:%.c
|
|
$(call quiet,c_to_o,CC )
|
|
$(out)/RW/%.o:%.c
|
|
$(call quiet,c_to_o,CC )
|
|
|
|
$(out)/RO/%.o:%.cc
|
|
$(call quiet,cxx_to_o,CXX )
|
|
$(out)/RW/%.o:%.cc
|
|
$(call quiet,cxx_to_o,CXX )
|
|
|
|
$(out)/RO/%.pb.o: CXXFLAGS+= -Wno-unreachable-code
|
|
$(out)/RO/%.pb.o:$(out)/gen/%.pb.cc
|
|
$(call quiet,cxx_to_o,CXX )
|
|
$(out)/RW/%.pb.o: CXXFLAGS+= -Wno-unreachable-code
|
|
$(out)/RW/%.pb.o:$(out)/gen/%.pb.cc
|
|
$(call quiet,cxx_to_o,CXX )
|
|
$(out)/gen/%.pb.cc:%.proto
|
|
$(call quiet,proto_to_cxx,PROTOC )
|
|
$(out)/gen/%.pb.h:%.proto
|
|
$(call quiet,proto_to_cxx,PROTOC )
|
|
|
|
$(out)/$(SHOBJLIB)/%.o: override LATE_CFLAGS_DEFINE:=-DSHAREDLIB_IMAGE=$(EMPTY)
|
|
$(out)/$(SHOBJLIB)/%.o:%.c
|
|
$(call quiet,c_to_o,CC )
|
|
|
|
$(out)/RO/%.o:%.S
|
|
$(call quiet,c_to_o,AS )
|
|
$(out)/RW/%.o:%.S
|
|
$(call quiet,c_to_o,AS )
|
|
|
|
# Default rules for archives, dependencies need to be fixes in build.mk
|
|
$(out)/RO/%.a:
|
|
$(call quiet,o_to_a,AR )
|
|
$(out)/RW/%.a:
|
|
$(call quiet,o_to_a,AR )
|
|
|
|
# Conditionally force the rebuilding of ec_version.h only if it would be
|
|
# changed.
|
|
old_version_hash := $(shell cat $(out)/ec_version.h 2> /dev/null | md5sum -)
|
|
new_version_hash := $(shell BOARD=$(BOARD) ./util/getversion.sh | md5sum -)
|
|
|
|
ifneq ($(old_version_hash),$(new_version_hash))
|
|
.PHONY: $(out)/ec_version.h
|
|
endif
|
|
|
|
# All of the objects have an order only dependency on the ec_version header.
|
|
# This ensures that if ec_version.h needs to be built (because it was marked
|
|
# PHONY above) then it will be rebuilt before any objects. This is important
|
|
# because some source files will include ec_version.h and fail to compile if
|
|
# it doesn't already exist. This dependency shouldn't be a normal dependency
|
|
# because that would cause every object to be rebuilt when ec_version.h
|
|
# changes, instead of just the ones that actually depend on it. The objects
|
|
# that truly depend on ec_version.h will have that information encoded in their
|
|
# .d file.
|
|
$(ro-objs): | $(out)/ec_version.h
|
|
$(rw-objs): | $(out)/ec_version.h
|
|
$(sharedlib-objs): | $(out)/ec_version.h
|
|
|
|
$(out)/ec_version.h:
|
|
$(call quiet,version,VERSION)
|
|
|
|
$(build-utils): $(out)/%:$(build-srcs)
|
|
$(call quiet,c_to_build,BUILDCC)
|
|
|
|
$(host-utils): $(out)/%:$(host-srcs)
|
|
$(call quiet,c_to_host,HOSTCC )
|
|
|
|
$(out)/cscope.files: $(out)/$(PROJECT).bin
|
|
$(call quiet,deps_to_list,SH )
|
|
|
|
$(out)/TAGS: $(out)/cscope.files
|
|
$(call quiet,etags,ETAGS )
|
|
|
|
$(out)/tags: $(out)/cscope.files
|
|
$(call quiet,ctags,CTAGS )
|
|
|
|
# TODO: optional make rules for PROJECT_EXTRA
|
|
$(npcx-monitor-fw-bin):
|
|
$(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; )
|
|
$(Q)mkdir -p $(@D)
|
|
$(Q)$(CC) $(CFLAGS) -MMD -MF $(out)/$(npcx-lfw).d -c $(npcx-monitor-fw).c \
|
|
-o $(out)/$(npcx-monitor-fw).o
|
|
$(Q)$(CC) $(out)/$(npcx-monitor-fw).o $(LDFLAGS) \
|
|
-o $(out)/$(npcx-monitor-fw).elf -Wl,-T,$(npcx-monitor-fw).ld \
|
|
-Wl,-Map,$(out)/$(npcx-monitor-fw).map
|
|
$(Q)$(OBJCOPY) -O binary $(out)/$(npcx-monitor-fw).elf $@
|
|
|
|
$(out)/$(npcx-monitor-hdr)_ro.o:$(npcx-monitor-hdr).c
|
|
$(Q)$(CC) $(CFLAGS) -DSECTION_IS_RO=$(EMPTY) -MMD -c $(npcx-monitor-hdr).c -o $@
|
|
|
|
$(npcx-monitor-hdr-ro-bin):$(out)/$(npcx-monitor-hdr)_ro.o
|
|
$(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; )
|
|
$(Q)$(OBJCOPY) -O binary $< $@
|
|
|
|
$(out)/$(npcx-monitor-hdr)_rw.o:$(npcx-monitor-hdr).c
|
|
$(Q)$(CC) $(CFLAGS) -MMD -c $(npcx-monitor-hdr).c -o $@
|
|
|
|
$(npcx-monitor-hdr-rw-bin):$(out)/$(npcx-monitor-hdr)_rw.o
|
|
$(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; )
|
|
$(Q)$(OBJCOPY) -O binary $< $@
|
|
|
|
.PHONY: xrefs
|
|
xrefs: $(call targ_if_prog,etags,$(out)/TAGS) \
|
|
$(call targ_if_prog,ctags,$(out)/tags)
|
|
|
|
.PHONY: flash
|
|
flash: $(out)/ec.bin
|
|
openocd -c "set BOARD $(BOARD)"\
|
|
-c "set BUILD_DIR $(out)"\
|
|
-f $(BDIR)/openocd-flash.cfg
|
|
|
|
.PHONY: flash_ec
|
|
flash_ec: $(out)/ec.bin
|
|
./util/flash_ec --board $(BOARD) --image $(out)/ec.bin --port $(PORT)
|
|
|
|
.PHONY: flash_dfu
|
|
flash_dfu: $(out)/ec.bin
|
|
sudo ./$(BDIR)/dfu $(out)/ec.bin
|
|
|
|
.PHONY: print-baseboard
|
|
print-baseboard:
|
|
@echo "${BASEBOARD}"
|
|
|
|
.PHONY: print-configs
|
|
print-configs:
|
|
@echo "----------------------------------------------------------------"
|
|
@echo "| RO Config: |"
|
|
@echo "----------------------------------------------------------------"
|
|
@$(CPP) $(CPPFLAGS) -P -dM -Ichip/$(CHIP) -I$(BASEDIR) -I$(BDIR) \
|
|
-DSECTION_IS_RO=$(EMPTY) include/config.h | \
|
|
grep "#define CONFIG_" | cut -c9- | sort
|
|
@echo "----------------------------------------------------------------"
|
|
@echo "| RW Config: |"
|
|
@echo "----------------------------------------------------------------"
|
|
@$(CPP) $(CPPFLAGS) -P -dM -Ichip/$(CHIP) -I$(BASEDIR) -I$(BDIR) \
|
|
-DSECTION_IS_RW=$(EMPTY) include/config.h | \
|
|
grep "#define CONFIG_" | cut -c9- | sort
|
|
|
|
.PHONY: clean
|
|
clean:
|
|
-rm -rf $(out)
|
|
|
|
.PHONY: clobber
|
|
clobber:
|
|
-rm -rf build TAGS cscope.files cscope.out
|
|
ifneq ($(CCACHE),)
|
|
$(CCACHE) -c
|
|
endif
|
|
|
|
.PHONY: help
|
|
help:
|
|
@echo "Google Chromium EC build"
|
|
@echo "Common Targets:"
|
|
@echo " all [BOARD=] - Build a single board (Default target)"
|
|
@echo " clean [BOARD=] - Clean a single board"
|
|
@echo " buildall - Build and test all boards"
|
|
@echo " clobber - Clean all boards"
|
|
@echo " proj-<boardname> - Build a single board (similar to 'all BOARD=boardname')"
|
|
@echo " savesizes - Save the filesizes of currently built boards for comparison"
|
|
@echo " newsizes - Compare previously saved filesizes against new sizes"
|
|
@echo ""
|
|
@echo " tests [BOARD=] - Build all unit tests for a specific board"
|
|
@echo " hosttests - Build all host unit tests"
|
|
@echo " runhosttests - Build and run all host unit tests"
|
|
@echo " buildfuzztests - Build all host fuzzers"
|
|
@echo " runfuzztests - Build and run all host fuzzers for one round"
|
|
@echo ""
|
|
@echo " print-tests - Prints all device specific test targets"
|
|
@echo " print-host-tests - Prints all host test targets"
|
|
@echo " print-host-fuzzers - Prints all host fuzz targets"
|
|
@echo " print-boards - Prints all boards"
|
|
@echo " print-configs [BOARD=] - Print CONFIG_* options for the target board"
|
|
@echo "Common Variables:"
|
|
@echo " V=1 - Show make output"
|
|
@echo " BOARD= - Set the board name to build (Default is $(BOARD))"
|
|
@echo " CROSS_COMPILE= - Set the compiler for the board"
|
|
@echo " CROSS_COMPILE_arch= - Set the compiler for arch"
|
|
@echo " The board picks its CROSS_COMPILE_arch if CROSS_COMPILE is not set."
|
|
@echo " arch may be one of 'arm', 'i386', 'nds32'."
|
|
@echo "Example:"
|
|
@echo " make BOARD=reef CROSS_COMPILE_arm='arm-eabi-'"
|
|
|
|
.PHONY: savesizes
|
|
savesizes:
|
|
@grep . build/*/*/space_free_*.txt | \
|
|
sed 's,\(.*\).txt:\(.*\),\2 \1,' | sort --key 2 > \
|
|
$(FLATSIZE_FILE)
|
|
@if [ -s $(FLATSIZE_FILE) ]; then \
|
|
echo "Saved sizes for $$(cat $(FLATSIZE_FILE) | wc -l) files"; \
|
|
else \
|
|
echo "Error: No file sizes saved. Are they built?"; \
|
|
fi
|
|
|
|
.PHONY: newsizes
|
|
newsizes:
|
|
@if [ ! -s "$(FLATSIZE_FILE)" ]; then \
|
|
echo "Error: no saved size file ($(FLATSIZE_FILE))."; \
|
|
echo " Run 'make savesizes' first"; \
|
|
exit 1; \
|
|
fi
|
|
@FILES_CHANGED=0; \
|
|
FILES_IN_LIST=0; \
|
|
FILES_COMPARED=0; \
|
|
FILE_SIZE_CHANGE=0; \
|
|
NEW_SIZES=$$(grep . build/*/*/space_free_*.txt | \
|
|
sed 's,\(.*\).txt:\(.*\),\2 \1,'); \
|
|
while read -r -u 10 line; do \
|
|
FILES_IN_LIST=$$((FILES_IN_LIST+1)); \
|
|
FLATFILE=$$(echo "$$line" | cut -f2 -d ' '); \
|
|
FLATSIZE_ORG=$$(echo "$$line" | cut -f1 -d ' '); \
|
|
FLATSIZE_NEW="$$(grep "$$FLATFILE" <<< "$$NEW_SIZES" | \
|
|
sed 's/ .*$$//')"; \
|
|
if [ -n "$$FLATSIZE_NEW" ]; then \
|
|
FILES_COMPARED=$$((FILES_COMPARED+1)); \
|
|
if [ "$$FLATSIZE_NEW" -gt "$$FLATSIZE_ORG" ]; then \
|
|
FILES_CHANGED=$$((FILES_CHANGED+1)); \
|
|
FILE_SIZE_CHANGE=$$((FILE_SIZE_CHANGE+ \
|
|
FLATSIZE_NEW-FLATSIZE_ORG)); \
|
|
printf "%s grew by %s bytes: (%d to %d)\n" \
|
|
"$$FLATFILE" \
|
|
"$$((FLATSIZE_NEW-FLATSIZE_ORG))" \
|
|
"$$FLATSIZE_ORG" "$$FLATSIZE_NEW"; \
|
|
elif [ "$$FLATSIZE_NEW" -lt "$$FLATSIZE_ORG" ]; then \
|
|
FILES_CHANGED=$$((FILES_CHANGED+1)); \
|
|
FILE_SIZE_CHANGE=$$((FILE_SIZE_CHANGE+ \
|
|
FLATSIZE_NEW-FLATSIZE_ORG)); \
|
|
printf "%s shrank by %s bytes: (%d to %d)\n" \
|
|
"$$FLATFILE" \
|
|
"$$((FLATSIZE_ORG-FLATSIZE_NEW))" \
|
|
"$$FLATSIZE_ORG" "$$FLATSIZE_NEW"; \
|
|
fi; \
|
|
fi; \
|
|
done 10< "$(FLATSIZE_FILE)"; \
|
|
echo "Compared $$FILES_COMPARED of $$FILES_IN_LIST files."; \
|
|
if [ $$FILES_COMPARED -ne 0 ] && [ $$FILES_CHANGED -eq 0 ]; then \
|
|
echo "File sizes are unchanged."; \
|
|
else \
|
|
printf "%d files changed.\n" "$$FILES_CHANGED"; \
|
|
printf "Total size change: %s bytes.\n" "$$FILE_SIZE_CHANGE"; \
|
|
printf "Average size change: %d bytes.\n" \
|
|
"$$((FILE_SIZE_CHANGE / FILES_CHANGED))"; \
|
|
fi
|
|
|
|
# The reason why don't add elf files as dependencies, but ask users to build
|
|
# them first is because elf dependencies will cause the elf files be rebuilt for
|
|
# updating date, which shouldn't happen when analyzing the existing firmwares.
|
|
.PHONY: analyzestack
|
|
ANNOTATION ?= ./$(BDIR)/analyzestack.yaml
|
|
analyzestack: $(out)/util/export_taskinfo.so
|
|
@if [ "$(SECTION)" != "RO" ] && [ "$(SECTION)" != "RW" ]; then \
|
|
echo "Please specify SECTION=RO or RW. The default is RW."; \
|
|
SECTION="RW"; \
|
|
fi; \
|
|
ELF=$(out)/$$SECTION/ec.$$SECTION.elf; \
|
|
EXPORT_TASKINFO=$(out)/util/export_taskinfo.so; \
|
|
if [ ! -f "$$ELF" ]; then \
|
|
echo "Some files are missing. Are they built?"; \
|
|
exit 1; \
|
|
fi; \
|
|
extra/stack_analyzer/stack_analyzer.py --objdump "$(OBJDUMP)" \
|
|
--addr2line "$(ADDR2LINE)" --section "$$SECTION" \
|
|
--annotation $(ANNOTATION) \
|
|
--export_taskinfo "$$EXPORT_TASKINFO" "$$ELF"
|
|
|
|
# Calculate size of remaining room in flash, using variables generated by
|
|
# linker.
|
|
size: $(out)/$(PROJECT).bin
|
|
ifneq ($(CONFIG_FW_INCLUDE_RO),)
|
|
$(call cmd_size,RO)
|
|
endif
|
|
$(call cmd_size,RW)
|
|
|
|
# Print the smallest spaces in flash
|
|
stats: build_boards
|
|
$(call cmd_stats,RO)
|
|
$(call cmd_stats,RW)
|
|
|
|
.PHONY: build_cros_ec_commands
|
|
build_cros_ec_commands: build/kernel/include/linux/mfd/cros_ec_commands.h
|
|
|
|
build/kernel/include/linux/mfd/cros_ec_commands.h: include/ec_commands.h
|
|
util/make_linux_ec_commands_h.sh $< $@
|
|
|
|
.SECONDARY:
|
|
|
|
-include $(deps)
|