rollog: Updating common.mk to ToT to enable profiling

This update replaces the current common.mk used in this project with the newest
version. This will allow all of the common.mk based projects to be on the same
version for debugging and enables profiling support.

BUG=chromium-os:37854
TEST=Exectuted the following commands to confirm the build works:
     MODE=profiling cros_workon_make --board=link
     MODE=profiling cros_workon_make --board=link --test
     cros_workon_make --board=link
     cros_workon_make --board=link --test
     Repeated these with emerge-link, USE=profiling, and
     FEATURES=test as need.
     For the emerge command with profiling and testing enable, confirmed the
     appropriate coverage files were created in /usr/share/profiling/...

Change-Id: Iea19155dd82ad508ff1feefaa6e60d4753e65fa5
Reviewed-on: https://gerrit.chromium.org/gerrit/42779
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Tested-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/common.mk b/common.mk
index 357d1f9..058e906 100644
--- a/common.mk
+++ b/common.mk
@@ -64,7 +64,11 @@
 # 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)
+#   - MODE=[opt|dbg|profiling] (default: opt)
+#          opt - Enable optimizations for release builds
+#          dbg - Turn down optimization for debugging
+#          profiling - Turn off optimization and turn on profiling/coverage
+#                      support.
 #   - ARCH=[x86|arm|supported qemu name] (default: from portage or uname -m)
 #   - SPLITDEBUG=[0|1] splits debug info in target.debug (default: 0)
 #        If NOSTRIP=1, SPLITDEBUG will never strip the final emitted objects.
@@ -97,8 +101,6 @@
 VERBOSE ?= 0
 MODE ?= opt
 ARCH ?= $(shell uname -m)
-# TODO: profiling support not completed.
-PROFILING ?= 0
 NEEDS_ROOT = 0
 NEEDS_MOUNTS = 0
 
@@ -161,8 +163,7 @@
 _all::
 %::
 	$(if $(filter 0,$(RUN_ONCE)), \
-	  $(QUIET)mkdir -p "$(OUT)" && \
-	  cd $(OUT) && \
+	  cd "$(OUT)" && \
 	  $(MAKE) -r -I "$(SRC)" -f "$(CURDIR)/Makefile" \
 	    SRC="$(CURDIR)" OUT="$(OUT)" $(foreach g,$(MAKECMDGOALS),"$(g)"),)
 	$(eval RUN_ONCE := 1)
@@ -182,10 +183,15 @@
 # Helper macros
 #
 
+# Create the directory if it doesn't yet exist.
+define auto_mkdir
+  $(if $(wildcard $(dir $1)),$2,$(QUIET)mkdir -p "$(dir $1)")
+endef
+
 # Creates the actual archive with an index.
 # The target $@ must end with .pic.a or .pie.a.
 define update_archive
-  $(QUIET)mkdir -p "$(dir $(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
   $(QUIET)# Create the archive in one step to avoid parallel use accessing it
   $(QUIET)# before all the symbols are present.
   @$(ECHO) "AR		$(subst \
@@ -235,24 +241,34 @@
 # Default variable values
 #
 
-OBJCOPY ?= objcopy
-STRIP ?= strip
+# Only override toolchain vars if they are from make.
+CROSS_COMPILE ?=
+define override_var
+ifneq ($(filter undefined default,$(origin $1)),)
+$1 = $(CROSS_COMPILE)$2
+endif
+endef
+$(eval $(call override_var,AR,ar))
+$(eval $(call override_var,CC,gcc))
+$(eval $(call override_var,CXX,g++))
+$(eval $(call override_var,OBJCOPY,objcopy))
+$(eval $(call override_var,PKG_CONFIG,pkg-config))
+$(eval $(call override_var,RANLIB,ranlib))
+$(eval $(call override_var,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.)
+ifeq ($(lastword $(subst /, ,$(CC))),clang)
+CDRIVER = clang
+else
+CDRIVER = gcc
+endif
+
+ifeq ($(lastword $(subst /, ,$(CXX))),clang++)
+CXXDRIVER = clang
+else
+CXXDRIVER = gcc
 endif
 
 # To update these from an including Makefile:
@@ -260,16 +276,14 @@
 #  CXXFLAGS := -mahflag $(CXXFLAGS) # Prepend to the list
 #  CXXFLAGS := $(filter-out badflag,$(CXXFLAGS)) # Filter out a value
 # The same goes for CFLAGS.
-COMMON_CFLAGS := -Wall -Werror -fstack-protector-strong -fno-strict-aliasing \
-  -ggdb3 -Wa,--noexecstack -O1 -fvisibility=internal -Wformat=2
-CXXFLAGS += $(COMMON_CFLAGS)
-CFLAGS += $(COMMON_CFLAGS)
+COMMON_CFLAGS-gcc := -fstack-protector-strong -fvisibility=internal -ggdb3 \
+  -Wa,--noexecstack
+COMMON_CFLAGS-clang := -fstack-protector-all -fvisibility=hidden -ggdb
+COMMON_CFLAGS := -Wall -Werror -fno-strict-aliasing -O1 -Wformat=2
+CXXFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CXXDRIVER))
+CFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CDRIVER))
 CPPFLAGS += -D_FORTIFY_SOURCE=2
 
-ifeq ($(PROFILING),1)
-  CFLAGS := -pg
-  CXXFLAGS := -pg
-endif
 
 ifeq ($(MODE),opt)
   # Up the optimizations.
@@ -283,6 +297,12 @@
   endif
 endif
 
+ifeq ($(MODE),profiling)
+  CFLAGS := $(CFLAGS) -O0 -g  --coverage
+  CXXFLAGS := $(CXXFLAGS) -O0 -g  --coverage
+  LDFLAGS := $(LDFLAGS) --coverage
+endif
+
 LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now
 
 # Fancy helpers for color if a prompt is defined
@@ -322,7 +342,7 @@
 # all non-.o files.
 define COMPILE_BINARY_implementation
   @$(ECHO) "LD$(1)		$(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
-  $(QUIET)mkdir -p "$(dir $(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
   $(QUIET)$($(1)) $(COMPILE_PIE_FLAGS) -o $(TARGET_OR_MEMBER) \
     $(2) $(LDFLAGS) \
     $(filter %.o %.a,$(^:.o=.pie.o)) \
@@ -346,7 +366,7 @@
 COMMA := ,
 define COMPILE_LIBRARY_implementation
   @$(ECHO) "SHARED$(1)	$(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
-  $(QUIET)mkdir -p "$(dir $(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
   $(QUIET)$($(1)) -shared -Wl,-E -o $(TARGET_OR_MEMBER) \
     $(2) $(LDFLAGS) \
     $(if $(filter %.a,$^),-Wl$(COMMA)--whole-archive,) \
@@ -501,30 +521,30 @@
 # $(5) source dir: _only_ if $(SRC). Leave blank for obj tree.
 define add_object_rules
 $(patsubst %.o,%.pie.o,$(1)): %.pie.o: $(5)%.$(3) %.o.depends
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(call OBJECT_PATTERN_implementation,$(2),\
           $$(basename $$@),$$($(4)) $$(CPPFLAGS) $$(OBJ_PIE_FLAG))
 
 $(patsubst %.o,%.pic.o,$(1)): %.pic.o: $(5)%.$(3) %.o.depends
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(call OBJECT_PATTERN_implementation,$(2),\
           $$(basename $$@),$$($(4)) $$(CPPFLAGS) -fPIC)
 
 # Placeholder for depends
 $(patsubst %.o,%.o.depends,$(1)):
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(QUIET)touch "$$@"
 
 $(1): %.o: %.pic.o %.pie.o
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(QUIET)touch "$$@"
 endef
 
 define OBJECT_PATTERN_implementation
   @$(ECHO) "$(1)		$(subst $(SRC)/,,$<) -> $(2).o"
-  $(QUIET)mkdir -p "$(dir $(2))"
+  $(call auto_mkdir,$@)
   $(QUIET)$($(1)) -c -MD -MF $(2).d $(3) -o $(2).o $<
-  $(QUIET)# Wrap all the deps in $(wildcard) so a missing header
+  $(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' \
@@ -627,7 +647,27 @@
 
 # Builds and runs tests for the target arch
 # Run them in parallel
+# After the test have completed, if profiling, run coverage analysis
 tests:
+ifeq ($(MODE),profiling)
+	@$(ECHO) -n "COVERAGE		gcov "
+	@$(ECHO) "[$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+	$(QUIET)(FILES="";						\
+		for GCNO in `find . -name "*.gcno"`;			\
+		do							\
+			GCDA="$${GCNO%.gcno}.gcda";			\
+			[ -e $${GCDA} ] && FILES="$${FILES} $${GCDA}";	\
+		done;							\
+		gcov -l $${FILES})
+	@$(ECHO) -n "COVERAGE		gcov "
+	@$(ECHO) "[$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+	@$(ECHO) -n "COVERAGE		lcov "
+	@$(ECHO) "[$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+	$(QUIET)lcov --capture --directory . --output-file=lcov-coverage.info
+	$(QUIET)genhtml lcov-coverage.info --output-directory lcov-html
+	@$(ECHO) -n "COVERAGE		lcov "
+	@$(ECHO) "[$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+endif
 .PHONY: tests
 
 qemu_clean:
@@ -732,6 +772,8 @@
 clean: qemu_clean
 clean: CLEAN($(OUT)*.d) CLEAN($(OUT)*.o) CLEAN($(OUT)*.debug)
 clean: CLEAN($(OUT)*.test) CLEAN($(OUT)*.depends)
+clean: CLEAN($(OUT)*.gcno) CLEAN($(OUT)*.gcda) CLEAN($(OUT)*.gcov)
+clean: CLEAN($(OUT)lcov-coverage.info) CLEAN($(OUT)lcov-html)
 
 clean:
 	$(QUIET)# Always delete the containing directory last.
@@ -775,6 +817,9 @@
 clean: CLEAN($(OUT)$(MODULE)/*.d) CLEAN($(OUT)$(MODULE)/*.o)
 clean: CLEAN($(OUT)$(MODULE)/*.debug) CLEAN($(OUT)$(MODULE)/*.test)
 clean: CLEAN($(OUT)$(MODULE)/*.depends)
+clean: CLEAN($(OUT)$(MODULE)/*.gcno) CLEAN($(OUT)$(MODULE)/*.gcda)
+clean: CLEAN($(OUT)$(MODULE)/*.gcov) CLEAN($(OUT)lcov-coverage.info)
+clean: CLEAN($(OUT)lcov-html)
 
 $(info + submodule: $(MODULE_NAME))
 # We must eval otherwise they may be dropped.