| # Copyright 2013 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| # This Makefile normally builds in a 'build' subdir, but use |
| # |
| # make BUILD=<dir> |
| # |
| # to put the output somewhere else. |
| |
| ############################################################################## |
| # Configuration variables come first. |
| |
| # We should only run pwd once, not every time we refer to ${BUILD}. |
| SRCDIR := $(shell pwd) |
| BUILD = ${SRCDIR}/build |
| export BUILD |
| LIBAVB_SRCDIR ?= ../../aosp/external/avb/ |
| |
| # Stuff for 'make install' |
| INSTALL = install |
| DESTDIR = / |
| LIBDIR ?= lib |
| |
| # Where exactly do the pieces go? |
| UB_DIR=${DESTDIR}/usr/bin |
| UL_DIR=${DESTDIR}/usr/${LIBDIR} |
| ULP_DIR=${UL_DIR}/pkgconfig |
| UI_DIR=${DESTDIR}/usr/include/vboot |
| US_DIR=${DESTDIR}/usr/share/vboot |
| DF_DIR=${DESTDIR}/etc/default |
| VB_DIR=${US_DIR}/bin |
| DUT_TEST_DIR=${US_DIR}/tests |
| |
| # Where to install the (exportable) executables for testing? |
| TEST_INSTALL_DIR = ${BUILD}/install_for_test |
| |
| # Set when installing into the SDK instead of building for a board sysroot. |
| SDK_BUILD ?= |
| |
| # Verbose? Use V=1 |
| ifeq ($(filter-out 0,${V}),) |
| Q := @ |
| endif |
| |
| # Quiet? Use QUIET=1 |
| ifeq ($(filter-out 0,${QUIET}),) |
| PRINTF := printf |
| else |
| PRINTF := : |
| endif |
| |
| # ARCH and/or FIRMWARE_ARCH are defined by the ChromiumOS ebuild. |
| ifeq (${ARCH},) |
| ARCH := $(shell uname -m) |
| endif |
| |
| ifeq (${ARCH},armv7l) |
| override ARCH := arm |
| else ifeq (${ARCH},aarch64) |
| override ARCH := arm64 |
| else ifeq (${ARCH},i386) |
| override ARCH := x86 |
| else ifeq (${ARCH},i686) |
| override ARCH := x86 |
| else ifeq (${ARCH},amd64) |
| override ARCH := x86_64 |
| endif |
| |
| ifneq (,$(filter arm arm64,${ARCH})) |
| ARCH_DIR := arm |
| else ifneq (,$(filter x86 x86_64,${ARCH})) |
| ARCH_DIR := x86 |
| else |
| ARCH_DIR := stub |
| endif |
| |
| # Compiler flags |
| DEBUG_FLAGS := $(if $(filter-out 0,${DEBUG}),-g -Og,-Os) |
| WERROR := -Werror |
| FIRMWARE_FLAGS := -nostdinc -ffreestanding -fno-builtin -fno-stack-protector |
| COMMON_FLAGS := -pipe ${WERROR} -Wall -Wstrict-prototypes -Wtype-limits \ |
| -Wundef -Wmissing-prototypes -Wno-trigraphs -Wredundant-decls -Wshadow \ |
| -Wwrite-strings -Wstrict-aliasing -Wdate-time \ |
| -Wint-conversion -ffunction-sections -fdata-sections \ |
| -Wformat -Wno-format-security -std=gnu11 ${DEBUG_FLAGS} ${CPPFLAGS} |
| |
| # test_ccflag |
| # $(1): compiler flags to test |
| # $(2): code to insert into test snippet |
| # returns: $(1) if compiler was successful, empty string otherwise |
| test_ccflag = $(shell \ |
| printf "$(2)\nvoid _start(void) {}\n" | \ |
| $(CC) -nostdlib -Werror $(1) -xc -c - -o /dev/null \ |
| >/dev/null 2>&1 && echo "$(1)") |
| |
| COMMON_FLAGS += $(call test_ccflag,-Wimplicit-fallthrough) |
| COMMON_FLAGS += $(call test_ccflag,-Wno-address-of-packed-member) |
| COMMON_FLAGS += $(call test_ccflag,-Wno-unknown-warning) |
| COMMON_FLAGS += $(call test_ccflag,-Wincompatible-function-pointer-types) |
| |
| TEST_FLAGS := $(call test_ccflag,-Wno-address-of-packed-member) |
| |
| # FIRMWARE_ARCH is only defined by the ChromiumOS ebuild if compiling |
| # for a firmware target (coreboot or depthcharge). It must map to the same |
| # consistent set of architectures as the host. |
| ifeq (${FIRMWARE_ARCH},i386) |
| override FIRMWARE_ARCH := x86 |
| else ifeq (${FIRMWARE_ARCH},amd64) |
| override FIRMWARE_ARCH := x86_64 |
| else ifneq ($(filter arm64 armv7 armv8 armv8_64,${FIRMWARE_ARCH}),) |
| override FIRMWARE_ARCH := arm |
| endif |
| |
| ifeq (${FIRMWARE_ARCH},arm) |
| CC ?= armv7a-cros-linux-gnueabihf-gcc |
| CFLAGS ?= -march=armv5 -fno-common -ffixed-r8 -mfloat-abi=hard -marm \ |
| -mabi=aapcs-linux -mno-thumb-interwork ${FIRMWARE_FLAGS} ${COMMON_FLAGS} |
| else ifeq (${FIRMWARE_ARCH},x86) |
| CC ?= i686-pc-linux-gnu-gcc |
| CFLAGS ?= -fvisibility=hidden -fomit-frame-pointer \ |
| -fno-toplevel-reorder -fno-dwarf2-cfi-asm -mpreferred-stack-boundary=2 \ |
| ${FIRMWARE_FLAGS} ${COMMON_FLAGS} |
| else ifeq (${FIRMWARE_ARCH},x86_64) |
| CFLAGS ?= ${FIRMWARE_FLAGS} ${COMMON_FLAGS} -fvisibility=hidden \ |
| -fomit-frame-pointer |
| else ifeq (${FIRMWARE_ARCH},riscv) |
| CC ?= riscv64-linux-gnu-gcc |
| else ifeq (${FIRMWARE_ARCH},mock) |
| FIRMWARE_STUB := 1 |
| CFLAGS += ${TEST_FLAGS} |
| else ifneq (${FIRMWARE_ARCH},) |
| $(error Unexpected FIRMWARE_ARCH ${FIRMWARE_ARCH}) |
| else |
| # FIRMWARE_ARCH not defined; assuming local compile. |
| FIRMWARE_STUB := 1 |
| CC ?= gcc |
| CFLAGS += -DCHROMEOS_ENVIRONMENT ${COMMON_FLAGS} |
| endif |
| |
| LDFLAGS += -Wl,--gc-sections |
| LDLIBS += -ldl |
| |
| ifneq ($(filter-out 0,${DEBUG})$(filter-out 0,${TEST_PRINT}),) |
| CFLAGS += -DVBOOT_DEBUG |
| endif |
| |
| ifneq ($(filter-out 0,${NDEBUG}),) |
| CFLAGS += -DNDEBUG |
| endif |
| |
| ifneq ($(filter-out 0,${TPM2_MODE}),) |
| CFLAGS += -DTPM2_MODE |
| endif |
| |
| # Enable EC early firmware selection. |
| ifneq ($(filter-out 0,${EC_EFS}),) |
| CFLAGS += -DEC_EFS=1 |
| else |
| CFLAGS += -DEC_EFS=0 |
| endif |
| |
| # Some tests need to be disabled when using mocked_secdata_tpm. |
| ifneq ($(filter-out 0,${MOCK_TPM}),) |
| CFLAGS += -DMOCK_TPM |
| endif |
| |
| # EXTERNAL_TPM_CLEAR_REQUEST indicates whether we want to use the external |
| # tpm_clear_request tool or not. |
| ifneq ($(filter-out 0,${EXTERNAL_TPM_CLEAR_REQUEST}),) |
| CFLAGS += -DEXTERNAL_TPM_CLEAR_REQUEST=1 |
| else |
| CFLAGS += -DEXTERNAL_TPM_CLEAR_REQUEST=0 |
| endif |
| |
| # Configurable temporary directory for host tools |
| VBOOT_TMP_DIR := /tmp |
| CFLAGS += -DVBOOT_TMP_DIR=\"${VBOOT_TMP_DIR}\" |
| |
| # Directory used by crossystem to create a lock file |
| CROSSYSTEM_LOCK_DIR := /run/lock |
| CFLAGS += -DCROSSYSTEM_LOCK_DIR=\"${CROSSYSTEM_LOCK_DIR}\" |
| |
| PC_IN_FILES = vboot_host.pc.in |
| |
| # Create / use dependency files |
| CFLAGS += -MMD -MF $@.d |
| |
| ifeq (${FIRMWARE_ARCH},) |
| CFLAGS += -fPIC |
| endif |
| |
| CFLAGS += -D_GNU_SOURCE |
| |
| # This is required to access large disks and files on 32-bit systems, |
| # but if the environment doesn't support it, at least compile support |
| # for what is possible. |
| # Pass through cflags_use_64bits to evaluate it only once, here. |
| HASH_CONST := \# |
| cflags_use_64bits := $(call test_ccflag,$\ |
| -D_FILE_OFFSET_BITS=64,$\ |
| ${HASH_CONST}include <fts.h>) |
| CFLAGS += $(cflags_use_64bits) |
| |
| # Code coverage |
| ifneq ($(filter-out 0,${COV}),) |
| COV_FLAGS = -Og --coverage -DCOVERAGE |
| CFLAGS += ${COV_FLAGS} |
| LDFLAGS += ${COV_FLAGS} |
| COV_INFO = ${BUILD}/coverage.info |
| endif |
| |
| ifdef HAVE_MACOS |
| CFLAGS += -DHAVE_MACOS -Wno-deprecated-declarations |
| endif |
| |
| # Musl doesn't have execinfo.h. |
| ifndef HAVE_MUSL |
| CFLAGS += -DHAVE_EXECINFO_H |
| endif |
| |
| LD = ${CC} |
| CXX ?= g++ |
| PKG_CONFIG ?= pkg-config |
| |
| ifneq ($(filter-out 0,${STATIC}),) |
| LDFLAGS += -static |
| PKG_CONFIG += --static |
| endif |
| |
| ifneq (${FUZZ_FLAGS},) |
| CFLAGS += ${FUZZ_FLAGS} |
| endif |
| |
| # Optional Libraries |
| LIBZIP_VERSION := $(shell ${PKG_CONFIG} --modversion libzip 2>/dev/null) |
| HAVE_LIBZIP := $(if ${LIBZIP_VERSION},1) |
| ifneq ($(filter-out 0,${HAVE_LIBZIP}),) |
| CFLAGS += -DHAVE_LIBZIP $(shell ${PKG_CONFIG} --cflags libzip) |
| LIBZIP_LIBS := $(shell ${PKG_CONFIG} --libs libzip) |
| endif |
| |
| LIBARCHIVE_VERSION := $(shell ${PKG_CONFIG} --modversion libarchive 2>/dev/null) |
| HAVE_LIBARCHIVE := $(if ${LIBARCHIVE_VERSION},1) |
| ifneq ($(filter-out 0,${HAVE_LIBARCHIVE}),) |
| CFLAGS += -DHAVE_LIBARCHIVE $(shell ${PKG_CONFIG} --cflags libarchive) |
| LIBARCHIVE_LIBS := $(shell ${PKG_CONFIG} --libs libarchive) |
| endif |
| |
| HAVE_CROSID := $(shell ${PKG_CONFIG} --exists crosid && echo 1) |
| ifeq ($(HAVE_CROSID),1) |
| CFLAGS += -DHAVE_CROSID $(shell ${PKG_CONFIG} --cflags crosid) |
| CROSID_LIBS := $(shell ${PKG_CONFIG} --libs crosid) |
| endif |
| |
| HAVE_NSS := $(shell ${PKG_CONFIG} --exists nss && echo 1) |
| ifeq ($(HAVE_NSS),1) |
| CFLAGS += -DHAVE_NSS $(shell ${PKG_CONFIG} --cflags nss) |
| else |
| $(warning Missing NSS. PKCS11 signing not supported. Install libnss3 to enable this feature.) |
| endif |
| |
| # Get major version of openssl (e.g. version 3.0.5 -> "3") |
| OPENSSL_VERSION := $(shell ${PKG_CONFIG} --modversion openssl | cut -d. -f1) |
| |
| # A test wrapper can be specified. Tests are run inside the wrapper eg: |
| # make RUNTEST=env runtests |
| RUNTEST = |
| |
| # The Path to the $BUILD inside the runtest wrapper, used by the test scripts. |
| # The top of the chroot for RUNTEST must be passed in via the SYSROOT |
| # environment variable. In the ChromiumOS chroot, this is done automatically by |
| # the ebuild. |
| export BUILD_RUN = $(subst ${SYSROOT},,${BUILD}) |
| # Path to the $SRCDIR inside the wrapper, the test scripts rederive this. |
| SRC_RUN = $(subst ${SYSROOT},,${SRCDIR}) |
| |
| INCLUDES += \ |
| -Ifirmware/include \ |
| -Ifirmware/lib/include \ |
| -Ifirmware/lib/cgptlib/include \ |
| -Ifirmware/lib/tpm_lite/include \ |
| -Ifirmware/2lib/include |
| |
| ifneq (${FIRMWARE_STUB},) |
| INCLUDES += -Ihost/include -Ihost/lib/include -Ihost/lib21/include |
| ifeq ($(shell uname -s), OpenBSD) |
| INCLUDES += -I/usr/local/include |
| endif |
| endif |
| |
| CRYPTO_LIBS := $(shell ${PKG_CONFIG} --libs libcrypto) |
| ifeq ($(shell uname -s), FreeBSD) |
| CRYPTO_LIBS += -lcrypto |
| endif |
| ifeq ($(shell uname -s), OpenBSD) |
| LDFLAGS += -Wl,-z,notext |
| endif |
| |
| ############################################################################## |
| # Subdirectory inclusion |
| |
| SUBMODULES = firmware host cgpt utility futility tests scripts |
| |
| # Initial empty definitions for common accumulation variables |
| ALL_OBJS = |
| ALL_DEPS = |
| TEST_OBJS = |
| TEST_DEPS = |
| FWLIB_OBJS = |
| TLCL_OBJS = |
| UTILLIB_OBJS = |
| HOSTLIB_OBJS = |
| CGPT_OBJS = |
| FUTIL_OBJS = |
| LIBS = |
| OBJS = |
| COMMONLIB_SRCS = |
| FWLIB_ASMS = |
| FWLIB_SRCS = |
| TLCL_SRCS = |
| TESTLIB_SRCS = |
| |
| # Include sub-makefiles only if they exist (for external projects like libpayload) |
| include $(foreach m,${SUBMODULES},$(wildcard $(m)/Makefile.inc)) |
| |
| ############################################################################## |
| # High-level targets |
| |
| .PHONY: all |
| all: fwlib futil utillib hostlib cgpt tlcl util_files \ |
| $(if $(filter x86_64,${ARCH}),$(if $(filter clang,${CC}),fuzzers)) \ |
| $(if $(filter-out 0,${COV}),coverage) |
| |
| .PHONY: clean |
| clean: |
| ${Q}/bin/rm -rf "${BUILD}" |
| |
| .PHONY: install |
| install: cgpt_install signing_install futil_install pc_files_install \ |
| lib_install $(if ${SDK_BUILD},,util_install_defaults) \ |
| $(foreach f,$(if ${SDK_BUILD},${UTIL_FILES_SDK},${UTIL_FILES_BOARD}), \ |
| util_install-$(patsubst ${BUILD}/%,%,${f})) |
| |
| .PHONY: install_dev |
| install_dev: devkeys_install headers_install |
| |
| .PHONY: install_for_test |
| install_for_test: override DESTDIR = ${TEST_INSTALL_DIR} |
| install_for_test: test_setup install \ |
| $(foreach f,${UTIL_FILES_SDK} ${UTIL_FILES_BOARD}, \ |
| util_install-$(patsubst ${BUILD}/%,%,${f})) |
| |
| .PHONY: util_files |
| util_files: $(if ${SDK_BUILD},${UTIL_FILES_SDK},${UTIL_FILES_BOARD}) |
| |
| .PHONY: fwlib |
| fwlib: $(if ${FIRMWARE_ARCH},${FWLIB},) |
| |
| .PHONY: futil |
| futil: ${FUTIL_BIN} |
| |
| .PHONY: test_setup |
| test_setup:: cgpt ${UTIL_FILES_SDK} ${UTIL_FILES_BOARD} futil tests |
| |
| .SECONDARY: |
| |
| ############################################################################## |
| # Generic build rules |
| |
| ${BUILD}/%: ${BUILD}/%.o ${OBJS} ${LIBS} |
| @${PRINTF} " LD $(subst ${BUILD}/,,$@)\n" |
| ${Q}${LD} -o $@ ${LDFLAGS} $< ${OBJS} ${LIBS} ${LDLIBS} |
| |
| ${BUILD}/%.o: %.c |
| @${PRINTF} " CC $(subst ${BUILD}/,,$@)\n" |
| ${Q}mkdir -p $(dir $@) |
| ${Q}${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< |
| |
| ${BUILD}/%.o: ${BUILD}/%.c |
| @${PRINTF} " CC $(subst ${BUILD}/,,$@)\n" |
| ${Q}mkdir -p $(dir $@) |
| ${Q}${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< |
| |
| ${BUILD}/%.o: %.S |
| @${PRINTF} " CC $(subst ${BUILD}/,,$@)\n" |
| ${Q}mkdir -p $(dir $@) |
| ${Q}${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< |
| |
| ############################################################################## |
| # Other targets |
| .PHONY: devkeys_install |
| devkeys_install: |
| @${PRINTF} " INSTALL DEVKEYS\n" |
| ${Q}mkdir -p ${US_DIR}/devkeys |
| ${Q}${INSTALL} -t ${US_DIR}/devkeys -m 644 \ |
| `find tests/devkeys -type f -maxdepth 1` |
| |
| # Code coverage |
| .PHONY: coverage |
| ifeq ($(filter-out 0,${COV}),) |
| coverage: |
| $(error Build coverage like this: make clean && COV=1 make coverage) |
| else |
| .PHONY: coverage_init |
| coverage_init: install_for_test |
| rm -f ${COV_INFO}* |
| lcov -c -i -d . -b . -o ${COV_INFO}.initial |
| |
| .PHONY: coverage_html |
| coverage_html: coverage_init runtests |
| lcov -c -d . -b . -o ${COV_INFO}.tests |
| lcov -a ${COV_INFO}.initial -a ${COV_INFO}.tests -o ${COV_INFO}.total |
| lcov -r ${COV_INFO}.total '/usr/*' -o ${COV_INFO}.local |
| genhtml ${COV_INFO}.local -o ${BUILD}/coverage |
| lcov -r ${COV_INFO}.local '*/stub/*' -o ${COV_INFO}.nostub |
| lcov -e ${COV_INFO}.nostub '${SRCDIR}/firmware/*' -o ${COV_INFO}.firmware |
| |
| coverage: coverage_init runtests coverage_html |
| endif |
| |
| # Dependencies |
| ALL_DEPS += ${ALL_OBJS:%.o=%.o.d} |
| TEST_DEPS += ${TEST_OBJS:%.o=%.o.d} |
| -include ${ALL_DEPS} |
| -include ${TEST_DEPS} |
| |
| # Tags and symbols |
| SRCDIRPAT=$(subst /,\/,${SRCDIR}/) |
| ${BUILD}/cscope.files: all install_for_test |
| ${Q}rm -f $@ |
| ${Q}cat ${ALL_DEPS} | tr -d ':\\' | tr ' ' '\012' | \ |
| sed -e "s/${SRCDIRPAT}//" | \ |
| egrep '\.[chS]$$' | sort | uniq > $@ |
| |
| cmd_etags = etags -o ${BUILD}/TAGS $(shell cat ${BUILD}/cscope.files) |
| cmd_ctags = ctags -o ${BUILD}/tags $(shell cat ${BUILD}/cscope.files) |
| run_if_prog = $(if $(shell which $(1) 2>/dev/null),$(2),) |
| |
| .PHONY: tags TAGS xrefs |
| tags TAGS xrefs: ${BUILD}/cscope.files |
| ${Q}\rm -f ${BUILD}/tags ${BUILD}/TAGS |
| ${Q}$(call run_if_prog,etags,${cmd_etags}) |
| ${Q}$(call run_if_prog,ctags,${cmd_ctags}) |
| |
| PC_FILES = ${PC_IN_FILES:%.pc.in=${BUILD}/%.pc} |
| ${PC_FILES}: ${PC_IN_FILES} |
| ${Q}sed \ |
| -e 's:@LDLIBS@:${LDLIBS}:' \ |
| -e 's:@LIBDIR@:${LIBDIR}:' \ |
| $< > $@ |
| |
| .PHONY: pc_files_install |
| pc_files_install: ${PC_FILES} |
| ${Q}mkdir -p ${ULP_DIR} |
| ${Q}${INSTALL} -D -m 0644 $< ${ULP_DIR}/$(notdir $<) |