build: enable code coverage

Enable code coverage for the project.  Valgrind not enabled in this
step.

Change-Id: I519bac32acc58ba388dc3724e187255d3237c085
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/.lcovrc b/.lcovrc
new file mode 100644
index 0000000..360a8b4
--- /dev/null
+++ b/.lcovrc
@@ -0,0 +1,3 @@
+geninfo_gcov_all_blocks = 1
+lcov_function_coverage = 1
+lcov_branch_coverage = 0
diff --git a/Makefile.am b/Makefile.am
index 6265ed8..d7b5c35 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,31 @@
+# Ignore system headers
+CODE_COVERAGE_IGNORE_PATTERN = '/include/*' '/usr/include/*' '$(includedir)/*'
+# Ignore the real implementation sources for sys
+CODE_COVERAGE_IGNORE_PATTERN += '$(abs_builddir)/internal/sys.*'
+export CODE_COVERAGE_IGNORE_PATTERN
+
+CODE_COVERAGE_LCOV_SHOPTS = $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
+# Use our configuration file for lcov
+CODE_COVERAGE_LCOV_SHOPTS += --config-file $(abs_srcdir)/.lcovrc
+export CODE_COVERAGE_LCOV_SHOPTS
+
+CODE_COVERAGE_LCOV_OPTIONS = $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
+# Use our configuration file for lcov
+CODE_COVERAGE_LCOV_OPTIONS += --config-file $(abs_srcdir)/.lcovrc
+export CODE_COVERAGE_LCOV_OPTIONS
+
+CODE_COVERAGE_LCOV_RMOPTS = $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
+# Use our configuration file for lcov
+CODE_COVERAGE_LCOV_RMOPTS += --config-file $(abs_srcdir)/.lcovrc
+export CODE_COVERAGE_LCOV_RMOPTS
+
+CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
+# Use our configuration file for genhtml
+CODE_COVERAGE_GENHTML_OPTIONS += --config-file $(abs_srcdir)/.lcovrc
+# Don't generate the absolute path for each file in the HTML output
+CODE_COVERAGE_GENHTML_OPTIONS += --prefix $(abs_srcdir) --prefix $(abs_builddir)
+export CODE_COVERAGE_GENHTML_OPTIONS
+
 ACLOCAL_AMFLAGS = -I m4
 AM_DEFAULT_SOURCE_EXT = .cpp
 
@@ -15,11 +43,13 @@
 libfirmwareblob_la_LDFLAGS = \
 	$(SDBUSPLUS_LIBS) \
 	$(PHOSPHOR_LOGGING_LIBS) \
+	$(CODE_COVERAGE_LIBS) \
 	-lstdc++fs \
 	-version-info 0:0:0 -shared
 libfirmwareblob_la_CXXFLAGS = \
 	$(SDBUSPLUS_CFLAGS) \
 	$(PHOSPHOR_LOGGING_CFLAGS) \
+	$(CODE_COVERAGE_CXXFLAGS) \
 	-flto
 
 SUBDIRS = . test tools
diff --git a/configure.ac b/configure.ac
index 3183509..f5812e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,19 @@
 AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
 AM_SILENT_RULES([yes])
 
+# Make sure the default CFLAGS of `-O2 -g` don't override CODE_COVERAGE_CFLAGS
+# It is important that this comes before AC_PROG_C{C,XX}, as we are attempting
+# to stop them from populating default CFLAGS and CXXFLAGS.
+AS_IF([test "x$enable_tests" = "xno"], [enable_code_coverage=no])
+AS_IF([test "x$enable_code_coverage" != "xno"], [
+    AS_IF([test "x${CXXFLAGS+set}" != "xset"], [
+        AC_SUBST(CXXFLAGS, [""])
+    ])
+    AS_IF([test "x${CFLAGS+set}" != "xset"], [
+        AC_SUBST(CFLAGS, [""])
+    ])
+])
+
 # Checks for programs.
 AC_PROG_CXX
 AM_PROG_AR
@@ -190,6 +203,13 @@
     AX_RESTORE_FLAGS_WITH_PREFIX(OLD, [LDFLAGS])
 ])
 
+# Code coverage
+AX_CODE_COVERAGE
+AM_EXTRA_RECURSIVE_TARGETS([check-code-coverage])
+AS_IF([test "x$CODE_COVERAGE_ENABLED" = "xyes"], [
+    AX_APPEND_COMPILE_FLAGS([-DHAVE_GCOV], [CODE_COVERAGE_CPPFLAGS])
+])
+
 # Add --enable-oe-sdk flag to configure script
 AC_ARG_ENABLE([oe-sdk],
     AS_HELP_STRING([--enable-oe-sdk], [Link testcases absolutely against OE SDK so they can be ran within it.])
diff --git a/test/Makefile.am b/test/Makefile.am
index 3f78dda..e5ea1ff 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,18 +1,23 @@
+@CODE_COVERAGE_RULES@
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/ \
 	-I$(top_srcdir)/tools/ \
 	$(GTEST_CFLAGS) \
-	$(GMOCK_CFLAGS)
+	$(GMOCK_CFLAGS) \
+	$(CODE_COVERAGE_CPPFLAGS)
 AM_CXXFLAGS = \
 	$(SDBUSPLUS_CFLAGS) \
-	$(PHOSPHOR_LOGGING_CFLAGS)
+	$(PHOSPHOR_LOGGING_CFLAGS) \
+	$(CODE_COVERAGE_CXXFLAGS)
 AM_LDFLAGS = \
 	$(GTEST_LIBS) \
 	$(GMOCK_LIBS) \
 	-lgmock_main \
 	$(OESDK_TESTCASE_FLAGS) \
 	$(SDBUSPLUS_LIBS) \
-	$(PHOSPHOR_LOGGING_LIBS)
+	$(PHOSPHOR_LOGGING_LIBS) \
+	$(CODE_COVERAGE_LIBS)
 
 # Run all 'check' test programs
 check_PROGRAMS = \
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 05daf75..11ec485 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,12 +1,12 @@
 noinst_PROGRAMS = burn_my_bmc
 
 burn_my_bmc_SOURCES = main.cpp
-burn_my_bmc_LDADD = libupdater.la
-burn_my_bmc_CXXFLAGS = -I$(top_srcdir)
+burn_my_bmc_LDADD = libupdater.la $(CODE_COVERAGE_LIBS)
+burn_my_bmc_CXXFLAGS = -I$(top_srcdir) $(CODE_COVERAGE_CXXFLAGS)
 
 noinst_LTLIBRARIES = libupdater.la
-libupdater_la_LDFLAGS = -static
-libupdater_la_CXXFLAGS = -I$(top_srcdir)
+libupdater_la_LDFLAGS = -static $(CODE_COVERAGE_LIBS)
+libupdater_la_CXXFLAGS = -I$(top_srcdir) $(CODE_COVERAGE_CXXFLAGS)
 libupdater_la_SOURCES = \
 	updater.cpp \
 	bt.cpp \