| Index: common.mk
|
| diff --git a/common.mk b/common.mk
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a58251a0bc2efe455a049ab8b2b0f2aca82e0079
|
| --- /dev/null
|
| +++ b/common.mk
|
| @@ -0,0 +1,478 @@
|
| +# Copyright (c) 2010 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.
|
| +#
|
| +# This file provides a common architecture for building C/C++ source trees.
|
| +# It uses recursive makefile inclusion to create a single make process which
|
| +# can be built in the source tree or with the build products placed elsewhere.
|
| +#
|
| +# To use:
|
| +# 1. Place common.mk in your top source level
|
| +# 2. In your top-level Makefile, place "include common.mk" at the top
|
| +# 3. In all subdirectories, create a 'module.mk' file that starts with:
|
| +# include common.mk
|
| +# And then contains the remainder of your targets.
|
| +# 4. All build targets should look like:
|
| +# $(OUT)relative/path/target: ...
|
| +#
|
| +# See existing makefiles for rule examples.
|
| +#
|
| +# Exported macros:
|
| +# - cc_binary, cxx_binary provide standard compilation steps for binaries
|
| +# - cxx_library, cc_library provide standard compilation steps for sos
|
| +# All of the above optionally take an argument for extra flags.
|
| +# - update_archive creates/updates a given .a target
|
| +#
|
| +# Exported variables
|
| +# - RM_ON_CLEAN - append files to remove on calls to clean
|
| +# - RMDIR_ON_CLEAN - append dirs to remove on calls to clean
|
| +#
|
| +# Exported targets meant to have prerequisites added to:
|
| +# - all - Your $(OUT)target should be given
|
| +# - small_tests - requires something, even if it is just NONE
|
| +# - large_tests - requires something, even if it is just NONE
|
| +# - NONE - nop target for *_tests
|
| +# - FORCE - force the given target to run regardless of changes
|
| +#
|
| +# Possible command line variables:
|
| +# - COLOR=[0|1] to set ANSI color output (default: 1)
|
| +# - VERBOSE=[0|1] to hide/show commands (default: 0)
|
| +# - MODE=dbg to turn down optimizations (default: opt)
|
| +# - ARCH=[x86|arm|supported qemu name] (default: from portage or uname -m)
|
| +# - SPLITDEBUG=[0|1] splits debug info in target.debug (default: 1)
|
| +# [SPLITDEBUG=0 MODE=opt will disable compiling with -g]
|
| +# - VALGRIND=[0|1] runs tests under valgrind (default: 0)
|
| +# - OUT=/path/to/builddir puts all output in given path
|
| +# (default: $PWD/build-$MODE. Use OUT=. for normal behavior)
|
| +# - VALGRIND_ARGS="" supplies extra memcheck arguments
|
| +#
|
| +# External CXXFLAGS and CFLAGS should be passed via the environment since this
|
| +# file does not use 'override' to control them.
|
| +
|
| +# Behavior configuration variables
|
| +SPLITDEBUG ?= 1
|
| +VALGRIND ?= 0
|
| +COLOR ?= 1
|
| +VERBOSE ?= 0
|
| +MODE ?= opt
|
| +ARCH ?= $(shell uname -m)
|
| +# TODO: profiling support not completed.
|
| +PROFILING ?= 0
|
| +
|
| +# Put objects in a separate tree based on makefile locations
|
| +# This means you can build a tree without touching it:
|
| +# make -C $SRCDIR # will create ./build
|
| +# Or
|
| +# make -C $SRCDIR OUT=$PWD
|
| +# This variable is extended on subdir calls and doesn't need to be re-called.
|
| +OUT ?= $(PWD)/build-$(MODE)/
|
| +# Ensure a command-line supplied OUT has a slash
|
| +override OUT := $(abspath $(OUT))/
|
| +
|
| +# Only call MODULE if we're in a submodule
|
| +MODULES_LIST := $(filter-out Makefile %.d,$(MAKEFILE_LIST))
|
| +ifeq ($(words $(filter-out Makefile common.mk %.d,$(MAKEFILE_LIST))),0)
|
| +# Setup a top level SRC
|
| +SRC ?= $(PWD)
|
| +
|
| +#
|
| +# Helper macros
|
| +#
|
| +
|
| +# Creates the actual archive with an index.
|
| +# $(1) is the object suffix modified: pie or pic.
|
| +define update_archive
|
| + $(QUIET)mkdir -p $(dir $@)
|
| + $(QUIET)# Create the archive in one step to avoid parallel use accessing it
|
| + $(QUIET)# before all the symbols are present.
|
| + @$(ECHO) "AR $(subst $(PWD)/,,$(^:.o=.$(1).o)) -> $(subst $(PWD)/,,$@)"
|
| + $(QUIET)$(AR) rcs $@ $(^:.o=.$(1).o)
|
| +endef
|
| +
|
| +# Default compile from objects using pre-requisites but filters out
|
| +# subdirs and .d files.
|
| +define cc_binary
|
| + $(call COMPILE_BINARY_implementation,CC,$(CFLAGS) $(1))
|
| +endef
|
| +
|
| +define cxx_binary
|
| + $(call COMPILE_BINARY_implementation,CXX,$(CXXFLAGS) $(1))
|
| +endef
|
| +
|
| +# Default compile from objects using pre-requisites but filters out
|
| +# subdirs and .d files.
|
| +define cc_library
|
| + $(call COMPILE_LIBRARY_implementation,CC,$(CFLAGS) $(1))
|
| +endef
|
| +define cxx_library
|
| + $(call COMPILE_LIBRARY_implementation,CXX,$(CXXFLAGS) $(1))
|
| +endef
|
| +
|
| +
|
| +# Deletes files silently if they exist. Meant for use in any local
|
| +# clean targets.
|
| +define silent_rm
|
| + $(QUIET)(test -n "$(wildcard $(1))" && \
|
| + $(ECHO) -n '$(COLOR_RED)CLEANFILE$(COLOR_RESET) ' && \
|
| + $(ECHO) '$(subst $(PWD)/,,$(wildcard $(1)))' && \
|
| + $(RM) -f $(1) 2>/dev/null) || true
|
| +endef
|
| +define silent_rmdir
|
| + $(QUIET)(test -n "$(wildcard $(1))" && \
|
| + $(ECHO) -n '$(COLOR_RED)CLEANDIR$(COLOR_RESET) ' && \
|
| + $(ECHO) '$(subst $(PWD)/,,$(wildcard $(1)))' && \
|
| + $(RMDIR) $(1) 2>/dev/null) || true
|
| +endef
|
| +
|
| +
|
| +
|
| +#
|
| +# Default variables for use in including makefiles
|
| +#
|
| +
|
| +# All objects for .c files at the top level
|
| +C_OBJECTS := $(patsubst %.c,$(OUT)%.o,$(wildcard *.c))
|
| +
|
| +# All objects for .cxx files at the top level
|
| +CXX_OBJECTS := $(patsubst %.cc,$(OUT)%.o,$(wildcard *.cc))
|
| +
|
| +#
|
| +# Default variable values
|
| +#
|
| +
|
| +OBJCOPY ?= objcopy
|
| +STRIP ?= strip
|
| +RMDIR ?= rmdir
|
| +# Only override CC and CXX if they are from make.
|
| +ifeq ($(origin CC), default)
|
| + CC = gcc
|
| +endif
|
| +ifeq ($(origin CXX), default)
|
| + CXX = g++
|
| +endif
|
| +ifeq ($(origin RANLIB), default)
|
| + RANLIB = ranlib
|
| +endif
|
| +RANLIB ?= ranlib
|
| +ECHO = /bin/echo -e
|
| +
|
| +ifeq ($(PROFILING),1)
|
| + $(warning PROFILING=1 disables relocatable executables.)
|
| +endif
|
| +
|
| +# To update these from an including Makefile:
|
| +# CXXFLAGS += -mahflag # Append to the list
|
| +# CXXFLAGS := -mahflag $(CXXFLAGS) # Prepend to the list
|
| +# CXXFLAGS := $(filter-out badflag,$(CXXFLAGS)) # Filter out a value
|
| +# The same goes for CFLAGS.
|
| +CXXFLAGS := $(CXXFLAGS) -Wall -Werror -fstack-protector-all -DFORTIFY_SOURCE \
|
| + -O2 -ggdb3 -DNDEBUG -Wa,--noexecstack
|
| +CFLAGS := $(CFLAGS) -Wall -Werror -fstack-protector-all -DFORTIFY_SOURCE \
|
| + -O2 -ggdb3 -DNDEBUG -Wa,--noexecstack
|
| +
|
| +ifeq ($(PROFILING),1)
|
| + CFLAGS := -pg
|
| + CXXFLAGS := -pg
|
| +endif
|
| +
|
| +ifeq ($(MODE),dbg)
|
| + CFLAGS := $(filter-out -O2 -DNDEBUG,$(CFLAGS)) -O1
|
| + CXXFLAGS := $(filter-out -O2 -DNDEBUG,$(CXXFLAGS)) -O1
|
| + # TODO: May need -nopie. need to check gdb
|
| +else # opt
|
| + ifeq ($(SPLITDEBUG),0)
|
| + # TODO: do we want -fomit-frame-pointer on x86?
|
| + CFLAGS := $(filter-out -ggdb3,$(CFLAGS))
|
| + CXXFLAGS := $(filter-out -ggdb3,$(CXXFLAGS))
|
| + endif
|
| +endif
|
| +
|
| +LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,noexecstack
|
| +
|
| +# Fancy helpers for color if a prompt is defined
|
| +ifeq ($(COLOR),1)
|
| +COLOR_RESET = \x1b[0m
|
| +COLOR_GREEN = \x1b[32;01m
|
| +COLOR_RED = \x1b[31;01m
|
| +COLOR_YELLOW = \x1b[33;01m
|
| +endif
|
| +
|
| +# By default, silence build output.
|
| +QUIET = @
|
| +ifeq ($(VERBOSE),1)
|
| + QUIET=
|
| +endif
|
| +
|
| +#
|
| +# Implementation macros for compile helpers above
|
| +#
|
| +
|
| +# Useful for dealing with pie-broken toolchains.
|
| +# Call make with PIE=0 to disable default PIE use.
|
| +OBJ_PIE_FLAG = -fPIE
|
| +COMPILE_PIE_FLAG = -pie
|
| +ifeq ($(PIE),0)
|
| + OBJ_PIE_FLAG =
|
| + COMPILE_PIE_FLAG =
|
| +endif
|
| +
|
| +# Default compile from objects using pre-requisites but filters out
|
| +# all non-.o files.
|
| +define COMPILE_BINARY_implementation
|
| + @$(ECHO) "LD$(1) $(subst $(PWD)/,,$@)"
|
| + $(QUIET)$($(1)) $(COMPILE_PIE_FLAGS) -o $@ \
|
| + $(filter %.o %.so %.a,$(^:.o=.pie.o)) $(LDFLAGS) $(2)
|
| + $(call strip_library)
|
| + @$(ECHO) "BIN $(COLOR_GREEN)$(subst $(PWD)/,,$@)$(COLOR_RESET)"
|
| + @$(ECHO) " $(COLOR_YELLOW)-----$(COLOR_RESET)"
|
| +endef
|
| +
|
| +# TODO: add version support extracted from PV environment variable
|
| +#ifeq ($(PV),9999)
|
| +#$(warning PV=$(PV). If shared object versions matter, please force PV=.)
|
| +#endif
|
| +# Then add -Wl,-soname,$@.$(PV) ?
|
| +
|
| +# Default compile from objects using pre-requisites but filters out
|
| +# all non-.o values. (Remember to add -L$(OUT) -llib)
|
| +define COMPILE_LIBRARY_implementation
|
| + @$(ECHO) "SHARED$(1) $(subst $(PWD)/,,$@)"
|
| + $(QUIET)$($(1)) -shared -Wl,-E -o $@ \
|
| + $(filter %.o %.so %.a,$(^:.o=.pic.o)) $(2) $(LDFLAGS)
|
| + $(call strip_library)
|
| + @$(ECHO) "LIB $(COLOR_GREEN)$(subst $(PWD)/,,$@)$(COLOR_RESET)"
|
| + @$(ECHO) " $(COLOR_YELLOW)-----$(COLOR_RESET)"
|
| +endef
|
| +
|
| +define strip_library
|
| + @$(ECHO) "STRIP $(subst $(PWD)/,,$@)"
|
| + $(if $(filter 1,$(SPLITDEBUG)), @$(ECHO) -n "DEBUG "; \
|
| + $(ECHO) "$(COLOR_YELLOW)$(subst $(PWD)/,,$@).debug$(COLOR_RESET)")
|
| + $(if $(filter 1,$(SPLITDEBUG)), \
|
| + $(QUIET)$(OBJCOPY) --only-keep-debug "$@" "$@.debug")
|
| + $(if $(filter-out dbg,$(MODE)),$(QUIET)$(STRIP) --strip-unneeded "$@",)
|
| +endef
|
| +
|
| +define strip_binary
|
| + @$(ECHO) "STRIP $(subst $(PWD)/,,$@)"
|
| + $(if $(filter 1,$(SPLITDEBUG)), @$(ECHO) -n "DEBUG "; \
|
| + $(ECHO) "$(COLOR_YELLOW)$(subst $(PWD)/,,$@).debug$(COLOR_RESET)")
|
| + $(if $(filter 1,$(SPLITDEBUG)), \
|
| + $(QUIET)$(OBJCOPY) --only-keep-debug "$@" "$@.debug")
|
| + $(if $(filter-out dbg,$(MODE)),$(QUIET)$(STRIP) --strip-unneeded "$@",)
|
| +endef
|
| +
|
| +#
|
| +# Pattern rules
|
| +#
|
| +
|
| +%.o: %.pie.o %.pic.o
|
| + $(QUIET)touch $@
|
| +
|
| +$(OUT)%.pie.o: %.c
|
| + $(call OBJECT_PATTERN_implementation,CC,$(CFLAGS) $(OBJ_PIE_FLAG))
|
| +
|
| +$(OUT)%.pic.o: %.c
|
| + $(call OBJECT_PATTERN_implementation,CC,$(CFLAGS) -fPIC)
|
| +
|
| +$(OUT)%.pie.o: %.cc
|
| + $(call OBJECT_PATTERN_implementation,CXX,$(CXXFLAGS) $(OBJ_PIE_FLAG))
|
| +
|
| +$(OUT)%.pic.o: %.cc
|
| + $(call OBJECT_PATTERN_implementation,CXX,$(CXXFLAGS) -fPIC)
|
| +
|
| +
|
| +define OBJECT_PATTERN_implementation
|
| + @$(ECHO) "$(subst $(PWD)/,,$(1)) $(subst $(PWD)/,,$<)"
|
| + $(QUIET)mkdir -p $(dir $@)
|
| + $(QUIET)$($(1)) -c -MD -MF $(basename $@).d -o $@ $< $(2)
|
| + $(QUIET)# Wrap all the deps in $(wildcard) so a missing header
|
| + $(QUIET)# won't cause weirdness. First we remove newlines and \,
|
| + $(QUIET)# then wrap it.
|
| + $(QUIET)sed -i -e :j -e '$$!N;s|\\\s*\n| |;tj' \
|
| + -e 's|^\(.*\s*:\s*\)\(.*\)$$|\1 $$\(wildcard \2\)|' $(basename $@).d
|
| +endef
|
| +
|
| +# NOTE: A specific rule for archive objects is avoided because parallel
|
| +# update of the archive causes build flakiness.
|
| +# Instead, just make the objects the prerequisites and use update_archive
|
| +# To use the foo.a(obj.o) functionality, targets would need to specify the
|
| +# explicit object they expect on the prerequisite line.
|
| +
|
| +#
|
| +# Architecture detection and QEMU wrapping
|
| +#
|
| +
|
| +ARCH ?= $(shell uname -m)
|
| +HOST_ARCH ?= $(shell uname -m)
|
| +# emake will supply "x86" or "arm" for ARCH, but
|
| +# if uname -m runs and you get x86_64, then this subst
|
| +# will break.
|
| +ifeq ($(subst x86,i386,$(ARCH)),i386)
|
| + QEMU_ARCH := $(subst x86,i386,$(ARCH)) # x86 -> i386
|
| +else
|
| + QEMU_ARCH = $(ARCH)
|
| +endif
|
| +
|
| +# If we're cross-compiling, try to use qemu for running the tests.
|
| +QEMU_CMD ?=
|
| +ifneq ($(QEMU_ARCH),$(HOST_ARCH))
|
| + ifeq ($(SYSROOT),)
|
| + $(info SYSROOT not defined. qemu-based testing disabled)
|
| + else
|
| + # A SYSROOT is assumed for QEmu use.
|
| + USE_QEMU ?= 1
|
| + endif
|
| +endif
|
| +
|
| +#
|
| +# Output full configuration at top level
|
| +#
|
| +
|
| +# Don't show on clean
|
| +ifneq ($(MAKECMDGOALS),clean)
|
| + $(info build configuration:)
|
| + $(info - OUT=$(OUT))
|
| + $(info - MODE=$(MODE))
|
| + $(info - SPLITDEBUG=$(SPLITDEBUG))
|
| + $(info - VALGRIND=$(VALGRIND))
|
| + $(info - COLOR=$(COLOR))
|
| + $(info - ARCH=$(ARCH))
|
| + $(info - QEMU_ARCH=$(QEMU_ARCH))
|
| + $(info - SYSROOT=$(SYSROOT))
|
| + $(info )
|
| +endif
|
| +
|
| +#
|
| +# Standard targets with detection for when they are improperly configured.
|
| +#
|
| +
|
| +# all does not include tests by default
|
| +all:
|
| + $(QUIET)(test -z "$^" && \
|
| + $(ECHO) "You must add your targets as 'all' prerequisites") || true
|
| + $(QUIET)test -n "$^"
|
| +
|
| +# Builds and runs tests for the target arch
|
| +tests: small_tests large_tests
|
| +
|
| +small_tests: qemu FORCE
|
| + $(call TEST_implementation)
|
| +
|
| +large_tests: qemu FORCE
|
| + $(call TEST_implementation)
|
| +
|
| +qemu_clean: FORCE
|
| +ifeq ($(USE_QEMU),1)
|
| + $(call silent_rm,$(PWD)/qemu-$(QEMU_ARCH))
|
| +endif
|
| +
|
| +qemu: FORCE
|
| +ifeq ($(USE_QEMU),1)
|
| + $(QUIET)$(ECHO) "QEMU Preparing qemu-$(QEMU_ARCH)"
|
| + $(QUIET)cp -f /usr/bin/qemu-$(QEMU_ARCH) $(PWD)/qemu-$(QEMU_ARCH)
|
| + $(QUIET)chmod a+rx $(PWD)/qemu-$(QEMU_ARCH)
|
| +endif
|
| +
|
| +# TODO(wad) separate chroot from qemu to make it possible to cross-compile
|
| +# and test outside of the chroot.
|
| +ifeq ($(USE_QEMU),1)
|
| + export QEMU_CMD = sudo chroot $(SYSROOT) \
|
| + $(subst $(SYSROOT),,$(PWD))/qemu-$(QEMU_ARCH) \
|
| + -drop-ld-preload \
|
| + -E LD_LIBRARY_PATH="$(SYSROOT_LDPATH)" \
|
| + -E HOME="$(HOME)" --
|
| +endif
|
| +
|
| +VALGRIND_CMD =
|
| +ifeq ($(VALGRIND),1)
|
| + VALGRIND_CMD = /usr/bin/valgrind --tool=memcheck $(VALGRIND_ARGS) --
|
| +endif
|
| +
|
| +define TEST_implementation
|
| + $(QUIET)(test -z "$(filter FORCE qemu,$^)" && \
|
| + $(ECHO) "No '$@' prerequisites defined!") || true
|
| + $(QUIET)test -n "$^"
|
| + $(QUIET)# TODO(wad) take root away after the chroot.
|
| + $(QUIET)test "$(filter NONE,$^)" = "NONE" || \
|
| + ((test "1" = "$(VALGRIND)" && test -n "$(USE_QEMU)" && \
|
| + sudo mkdir -p $(SYSROOT)/proc && \
|
| + sudo mount --bind /proc $(SYSROOT)/proc); \
|
| + (status=0 && for tgt in $(subst $(SYSROOT),,$(filter-out FORCE qemu,$^)); \
|
| + do \
|
| + $(ECHO) "TEST $$tgt"; \
|
| + $(QEMU_CMD) $(VALGRIND_CMD) $$tgt $(GTEST_ARGS); \
|
| + status=$$((status + $$?)); \
|
| + done; (test "1" = "$(VALGRIND)" && test -n "$(USE_QEMU)" && \
|
| + sudo umount $(SYSROOT)/proc); exit $$status))
|
| +endef
|
| +
|
| +
|
| +# Add the defaults from this dir to rm_clean
|
| +define default_rm_clean
|
| + $(OUT)$(1)*.d $(OUT)$(1)*.o $(OUT)$(1)*.debug
|
| +endef
|
| +
|
| +# Start with the defaults
|
| +RM_ON_CLEAN = $(call default_rm_clean)
|
| +RMDIR_ON_CLEAN = $(OUT)
|
| +
|
| +# Recursive list reversal so that we get RMDIR_ON_CLEAN in reverse order.
|
| +define reverse
|
| +$(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
|
| +endef
|
| +
|
| +rm_clean: FORCE
|
| + $(call silent_rm,$(RM_ON_CLEAN))
|
| +
|
| +rmdir_clean: FORCE rm_clean
|
| + $(call silent_rmdir,$(call reverse,$(RMDIR_ON_CLEAN)))
|
| +
|
| +clean: qemu_clean rmdir_clean
|
| +
|
| +FORCE: ;
|
| +# Empty rule for use when no special targets are needed, like large_tests
|
| +NONE:
|
| +
|
| +.PHONY: clean NONE qemu_clean valgrind rm_clean rmdir_clean
|
| +.DEFAULT_GOAL := all
|
| +# Don't let make blow away "intermediates"
|
| +.PRECIOUS: $(OUT)%.pic.o $(OUT)%.pie.o
|
| +
|
| +# Start accruing build info
|
| +OUT_DIRS = $(OUT)
|
| +SRC_DIRS = .
|
| +
|
| +include $(wildcard $(OUT)*.d)
|
| +SUBMODULE_DIRS = $(wildcard */module.mk)
|
| +include $(SUBMODULE_DIRS)
|
| +
|
| +else ## In duplicate inclusions of common.mk
|
| +
|
| +# Get the current inclusion directory without a trailing slash
|
| +MODULE := $(patsubst %/,%, \
|
| + $(dir $(lastword $(filter-out %common.mk,$(MAKEFILE_LIST)))))
|
| +MODULE_NAME := $(subst /,_,$(MODULE))
|
| +
|
| +# Depth first
|
| +$(eval OUT_DIRS += $(OUT)/$(MODULE))
|
| +$(eval SRC_DIRS += $(MODULE))
|
| +
|
| +# Add the defaults from this dir to rm_clean
|
| +$(eval RM_ON_CLEAN += $(call default_rm_clean,$(MODULE)/))
|
| +$(eval RMDIR_ON_CLEAN += $(wildcard $(OUT)$(MODULE)/))
|
| +
|
| +$(info + submodule: $(MODULE_NAME))
|
| +# We must eval otherwise they may be dropped.
|
| +$(eval $(MODULE_NAME)_C_OBJECTS ?= \
|
| + $(patsubst %.c,$(OUT)%.o,$(wildcard $(MODULE)/*.c)))
|
| +$(eval $(MODULE_NAME)_CXX_OBJECTS ?= \
|
| + $(patsubst %.cc,$(OUT)%.o,$(wildcard $(MODULE)/*.cc)))
|
| +
|
| +# Continue recursive inclusion of module.mk files
|
| +SUBMODULE_DIRS = $(wildcard $(MODULE)/*/module.mk)
|
| +
|
| +include $(wildcard $(OUT)$(MODULE)/*.d)
|
| +include $(SUBMODULE_DIRS)
|
| +endif
|
| +
|
|
|