# -*- 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 # FLATSIZE_FILE ?= .sizes.txt 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); 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) # 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_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,$@) -flto-partition=one 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 $< \ -MT $(@D)/$(@F) -o $(@D)/$(@F) cmd_cxx_to_o = $(CXX) -std=c++11 $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $@.d -c $< \ -MT $(@D)/$(@F) -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 -MT $@ -o $@ cmd_c_to_vif = $(BUILDCC) $(BUILD_CFLAGS) $(STANDALONE_FLAGS) \ -MMD -MF $@.d -c $< -flto -MT $@ -o $@ 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++17 $(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 CROSS_COMPILE= \ $(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_vif = $(out)/util/genvif -b $(BOARD) -o $(out) \ -v board/$(BOARD)/vif_override.xml 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 -MT $@ -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 \ -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_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 # 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_only buildall_only: build_boards .PHONY: buildall buildall: buildall_only @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: 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 # TODO(b/195718112): Disable config option check as it's # suspected to be breaking the CQ. We should consider enabling # as a pre-submit only when re-enabling. # $(call quiet,check_allowed) proj-%: | $(FAILED_BOARDS_DIR) @touch $(FAILED_BOARDS_DIR)/$* @echo "======= building $*" $(MAKE) BOARD=$* V=$(V) @rm $(FAILED_BOARDS_DIR)/$* tests-%: @echo "======= building $* tests" $(MAKE) 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 # 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 '\ /__flash_used =/ {flash_used = strtonum($$1)} \ /^FLASH / {flash_size = strtonum($$3)} \ /__ram_free =/ {ram_free = strtonum($$1)} \ END {room_free = flash_size - flash_used; \ 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 $(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.xml: $(out)/util/genvif board/$(BOARD)/vif_override.xml $(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 $(build-utils) $(call quiet,ec_elf_to_flat,OBJCOPY) $(out)/%.flat.dram: $(out)/%.elf $(out)/%.smap $(build-utils) $(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) $(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 ) .PHONY: xrefs xrefs: $(call targ_if_prog,etags,$(out)/TAGS) \ $(call targ_if_prog,ctags,$(out)/tags) # Print variables identifying and providing Makefile-specific # configuration for each board. The format is one variable per line, # in the format KEY=VALUE. .PHONY: print-make-vars print-make-vars: @echo "BASEBOARD=${BASEBOARD}" @echo "CHIP=${CHIP}" @echo "CHIP_FAMILY=${CHIP_FAMILY}" @echo "CHIP_VARIANT=${CHIP_VARIANT}" @echo "CORE=${CORE}" .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: print-defines print-defines: BLD ?= RW print-defines: $(call cmd_pretty_print_cmd,echo $(CFLAGS) | tr '[:space:]' '\n' | \ sort -u | grep -- '^-D' | sed 's/^-D//' | sed 's/=$$//') .PHONY: print-includes print-includes: $(call cmd_pretty_print_cmd,echo $(CFLAGS) | tr '[:space:]' '\n' | \ sort -u | grep -- '^-I' | sed 's/^-I//') .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 "" @echo "Common Targets:" @echo " all [BOARD=] - Build a single board (Default target)" @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- - 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 " utils [BOARD=] - Build all host side utilities" @echo " dis [BOARD=] - Generate the complete disassembly of the RO and RW images" @echo " hex [BOARD=] - Generate an Intel hex formated output binary" @echo "" @echo " tests [BOARD=] - Build all on-device unit tests for a specific board" @echo " hosttests - Build all host unit tests" @echo " runhosttests - Build and run all host unit tests" @echo " coverage - Build and run all host unit tests for code coverage" @echo " buildfuzztests - Build all host fuzzers" @echo " runfuzztests - Build and run all host fuzzers for one round" @echo " analyzestack [BOARD=]- Run max stack size analysis" @echo "" @echo " flash [BOARD=] - Use OpenOCD to flash the latest image" @echo " flash_ec [BOARD=] - Use flash_ec to flash the latest image" @echo " flash_dfu [BOARD=] - Use DFU to flash the latest image" @echo "" @echo " print-tests [BOARD=] - Print on-device test targets" @echo " print-host-tests - Print all host unit test targets" @echo " print-host-fuzzers - Print all host fuzz targets" @echo " print-boards - Print all boards" @echo " print-configs [BOARD=] - Print CONFIG_* options for the target board" @echo " print-defines [BOARD=] - Print forced defines passed to the compiler" @echo " print-includes [BOARD=] - Print include paths passed to the compiler" @echo " print-baseboard [BOARD=] - Print include paths passed to the compiler" @echo " print-make-vars [BOARD=] - Print chip/core/board make variables for a board" @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 " 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-'" .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) 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)