|
| 1 | +# =========================================================================== |
| 2 | +# https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html |
| 3 | +# =========================================================================== |
| 4 | +# |
| 5 | +# SYNOPSIS |
| 6 | +# |
| 7 | +# AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off) |
| 8 | +# AX_VALGRIND_CHECK() |
| 9 | +# |
| 10 | +# DESCRIPTION |
| 11 | +# |
| 12 | +# AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows |
| 13 | +# running `make check` under a variety of Valgrind tools to check for |
| 14 | +# memory and threading errors. |
| 15 | +# |
| 16 | +# Defines VALGRIND_CHECK_RULES which should be substituted in your |
| 17 | +# Makefile; and $enable_valgrind which can be used in subsequent configure |
| 18 | +# output. VALGRIND_ENABLED is defined and substituted, and corresponds to |
| 19 | +# the value of the --enable-valgrind option, which defaults to being |
| 20 | +# enabled if Valgrind is installed and disabled otherwise. Individual |
| 21 | +# Valgrind tools can be disabled via --disable-valgrind-<tool>, the |
| 22 | +# default is configurable via the AX_VALGRIND_DFLT command or is to use |
| 23 | +# all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT |
| 24 | +# calls must be made before the call to AX_VALGRIND_CHECK. |
| 25 | +# |
| 26 | +# If unit tests are written using a shell script and automake's |
| 27 | +# LOG_COMPILER system, the $(VALGRIND) variable can be used within the |
| 28 | +# shell scripts to enable Valgrind, as described here: |
| 29 | +# |
| 30 | +# https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html |
| 31 | +# |
| 32 | +# Usage example: |
| 33 | +# |
| 34 | +# configure.ac: |
| 35 | +# |
| 36 | +# AX_VALGRIND_DFLT([sgcheck], [off]) |
| 37 | +# AX_VALGRIND_CHECK |
| 38 | +# |
| 39 | +# in each Makefile.am with tests: |
| 40 | +# |
| 41 | +# @VALGRIND_CHECK_RULES@ |
| 42 | +# VALGRIND_SUPPRESSIONS_FILES = my-project.supp |
| 43 | +# EXTRA_DIST = my-project.supp |
| 44 | +# |
| 45 | +# This results in a "check-valgrind" rule being added. Running `make |
| 46 | +# check-valgrind` in that directory will recursively run the module's test |
| 47 | +# suite (`make check`) once for each of the available Valgrind tools (out |
| 48 | +# of memcheck, helgrind and drd) while the sgcheck will be skipped unless |
| 49 | +# enabled again on the commandline with --enable-valgrind-sgcheck. The |
| 50 | +# results for each check will be output to test-suite-$toolname.log. The |
| 51 | +# target will succeed if there are zero errors and fail otherwise. |
| 52 | +# |
| 53 | +# Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in |
| 54 | +# memcheck, helgrind, drd and sgcheck. These are useful because often only |
| 55 | +# some of those tools can be ran cleanly on a codebase. |
| 56 | +# |
| 57 | +# The macro supports running with and without libtool. |
| 58 | +# |
| 59 | +# LICENSE |
| 60 | +# |
| 61 | +# Copyright (c) 2014, 2015, 2016 Philip Withnall <philip.withnall@collabora.co.uk> |
| 62 | +# |
| 63 | +# Copying and distribution of this file, with or without modification, are |
| 64 | +# permitted in any medium without royalty provided the copyright notice |
| 65 | +# and this notice are preserved. This file is offered as-is, without any |
| 66 | +# warranty. |
| 67 | + |
| 68 | +#serial 17 |
| 69 | + |
| 70 | +dnl Configured tools |
| 71 | +m4_define([valgrind_tool_list], [[memcheck], [helgrind], [drd], [sgcheck]]) |
| 72 | +m4_set_add_all([valgrind_exp_tool_set], [sgcheck]) |
| 73 | +m4_foreach([vgtool], [valgrind_tool_list], |
| 74 | + [m4_define([en_dflt_valgrind_]vgtool, [on])]) |
| 75 | + |
| 76 | +AC_DEFUN([AX_VALGRIND_DFLT],[ |
| 77 | + m4_define([en_dflt_valgrind_$1], [$2]) |
| 78 | +])dnl |
| 79 | + |
| 80 | +AM_EXTRA_RECURSIVE_TARGETS([check-valgrind]) |
| 81 | +m4_foreach([vgtool], [valgrind_tool_list], |
| 82 | + [AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)]) |
| 83 | + |
| 84 | +AC_DEFUN([AX_VALGRIND_CHECK],[ |
| 85 | + dnl Check for --enable-valgrind |
| 86 | + AC_ARG_ENABLE([valgrind], |
| 87 | + [AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])], |
| 88 | + [enable_valgrind=$enableval],[enable_valgrind=]) |
| 89 | +
|
| 90 | + AS_IF([test "$enable_valgrind" != "no"],[ |
| 91 | + # Check for Valgrind. |
| 92 | + AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind]) |
| 93 | + AS_IF([test "$VALGRIND" = ""],[ |
| 94 | + AS_IF([test "$enable_valgrind" = "yes"],[ |
| 95 | + AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind]) |
| 96 | + ],[ |
| 97 | + enable_valgrind=no |
| 98 | + ]) |
| 99 | + ],[ |
| 100 | + enable_valgrind=yes |
| 101 | + ]) |
| 102 | + ]) |
| 103 | +
|
| 104 | + AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) |
| 105 | + AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind]) |
| 106 | +
|
| 107 | + # Check for Valgrind tools we care about. |
| 108 | + [valgrind_enabled_tools=] |
| 109 | + m4_foreach([vgtool],[valgrind_tool_list],[ |
| 110 | + AC_ARG_ENABLE([valgrind-]vgtool, |
| 111 | + m4_if(m4_defn([en_dflt_valgrind_]vgtool),[off],dnl |
| 112 | +[AS_HELP_STRING([--enable-valgrind-]vgtool, [Whether to use ]vgtool[ during the Valgrind tests])],dnl |
| 113 | +[AS_HELP_STRING([--disable-valgrind-]vgtool, [Whether to skip ]vgtool[ during the Valgrind tests])]), |
| 114 | + [enable_valgrind_]vgtool[=$enableval], |
| 115 | + [enable_valgrind_]vgtool[=]) |
| 116 | + AS_IF([test "$enable_valgrind" = "no"],[ |
| 117 | + enable_valgrind_]vgtool[=no], |
| 118 | + [test "$enable_valgrind_]vgtool[" ]dnl |
| 119 | +m4_if(m4_defn([en_dflt_valgrind_]vgtool), [off], [= "yes"], [!= "no"]),[ |
| 120 | + AC_CACHE_CHECK([for Valgrind tool ]vgtool, |
| 121 | + [ax_cv_valgrind_tool_]vgtool,[ |
| 122 | + ax_cv_valgrind_tool_]vgtool[=no |
| 123 | + m4_set_contains([valgrind_exp_tool_set],vgtool, |
| 124 | + [m4_define([vgtoolx],[exp-]vgtool)], |
| 125 | + [m4_define([vgtoolx],vgtool)]) |
| 126 | + AS_IF([`$VALGRIND --tool=]vgtoolx[ --help >/dev/null 2>&1`],[ |
| 127 | + ax_cv_valgrind_tool_]vgtool[=yes |
| 128 | + ]) |
| 129 | + ]) |
| 130 | + AS_IF([test "$ax_cv_valgrind_tool_]vgtool[" = "no"],[ |
| 131 | + AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ |
| 132 | + AC_MSG_ERROR([Valgrind does not support ]vgtool[; reconfigure with --disable-valgrind-]vgtool) |
| 133 | + ],[ |
| 134 | + enable_valgrind_]vgtool[=no |
| 135 | + ]) |
| 136 | + ],[ |
| 137 | + enable_valgrind_]vgtool[=yes |
| 138 | + ]) |
| 139 | + ]) |
| 140 | + AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ |
| 141 | + valgrind_enabled_tools="$valgrind_enabled_tools ]m4_bpatsubst(vgtool,[^exp-])[" |
| 142 | + ]) |
| 143 | + AC_SUBST([ENABLE_VALGRIND_]vgtool,[$enable_valgrind_]vgtool) |
| 144 | + ]) |
| 145 | + AC_SUBST([valgrind_tools],["]m4_join([ ], valgrind_tool_list)["]) |
| 146 | + AC_SUBST([valgrind_enabled_tools],[$valgrind_enabled_tools]) |
| 147 | +
|
| 148 | +[VALGRIND_CHECK_RULES=' |
| 149 | +# Valgrind check |
| 150 | +# |
| 151 | +# Optional: |
| 152 | +# - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions |
| 153 | +# files to load. (Default: empty) |
| 154 | +# - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. |
| 155 | +# (Default: --num-callers=30) |
| 156 | +# - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: |
| 157 | +# memcheck, helgrind, drd, sgcheck). (Default: various) |
| 158 | +
|
| 159 | +# Optional variables |
| 160 | +VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) |
| 161 | +VALGRIND_FLAGS ?= --num-callers=30 |
| 162 | +VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no |
| 163 | +VALGRIND_helgrind_FLAGS ?= --history-level=approx |
| 164 | +VALGRIND_drd_FLAGS ?= |
| 165 | +VALGRIND_sgcheck_FLAGS ?= |
| 166 | +
|
| 167 | +# Internal use |
| 168 | +valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) |
| 169 | +
|
| 170 | +valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) |
| 171 | +valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) |
| 172 | +valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) |
| 173 | +valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) |
| 174 | +
|
| 175 | +valgrind_quiet = $(valgrind_quiet_$(V)) |
| 176 | +valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) |
| 177 | +valgrind_quiet_0 = --quiet |
| 178 | +valgrind_v_use = $(valgrind_v_use_$(V)) |
| 179 | +valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY)) |
| 180 | +valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):; |
| 181 | +
|
| 182 | +# Support running with and without libtool. |
| 183 | +ifneq ($(LIBTOOL),) |
| 184 | +valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute |
| 185 | +else |
| 186 | +valgrind_lt = |
| 187 | +endif |
| 188 | +
|
| 189 | +# Use recursive makes in order to ignore errors during check |
| 190 | +check-valgrind-am: |
| 191 | +ifeq ($(VALGRIND_ENABLED),yes) |
| 192 | + $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \ |
| 193 | + $(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool)) |
| 194 | +else |
| 195 | + @echo "Need to reconfigure with --enable-valgrind" |
| 196 | +endif |
| 197 | +
|
| 198 | +# Valgrind running |
| 199 | +VALGRIND_TESTS_ENVIRONMENT = \ |
| 200 | + $(TESTS_ENVIRONMENT) \ |
| 201 | + env VALGRIND=$(VALGRIND) \ |
| 202 | + G_SLICE=always-malloc,debug-blocks \ |
| 203 | + G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly |
| 204 | +
|
| 205 | +VALGRIND_LOG_COMPILER = \ |
| 206 | + $(valgrind_lt) \ |
| 207 | + $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) |
| 208 | +
|
| 209 | +define valgrind_tool_rule |
| 210 | +check-valgrind-$(1)-am: |
| 211 | +ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes) |
| 212 | +ifneq ($$(TESTS),) |
| 213 | + $$(valgrind_v_use)$$(MAKE) check-TESTS \ |
| 214 | + TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \ |
| 215 | + LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \ |
| 216 | + LOG_FLAGS="$$(valgrind_$(1)_flags)" \ |
| 217 | + TEST_SUITE_LOG=test-suite-$(1).log |
| 218 | +endif |
| 219 | +else ifeq ($$(VALGRIND_ENABLED),yes) |
| 220 | + @echo "Need to reconfigure with --enable-valgrind-$(1)" |
| 221 | +else |
| 222 | + @echo "Need to reconfigure with --enable-valgrind" |
| 223 | +endif |
| 224 | +endef |
| 225 | +
|
| 226 | +$(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool)))) |
| 227 | +
|
| 228 | +A''M_DISTCHECK_CONFIGURE_FLAGS ?= |
| 229 | +A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind |
| 230 | +
|
| 231 | +MOSTLYCLEANFILES ?= |
| 232 | +MOSTLYCLEANFILES += $(valgrind_log_files) |
| 233 | +
|
| 234 | +.PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools)) |
| 235 | +'] |
| 236 | +
|
| 237 | + AC_SUBST([VALGRIND_CHECK_RULES]) |
| 238 | + m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])]) |
| 239 | +]) |
0 commit comments