1 # =========================================================================== 2 # https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html 3 # =========================================================================== 4 # 5 # SYNOPSIS 6 # 7 # AX_CODE_COVERAGE() 8 # 9 # DESCRIPTION 10 # 11 # Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS, 12 # CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included 13 # in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every 14 # build target (program or library) which should be built with code 15 # coverage support. Also defines CODE_COVERAGE_RULES which should be 16 # substituted in your Makefile; and $enable_code_coverage which can be 17 # used in subsequent configure output. CODE_COVERAGE_ENABLED is defined 18 # and substituted, and corresponds to the value of the 19 # --enable-code-coverage option, which defaults to being disabled. 20 # 21 # Test also for gcov program and create GCOV variable that could be 22 # substituted. 23 # 24 # Note that all optimization flags in CFLAGS must be disabled when code 25 # coverage is enabled. 26 # 27 # Usage example: 28 # 29 # configure.ac: 30 # 31 # AX_CODE_COVERAGE 32 # 33 # Makefile.am: 34 # 35 # @CODE_COVERAGE_RULES@ 36 # my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ... 37 # my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ... 38 # my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ... 39 # my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ... 40 # 41 # This results in a "check-code-coverage" rule being added to any 42 # Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module 43 # has been configured with --enable-code-coverage). Running `make 44 # check-code-coverage` in that directory will run the module's test suite 45 # (`make check`) and build a code coverage report detailing the code which 46 # was touched, then print the URI for the report. 47 # 48 # In earlier versions of this macro, CODE_COVERAGE_LDFLAGS was defined 49 # instead of CODE_COVERAGE_LIBS. They are both still defined, but use of 50 # CODE_COVERAGE_LIBS is preferred for clarity; CODE_COVERAGE_LDFLAGS is 51 # deprecated. They have the same value. 52 # 53 # This code was derived from Makefile.decl in GLib, originally licenced 54 # under LGPLv2.1+. 55 # 56 # LICENSE 57 # 58 # Copyright (c) 2012, 2016 Philip Withnall 59 # Copyright (c) 2012 Xan Lopez 60 # Copyright (c) 2012 Christian Persch 61 # Copyright (c) 2012 Paolo Borelli 62 # Copyright (c) 2012 Dan Winship 63 # Copyright (c) 2015 Bastien ROUCARIES 64 # 65 # This library is free software; you can redistribute it and/or modify it 66 # under the terms of the GNU Lesser General Public License as published by 67 # the Free Software Foundation; either version 2.1 of the License, or (at 68 # your option) any later version. 69 # 70 # This library is distributed in the hope that it will be useful, but 71 # WITHOUT ANY WARRANTY; without even the implied warranty of 72 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 73 # General Public License for more details. 74 # 75 # You should have received a copy of the GNU Lesser General Public License 76 # along with this program. If not, see <https://www.gnu.org/licenses/>. 77 78 #serial 25 79 80 AC_DEFUN([AX_CODE_COVERAGE],[ 81 dnl Check for --enable-code-coverage 82 AC_REQUIRE([AC_PROG_SED]) 83 84 # allow to override gcov location 85 AC_ARG_WITH([gcov], 86 [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], 87 [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], 88 [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) 89 90 AC_MSG_CHECKING([whether to build with code coverage support]) 91 AC_ARG_ENABLE([code-coverage], 92 AS_HELP_STRING([--enable-code-coverage], 93 [Whether to enable code coverage support]),, 94 enable_code_coverage=no) 95 96 AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes]) 97 AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) 98 AC_MSG_RESULT($enable_code_coverage) 99 100 AS_IF([ test "$enable_code_coverage" = "yes" ], [ 101 # check for gcov 102 AC_CHECK_TOOL([GCOV], 103 [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], 104 [:]) 105 AS_IF([test "X$GCOV" = "X:"], 106 [AC_MSG_ERROR([gcov is needed to do coverage])]) 107 AC_SUBST([GCOV]) 108 109 dnl Check if gcc is being used 110 AS_IF([ test "$GCC" = "no" ], [ 111 AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) 112 ]) 113 114 AC_CHECK_PROG([LCOV], [lcov], [lcov]) 115 AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) 116 117 AS_IF([ test -z "$LCOV" ], [ 118 AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed]) 119 ]) 120 121 AS_IF([ test -z "$GENHTML" ], [ 122 AC_MSG_ERROR([Could not find genhtml from the lcov package]) 123 ]) 124 125 dnl Build the code coverage flags 126 dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility 127 CODE_COVERAGE_CPPFLAGS="-DNDEBUG" 128 CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" 129 CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" 130 CODE_COVERAGE_LIBS="-lgcov" 131 CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS" 132 133 AC_SUBST([CODE_COVERAGE_CPPFLAGS]) 134 AC_SUBST([CODE_COVERAGE_CFLAGS]) 135 AC_SUBST([CODE_COVERAGE_CXXFLAGS]) 136 AC_SUBST([CODE_COVERAGE_LIBS]) 137 AC_SUBST([CODE_COVERAGE_LDFLAGS]) 138 139 [CODE_COVERAGE_RULES_CHECK=' 140 -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check 141 $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture 142 '] 143 [CODE_COVERAGE_RULES_CAPTURE=' 144 $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) 145 $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) 146 -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp 147 $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) 148 @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" 149 '] 150 [CODE_COVERAGE_RULES_CLEAN=' 151 clean: code-coverage-clean 152 distclean: code-coverage-clean 153 code-coverage-clean: 154 -$(LCOV) --directory $(top_builddir) -z 155 -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) 156 -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete 157 '] 158 ], [ 159 [CODE_COVERAGE_RULES_CHECK=' 160 @echo "Need to reconfigure with --enable-code-coverage" 161 '] 162 CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK" 163 CODE_COVERAGE_RULES_CLEAN='' 164 ]) 165 166 [CODE_COVERAGE_RULES=' 167 # Code coverage 168 # 169 # Optional: 170 # - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. 171 # Multiple directories may be specified, separated by whitespace. 172 # (Default: $(top_builddir)) 173 # - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated 174 # by lcov for code coverage. (Default: 175 # $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) 176 # - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage 177 # reports to be created. (Default: 178 # $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) 179 # - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, 180 # set to 0 to disable it and leave empty to stay with the default. 181 # (Default: empty) 182 # - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov 183 # instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) 184 # - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov 185 # instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) 186 # - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov 187 # - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the 188 # collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) 189 # - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov 190 # instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) 191 # - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering 192 # lcov instance. (Default: empty) 193 # - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov 194 # instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) 195 # - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the 196 # genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) 197 # - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml 198 # instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) 199 # - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore 200 # 201 # The generated report will be titled using the $(PACKAGE_NAME) and 202 # $(PACKAGE_VERSION). In order to add the current git hash to the title, 203 # use the git-version-gen script, available online. 204 205 # Optional variables 206 CODE_COVERAGE_DIRECTORY ?= $(top_builddir) 207 CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info 208 CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage 209 CODE_COVERAGE_BRANCH_COVERAGE ?= 210 CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ 211 --rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) 212 CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) 213 CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" 214 CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) 215 CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) 216 CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= 217 CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) 218 CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ 219 $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ 220 --rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) 221 CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) 222 CODE_COVERAGE_IGNORE_PATTERN ?= 223 224 GITIGNOREFILES ?= 225 GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) 226 227 code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) 228 code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) 229 code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ 230 $(CODE_COVERAGE_OUTPUT_FILE); 231 code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) 232 code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) 233 code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ 234 $(CODE_COVERAGE_IGNORE_PATTERN); 235 code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) 236 code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) 237 code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); 238 code_coverage_quiet = $(code_coverage_quiet_$(V)) 239 code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) 240 code_coverage_quiet_0 = --quiet 241 242 # sanitizes the test-name: replaces with underscores: dashes and dots 243 code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) 244 245 # Use recursive makes in order to ignore errors during check 246 check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"' 247 248 # Capture code coverage data 249 code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"' 250 251 # Hook rule executed before code-coverage-capture, overridable by the user 252 code-coverage-capture-hook: 253 254 '"$CODE_COVERAGE_RULES_CLEAN"' 255 256 A''M_DISTCHECK_CONFIGURE_FLAGS ?= 257 A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage 258 259 .PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean 260 '] 261 262 AC_SUBST([CODE_COVERAGE_RULES]) 263 m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])]) 264 ]) 265