blob: 95788c3ab12b763a96378a869a9017f7d1fe97d5 [file]
# -*- makefile -*-
# vim: set filetype=make :
# Copyright 2012 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 - common targets
#
BUILD_DIR := $(firstword $(subst /, ,$(out)))
# Don't do a build test on the following boards:
skip_boards = OWNERS cr50 host
boards := $(filter-out $(skip_boards), \
$(notdir $(wildcard board/* ../private*/board/*)))
# Create output directories if necessary
_common_dir_create := $(foreach d,$(common_dirs) $(common-dirs-y),\
$(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)))
# 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)
# V=0
Q := @
echo = echo -n;
quiet = echo -n; $(cmd_$(1))
silent = 1>/dev/null
silent_err = 2>/dev/null
MAKEFLAGS += --no-print-directory
else ifeq ($(V),)
# V=
Q := @
echo = echo $(1);
echo-cmd = $(if $(quiet_cmd_$(1)), \
$(quiet_cmd_$(1)), \
$(2) $(patsubst $(out)/%,%,$@))
quiet = @echo ' $(echo-cmd)' ; $(cmd_$(1))
silent = 1>/dev/null
silent_err = 2>/dev/null
MAKEFLAGS += --no-print-directory
else
# V=*
Q :=
echo = echo $(1);
quiet = $(cmd_$(1))
endif
# Provide an option to use a consistent ec_version.h file when
# compiling, which is useful to verify that a commit does not modify
# the resulting ec.bin
export STATIC_VERSION
# Commonly used compiler options used in these scripts
#
# -MT explicitly sets target file name in generated .d files to work around
# a ccache issue.
# commands to build all targets
cmd_exe = $(CXX) $(ro-objs) $(HOST_TEST_LDFLAGS) $(LDFLAGS_EXTRA) -o $@
cmd_c_to_o = $(CC) -std=gnu11 $(C_WARN) $(C_WARN-$(CROSS_COMPILE_CC_NAME)) \
$(CFLAGS) -MMD -MP -MF $@.d -c $< \
-MT $(@D)/$(@F) -o $(@D)/$(@F)
cmd_c_to_s = $(CC) -S $(C_WARN) $(CFLAGS) $(C_WARN-$(CROSS_COMPILE_CC_NAME)) \
-fno-lto -MMD -MP -MF $@.d -c $< \
-MT $(@D)/$(@F) -o $(@D)/$(@F)
cmd_cxx_to_o = $(CXX) -std=gnu++2a $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $@.d \
-c $< -MT $(@D)/$(@F) -o $(@D)/$(@F)
cmd_c_to_host = $(HOSTCC) $(HOST_CFLAGS) -MMD -MF $@.d -MT $@ -o $@ \
$(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.c)) $(wildcard $*.c)) $(HOST_LDFLAGS)
cmd_cxx_to_host = $(HOSTCXX) -std=gnu++2a $(HOST_CXXFLAGS) \
-MMD -MF $@.d -MT $@ -o $@ \
$(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.cc)) $(wildcard $*.cc)) $(HOST_LDFLAGS)
cmd_o_to_a = $(AR) rcs $@ $^
cmd_host_test = $(MAKE) BOARD=host PROJECT=$* \
V=$(V) out=build/host/$* TEST_BUILD=y EMU_BUILD=y \
$(if $(TEST_SCRIPT),TEST_SCRIPT=$(TEST_SCRIPT)) $(TEST_FLAG) \
build/host/$*/$*.exe
cmd_coverage_test = $(subst build/host,build/coverage,$(cmd_host_test))
cmd_run_host_test = ./util/run_host_test $* $(silent)
cmd_run_coverage_test = ./util/run_host_test --coverage $* $(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_mv_from_tmp = mv $(out)/$*.bin.tmp $(out)/$*.bin
cmd_copyrw-y = cd $(out) && cp RW/$(PROJECT).RW.flat RW/$(PROJECT).RW.bin
cmd_cp_script = cp "$<" "$@" && chmod +x "$@"
# If outputing to tty and column command exists, pipe into column.
# Otherwise, print in newline format.
cmd_pretty_print_cmd = @$(1) \
| { [ -t 1 ] \
&& which column 1>/dev/null 2>&1 \
&& column || cat ; }
cmd_pretty_print_list = $(call cmd_pretty_print_cmd,echo $(1) | tr ' ' '\n')
# 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
tests-%:
@echo "======= building $* tests"
$(MAKE) BOARD=$* V=$(V) tests
.PHONY: utils-host
ifeq ($(BOARD),host)
utils-host: $(host-utils) $(host-utils-cxx)
else
utils-host:
$(error Building utils-host not supported when BOARD is not "host")
endif
# 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) 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-$*
host-coverage-targets=$(foreach t,$(test-list-host),host-coverage-$(t))
run-coverage-targets=$(foreach t,$(test-list-host),run-coverage-$(t))
.PHONY: $(host-coverage-targets) $(run-coverage-targets)
$(host-coverage-targets): host-coverage-%: | $(FAILED_BOARDS_DIR)
@touch $(FAILED_BOARDS_DIR)/test-$*
+$(call quiet,coverage_test,BUILD )
$(run-coverage-targets): run-coverage-%: host-coverage-%
$(call quiet,run_coverage_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)))
$(FAILED_BOARDS_DIR):
@mkdir $(FAILED_BOARDS_DIR)
cov-test-targets=$(foreach t,$(cov-test-list-host),build/coverage/$(t).info)
bldversion=$(shell (./util/getversion.sh ; echo VERSION) | $(CPP) -P -)
cmd_lcov=lcov --rc branch_coverage=1 --gcov-tool \
$(HOSTGCOV) -q -o $@ -c -d build/coverage/$* -t $* \
--exclude '*/ec/test/*' --exclude '*/ec/include/tests/*' \
--exclude '*/ec/common/mock/*' \
--ignore-errors unused,unused,inconsistent,inconsistent \
--ignore-errors negative,negative
cmd_merge_cov=lcov --rc branch_coverage=1 -o build/coverage/lcov.info \
$(foreach info,$^,-a ${info})
.DELETE_ON_ERROR: build/coverage/%.info
build/coverage/%.info: run-coverage-%
$(call quiet,lcov,COV )
.PHONY: test-coverage
test-coverage: TEST_FLAG=TEST_COVERAGE=y
test-coverage: $(cov-test-targets)
$(call quiet,merge_cov,MERGE )
$(out)/%.bin: $(out)/%.obj
$(call quiet,obj_to_bin,OBJCOPY)
$(call quiet,copyrw-y,COPY_RW)
$(call quiet,mv_from_tmp,MV )
flat-y := $(out)/RW/$(PROJECT).RW.flat
flat-$(CONFIG_FW_INCLUDE_RO) += $(out)/RO/$(PROJECT).RO.flat
flat-$(CONFIG_DRAM_BASE) += $(out)/RW/$(PROJECT).RW.flat.dram
flat-$(CONFIG_SHAREDLIB) += $(libsharedobjs-y)
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/%.s:%.c
$(call quiet,c_to_s,CC )
$(out)/RW/%.s:%.c
$(call quiet,c_to_s,CC )
$(out)/RO/%.o:%.cc
$(call quiet,cxx_to_o,CXX )
$(out)/RW/%.o:%.cc
$(call quiet,cxx_to_o,CXX )
$(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)
$(host-utils): $(out)/%:$(host-srcs)
$(call quiet,c_to_host,HOSTCC )
$(host-utils-cxx): $(out)/%:$(host-srcs-cxx)
$(call quiet,cxx_to_host,HOSTCXX )
.PHONY: clean
clean:
-rm -rf $(out) build/Makefile.sdk
.PHONY: clobber
clobber:
-rm -rf build
ifneq ($(CCACHE),)
$(CCACHE) -C
endif
.PHONY: help
help:
@echo "Google Chromium EC build"
@echo ""
@echo "Common Targets:"
@echo " clean [BOARD=] - Clean a single board"
@echo " buildall - Build all boards and build/run host unit tests"
@echo " buildall_only - Build all boards and host unit tests"
@echo " build_boards - Build all boards"
@echo " clobber - Clean all boards"
@echo " proj-<boardname> - Build a single board (similar to 'all BOARD=boardname')"
@echo ""
@echo " tests [BOARD=] - Build all on-device unit tests for a specific board"
@echo " test-coverage - Build and run all host unit tests for code coverage"
@echo ""
@echo " print-tests [BOARD=] - Print on-device test targets"
@echo " print-host-tests - Print all host unit test targets"
@echo ""
@echo "Common Variables:"
@echo " V=1 - Show make output"
@echo " BOARD= - Set the board name to build (Default is $(BOARD))"
@echo " STATIC_VERSION=1 - Force a constant version string for reproducable builds"
@echo " BUILDCC_PREFIX= - Set the compiler prefix for the system doing "
@echo " the build (defaults to 'x86_64-pc-linux-gnu-')."
@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 " HOST_CROSS_COMPILE= - Set the compiler for the target platform on top of"
@echo " the EC. For example, this may be 32-bit x86 linux ('i686-pc-linux-gnu-'),"
@echo " 64-bit x86 linux ('x86_64-pc-linux-gnu-'), or maybe 64-bit ARM linux"
@echo " ('aarch64-cros-linux-gnu-')."
@echo "Example:"
@echo " make BOARD=reef CROSS_COMPILE_arm='arm-eabi-'"
out_cros_ec_commands=build/kernel/include/linux/mfd/cros_ec_commands.h
.PHONY: build_cros_ec_commands
build_cros_ec_commands: $(out_cros_ec_commands)
$(out_cros_ec_commands): include/ec_commands.h util/make_linux_ec_commands_h.sh
util/make_linux_ec_commands_h.sh $< $@
# Pull in special rules/targets for third_party software
-include third_party/rules.mk
.SECONDARY:
-include $(deps)
.PHONY: get_sdk
get_sdk:
ifneq ($(BAZEL_SUPPORTED),)
declare -A toolchain_dict=($(shell ./util/coreboot_sdk.py)) ; \
rm -rf build/Makefile.sdk ; \
for key in "$${!toolchain_dict[@]}"; do \
echo "export $${key} := $${toolchain_dict[$${key}]}" >> build/Makefile.sdk ; \
done
sync
endif