Makefile.maint 23.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
# This is reported not to work with make-3.79.1
# ME := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
ME := Makefile.maint

# Do not save the original name or timestamp in the .tar.gz file.
# Use --rsyncable if available.
gzip_rsyncable := \
  $(shell gzip --help 2>/dev/null|grep rsyncable >/dev/null && echo --rsyncable)
GZIP_ENV = '--no-name --best $(gzip_rsyncable)'

11
VC_LIST = $(top_srcdir)/build-aux/vc-list-files
12

13
VC_LIST_EXCEPT = \
14
  $(VC_LIST) -C $(top_srcdir) | if test -f .x-$@; then grep -vEf .x-$@; else grep -v ChangeLog; fi
15 16 17 18 19 20

# Prevent programs like 'sort' from considering distinct strings to be equal.
# Doing it here saves us from having to set LC_ALL elsewhere in this file.
export LC_ALL = C

# Collect the names of rules starting with `sc_'.
21 22
syntax-check-rules := $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' \
                        $(srcdir)/$(ME))
23 24 25 26
.PHONY: $(syntax-check-rules)

local-checks-available = \
  po-check copyright-check m4-check author_mark_check \
27
  patch-check strftime-check $(syntax-check-rules) \
28 29 30 31 32 33 34
  makefile_path_separator_check \
  makefile-check check-AUTHORS
.PHONY: $(local-checks-available)

local-check := $(filter-out $(local-checks-to-skip), $(local-checks-available))

syntax-check: $(local-check)
35 36 37 38
#	@grep -nE '#  *include <(limits|std(def|arg|bool))\.h>'		\
#	    $$(find -type f -name '*.[chly]') &&			\
#	  { echo '$(ME): found conditional include' 1>&2;		\
#	    exit 1; } || :
39

40 41 42 43 44
#	grep -nE '^#  *include <(string|stdlib)\.h>'			\
#	    $(srcdir)/{lib,src}/*.[chy] &&				\
#	  { echo '$(ME): FIXME' 1>&2;					\
#	    exit 1; } || :
# FIXME: don't allow `#include .strings\.h' anywhere
45 46

sc_avoid_if_before_free:
47 48
	@$(srcdir)/build-aux/useless-if-before-free			\
		$(useless_free_options)					\
49
	    $$($(VC_LIST_EXCEPT)) &&					\
50 51 52
	  { echo '$(ME): found useless "if" before "free" above' 1>&2;	\
	    exit 1; } || :

53 54 55
# Avoid uses of write(2).  Either switch to streams (fwrite), or use
# the safewrite wrapper.
sc_avoid_write:
56 57
	@if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then		\
	  grep '\<write *(' $$($(VC_LIST_EXCEPT) | grep '\.c$$') &&	\
58 59 60 61 62 63
	    { echo "$(ME): the above files use write;"			\
	      " consider using the safewrite wrapper instead"		\
		  1>&2; exit 1; } || :;					\
	else :;								\
	fi

64
sc_cast_of_argument_to_free:
65
	@grep -nE '\<free \(\(' $$($(VC_LIST_EXCEPT)) &&		\
66 67 68 69
	  { echo '$(ME): don'\''t cast free argument' 1>&2;		\
	    exit 1; } || :

sc_cast_of_x_alloc_return_value:
70
	@grep -nE '\*\) *x(m|c|re)alloc\>' $$($(VC_LIST_EXCEPT)) &&	\
71 72 73 74
	  { echo '$(ME): don'\''t cast x*alloc return value' 1>&2;	\
	    exit 1; } || :

sc_cast_of_alloca_return_value:
75
	@grep -nE '\*\) *alloca\>' $$($(VC_LIST_EXCEPT)) &&		\
76 77 78 79
	  { echo '$(ME): don'\''t cast alloca return value' 1>&2;	\
	    exit 1; } || :

sc_space_tab:
80
	@grep -n '[ ]	' $$($(VC_LIST_EXCEPT)) &&			\
81 82 83
	  { echo '$(ME): found SPACE-TAB sequence; remove the SPACE'	\
		1>&2; exit 1; } || :

84 85 86 87 88 89 90 91
cvs_keywords = \
  Author|Date|Header|Id|Name|Locker|Log|RCSfile|Revision|Source|State

sc_prohibit_cvs_keyword:
	@grep -nE '\$$($(cvs_keywords))\$$' $$($(VC_LIST_EXCEPT)) &&	\
	  { echo '$(ME): do not use CVS keyword expansion '		\
		1>&2; exit 1; } || :

92 93 94 95
# Don't use *scanf or the old ato* functions in `real' code.
# They provide no error checking mechanism.
# Instead, use strto* functions.
sc_prohibit_atoi_atof:
96
	@grep -nE '\<([fs]?scanf|ato([filq]|ll))\>' $$($(VC_LIST_EXCEPT)) && \
97 98 99 100
	  { echo '$(ME): do not use *scan''f, ato''f, ato''i, ato''l, ato''ll, ato''q, or ss''canf'	\
		1>&2; exit 1; } || :

# Use STREQ rather than comparing strcmp == 0, or != 0.
101
# Similarly, use STREQLEN or STRPREFIX rather than strncmp.
102
sc_prohibit_strcmp:
103
	@grep -nE '! *str''n?cmp *\(|\<str''n?cmp *\([^)]+\) *=='	\
104
	    $$($(VC_LIST_EXCEPT)) &&					\
105 106 107 108 109 110 111 112 113 114 115 116
	  { echo '$(ME): use STREQ in place of the above uses of str''cmp' \
		1>&2; exit 1; } || :

# Using EXIT_SUCCESS as the first argument to error is misleading,
# since when that parameter is 0, error does not exit.  Use `0' instead.
sc_error_exit_success:
	@grep -nF 'error (EXIT_SUCCESS,'				\
	    $$(find -type f -name '*.[chly]') &&			\
	  { echo '$(ME): found error (EXIT_SUCCESS' 1>&2;		\
	    exit 1; } || :

sc_file_system:
117
	@grep -ni 'file''system' $$($(VC_LIST_EXCEPT)) &&		\
118 119 120 121 122
	  { echo '$(ME): found use of "file''system";'			\
	    'rewrite to use "file system"' 1>&2;			\
	    exit 1; } || :

sc_no_have_config_h:
123
	@grep -n '^# *if.*HAVE''_CONFIG_H' $$($(VC_LIST_EXCEPT)) &&	\
124 125 126 127 128
	  { echo '$(ME): found use of HAVE''_CONFIG_H; remove'		\
		1>&2; exit 1; } || :

# Nearly all .c files must include <config.h>.
sc_require_config_h:
129
	@if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then		\
130
	  grep -L '^# *include <config\.h>'				\
131
		$$($(VC_LIST_EXCEPT) | grep '\.c$$')			\
132 133 134 135 136 137
	      | grep . &&						\
	  { echo '$(ME): the above files do not include <config.h>'	\
		1>&2; exit 1; } || :;					\
	else :;								\
	fi

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
# You must include <config.h> before including any other header file.
sc_require_config_h_first:
	@if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then		\
	  fail=0;							\
	  for i in $$($(VC_LIST_EXCEPT) | grep '\.c$$'); do		\
	    grep '^# *include\>' $$i | sed 1q				\
		| grep '^# *include <config\.h>' > /dev/null		\
	      || { echo $$i; fail=1; };					\
	  done;								\
	  test $$fail = 1 &&						\
	    { echo '$(ME): the above files include some other header'	\
		'before <config.h>' 1>&2; exit 1; } || :;		\
	else :;								\
	fi

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
# To use this "command" macro, you must first define two shell variables:
# h: the header, enclosed in <> or ""
# re: a regular expression that matches IFF something provided by $h is used.
define _header_without_use
  h_esc=`echo "$$h"|sed 's/\./\\./'`;					\
  if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then			\
    files=$$(grep -l '^# *include '"$$h_esc"				\
	     $$($(VC_LIST_EXCEPT) | grep '\.c$$')) &&			\
    grep -LE "$$re" $$files | grep . &&					\
      { echo "$(ME): the above files include $$h but don't use it"	\
	1>&2; exit 1; } || :;						\
  else :;								\
  fi
endef

168 169
# Prohibit the inclusion of assert.h without an actual use of assert.
sc_prohibit_assert_without_use:
170 171 172 173 174
	@h='<assert.h>' re='\<assert *\(' $(_header_without_use)

# Prohibit the inclusion of getopt.h without an actual use.
sc_prohibit_getopt_without_use:
	@h='<getopt.h>' re='\<getopt(_long)? *\(' $(_header_without_use)
175 176 177

# Don't include quotearg.h unless you use one of its functions.
sc_prohibit_quotearg_without_use:
178
	@h='"quotearg.h"' re='\<quotearg(_[^ ]+)? *\(' $(_header_without_use)
179 180 181

# Don't include quote.h unless you use one of its functions.
sc_prohibit_quote_without_use:
182
	@h='"quote.h"' re='\<quote(_n)? *\(' $(_header_without_use)
183

184 185 186 187 188 189 190 191 192 193
# Prohibit the inclusion of c-ctype.h without an actual use.
sc_prohibit_c_ctype_without_use:
	@h='[<"]c-ctype.h[">]' re='\<c_($(ctype_re)) *\(' $(_header_without_use)

# Prohibit the inclusion of <ctype.h>.
sc_prohibit_ctype_h:
	@grep -E '^# *include  *<ctype\.h>' $$($(VC_LIST_EXCEPT)) &&	\
	  { echo "$(ME): don't use ctype.h; instead, use c-ctype.h"	\
		1>&2; exit 1; } || :

194 195
sc_obsolete_symbols:
	@grep -nE '\<(HAVE''_FCNTL_H|O''_NDELAY)\>'			\
196
	     $$($(VC_LIST_EXCEPT)) &&					\
197 198 199 200 201 202
	  { echo '$(ME): do not use HAVE''_FCNTL_H or O''_NDELAY'	\
		1>&2; exit 1; } || :

# FIXME: warn about definitions of EXIT_FAILURE, EXIT_SUCCESS, STREQ

# Each nonempty line must start with a year number, or a TAB.
203 204 205
# Or day-of-week+space.
changelog_entry_header_regexp = \
  ([12][0-9][0-9][0-9]|	.|(Mon|Tue|Wed|Thu|Fri|Sat|Sun) )
206
sc_changelog:
207 208
	@grep -Evn '(^$$|^$(changelog_entry_header_regexp))'		\
	  $$(find . -maxdepth 2 -name ChangeLog) &&			\
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	  { echo '$(ME): found unexpected prefix in a ChangeLog' 1>&2;	\
	    exit 1; } || :

# Ensure that dd's definition of LONGEST_SYMBOL stays in sync
# with the strings from the two affected variables.
dd_c = $(srcdir)/src/dd.c
sc_dd_max_sym_length:
ifneq ($(wildcard $(dd_c)),)
	@len=$$( (sed -n '/conversions\[\] =$$/,/^};/p' $(dd_c);\
		 sed -n '/flags\[\] =$$/,/^};/p' $(dd_c) )	\
		|sed -n '/"/s/^[^"]*"\([^"]*\)".*/\1/p'		\
	      | wc --max-line-length);				\
	max=$$(sed -n '/^#define LONGEST_SYMBOL /s///p' $(dd_c)	\
	      |tr -d '"' | wc --max-line-length);		\
	if test "$$len" = "$$max"; then :; else			\
	  echo 'dd.c: LONGEST_SYMBOL is not longest' 1>&2;	\
	  exit 1;						\
	fi
endif

# Many m4 macros names once began with `jm_'.
# On 2004-04-13, they were all changed to start with gl_ instead.
# Make sure that none are inadvertently reintroduced.
sc_prohibit_jm_in_m4:
	@grep -nE 'jm_[A-Z]'					\
234
		$$($(VC_LIST) m4 |grep '\.m4$$'; echo /dev/null) && \
235 236 237 238 239 240 241
	    { echo '$(ME): do not use jm_ in m4 macro names'	\
	      1>&2; exit 1; } || :

sc_root_tests:
	@if test -d tests \
	      && grep check-root tests/Makefile.am>/dev/null 2>&1; then \
	t1=sc-root.expected; t2=sc-root.actual;				\
242 243
	grep -nl '^require_root_$$'					\
	  $$($(VC_LIST) tests) |sed s,tests,., |sort > $$t1;		\
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
	sed -n 's,	cd \([^ ]*\) .*MAKE..check TESTS=\(.*\),./\1/\2,p' \
	  $(srcdir)/tests/Makefile.am |sort > $$t2;			\
	diff -u $$t1 $$t2 || diff=1;					\
	rm -f $$t1 $$t2;						\
	test "$$diff"							\
	  && { echo 'tests/Makefile.am: missing check-root action'>&2;	\
	       exit 1; } || :;						\
	fi

headers_with_interesting_macro_defs = \
  exit.h	\
  fcntl_.h	\
  fnmatch_.h	\
  intprops.h	\
  inttypes_.h	\
  lchown.h	\
  openat.h	\
  stat-macros.h	\
  stdint_.h

# Create a list of regular expressions matching the names
# of macros that are guaranteed by parts of gnulib to be defined.
.re-defmac:
	@(cd $(srcdir)/lib;						\
	  for f in $(headers_with_interesting_macro_defs); do		\
	    test -f $$f &&						\
	      sed -n '/^# *define \([^_ (][^ (]*\)[ (].*/s//\1/p' $$f;	\
	   done;							\
	 ) | sort -u							\
	   | grep -Ev 'ATTRIBUTE_NORETURN|SIZE_MAX'			\
	   | sed 's/^/^# *define /'					\
	  > $@-t
	@mv $@-t $@

# Don't define macros that we already get from gnulib header files.
sc_always_defined_macros: .re-defmac
	@if test -f $(srcdir)/src/system.h; then			\
	  trap 'rc=$$?; rm -f .re-defmac; exit $$rc' 0 1 2 3 15;	\
282
	  grep -f .re-defmac $$($(VC_LIST))				\
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
	    && { echo '$(ME): define the above via some gnulib .h file'	\
		  1>&2;  exit 1; } || :;				\
	fi

# Create a list of regular expressions matching the names
# of files included from system.h.  Exclude a couple.
.re-list:
	@sed -n '/^# *include /s///p' $(srcdir)/src/system.h \
	  | grep -Ev 'sys/(param|file)\.h' \
	  | sed 's/ .*//;;s/^["<]/^# *include [<"]/;s/\.h[">]$$/\\.h[">]/' \
	  > $@-t
	@mv $@-t $@

# Files in src/ should not include directly any of
# the headers already included via system.h.
sc_system_h_headers: .re-list
	@if test -f $(srcdir)/src/system.h; then			\
	  trap 'rc=$$?; rm -f .re-list; exit $$rc' 0 1 2 3 15;		\
	  grep -nE -f .re-list						\
302
	      $$($(VC_LIST) src |					\
303 304 305 306 307 308 309 310
		 grep -Ev '((copy|system)\.h|parse-gram\.c)$$')		\
	    && { echo '$(ME): the above are already included via system.h'\
		  1>&2;  exit 1; } || :;				\
	fi

sc_sun_os_names:
	@grep -nEi \
	    'solaris[^[:alnum:]]*2\.(7|8|9|[1-9][0-9])|sunos[^[:alnum:]][6-9]' \
311
	    $$($(VC_LIST_EXCEPT)) &&					\
312 313 314 315
	  { echo '$(ME): found misuse of Sun OS version numbers' 1>&2;	\
	    exit 1; } || :

sc_the_the:
316
	@grep -ni '\<the ''the\>' $$($(VC_LIST_EXCEPT)) &&		\
317 318 319 320 321 322 323
	  { echo '$(ME): found use of "the ''the";' 1>&2;		\
	    exit 1; } || :

sc_tight_scope:
	$(MAKE) -C src $@

sc_trailing_blank:
324
	@grep -n '[	 ]$$' $$($(VC_LIST_EXCEPT)) &&			\
325 326 327
	  { echo '$(ME): found trailing blank(s)'			\
		1>&2; exit 1; } || :

328 329 330 331 332 333 334 335
# Ensure that no C source file uses TABs for indentation.
# Also match *.h.in files, to get libvirt.h.in.
# Exclude files in gnulib, since they're imported.
sc_TAB_in_indentation:
	@grep -lE '^ *	' /dev/null					\
	     $$($(VC_LIST_EXCEPT)					\
	        | grep -E '\.[ch](\.in)?$$'				\
	        | grep -v '^gnulib/') &&				\
336 337
	  { echo '$(ME): found TAB(s) used for indentation in C sources;'\
	      'use spaces' 1>&2; exit 1; } || :
338

339 340 341
ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper

342
sc_avoid_ctype_macros:
343
	@grep -E '\b($(ctype_re)) *\(' /dev/null			\
344 345
	     $$($(VC_LIST_EXCEPT)) &&					\
	  { echo "$(ME): don't use ctype macros (use c-ctype.h)"	\
346 347
		1>&2; exit 1; } || :

348 349 350 351 352 353
# Match lines like the following, but where there is only one space
# between the options and the description:
#   -D, --all-repeated[=delimit-method]  print all duplicate lines\n
longopt_re = --[a-z][0-9A-Za-z-]*(\[?=[0-9A-Za-z-]*\]?)?
sc_two_space_separator_in_usage:
	@grep -nE '^   *(-[A-Za-z],)? $(longopt_re) [^ ].*\\$$'		\
354
	    $$($(VC_LIST_EXCEPT)) &&					\
355 356 357 358
	  { echo "$(ME): help2man requires at least two spaces between"; \
	    echo "$(ME): an option and its description"; \
		1>&2; exit 1; } || :

359 360 361 362 363 364 365 366 367 368 369 370 371 372
msg_gen_function =
msg_gen_function += DISABLE_fprintf
msg_gen_function += virXendError
msg_gen_function += virXMLError
msg_gen_function += virHashError
msg_gen_function += virConfError
msg_gen_function += virTestError
msg_gen_function += virLibConnError
msg_gen_function += virStorageReportError
msg_gen_function += virxmlRpcError
msg_gen_function += virLog
msg_gen_function += qemudLog
msg_gen_function += remoteDispatchError
msg_gen_function += virStorageLog
373
msg_gen_function += xenXMError
374
msg_gen_function += ReportError
375
msg_gen_function += qemudReportError
376
msg_gen_function += openvzLog
D
Daniel Veillard 已提交
377
msg_gen_function += openvzError
378
msg_gen_function += virDomainReportError
379 380
msg_gen_function += virReportErrorHelper
msg_gen_function += lxcError
381
msg_gen_function += umlError
382

383 384 385
# Uncomment the following and run "make syntax-check" to see diagnostics
# that are not yet marked for translation, but that need to be rewritten
# so that they are translatable.
386
# msg_gen_function += error
387 388 389 390 391
# msg_gen_function += virXenError
# msg_gen_function += testError

func_or := $(shell printf '$(msg_gen_function)'|tr -s '[[:space:]]' '|')
func_re := ($(func_or))
392

393 394
# Look for diagnostics that aren't marked for translation.
# This won't find any for which error's format string is on a separate line.
395 396 397
# The sed filters eliminate false-positives like these:
#    _("...: "
#    "%s", _("no storage vol w..."
398 399
sc_unmarked_diagnostics:
	@grep -nE							\
400
            '\<$(func_re) \([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT))	\
401 402 403
	  | grep -v '_''(' &&						\
	  { echo '$(ME): found unmarked diagnostic(s)' 1>&2;		\
	    exit 1; } || :
404 405
	@{ grep     -nE '\<$(func_re) *\(.*;$$' $$($(VC_LIST_EXCEPT));   \
	   grep -A1 -nE '\<$(func_re) *\(.*,$$' $$($(VC_LIST_EXCEPT)); } \
406 407
	   | sed 's/_("[^"][^"]*"//;s/[	 ]"%s"//'			\
	   | grep '[	 ]"' &&						\
408 409
	  { echo '$(ME): found unmarked diagnostic(s)' 1>&2;		\
	    exit 1; } || :
410

411
sc_prohibit_virBufferAdd_with_string_literal:
412
	@grep -nE '\<virBufferAdd *\([^,]+, *"[^"]' $$($(VC_LIST_EXCEPT)) && \
413 414 415
	  { echo '$(ME): use virBufferAddLit, not virBufferAdd,' \
	      'with a string literal' 1>&2; exit 1; } || :

416 417 418 419 420 421
# Not only do they fail to deal well with ipv6, but the gethostby*
# functions are also not thread-safe.
sc_prohibit_gethostby:
	@grep -nE '\<gethostby(addr|name2?) *\(' $$($(VC_LIST_EXCEPT)) && \
	  { echo '$(ME): use getaddrinfo, not gethostby*' 1>&2; exit 1; } || :

422 423 424
# Avoid useless parentheses like those in this example:
# #if defined (SYMBOL) || defined (SYM2)
sc_useless_cpp_parens:
425
	@grep -n '^# *if .*defined *(' $$($(VC_LIST_EXCEPT)) &&		\
426 427 428 429 430
	  { echo '$(ME): found useless parentheses in cpp directive'	\
		1>&2; exit 1; } || :

# Require the latest GPL.
sc_GPL_version:
431
	@grep -n 'either ''version [^3]' $$($(VC_LIST_EXCEPT)) &&	\
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
	  { echo '$(ME): GPL vN, N!=3' 1>&2; exit 1; } || :

# Ensure that the c99-to-c89 patch applies cleanly.
patch-check:
	rm -rf src-c89 $@.1 $@.2
	cp -a src src-c89
	(cd src-c89; patch -p1 -V never --fuzz=0) < src/c99-to-c89.diff \
	  > $@.1 2>&1
	if test "$$REGEN_PATCH" = yes; then \
	  diff -upr src src-c89 | sed 's,src-c89/,src/,' \
	    | grep -v '^Only in' > new-diff || : ; fi
	grep -v '^patching file ' $@.1 > $@.2 || :
	msg=ok; test -s $@.2 && msg='fuzzy patch' || : ;	\
	rm -f src-c89/*.o || msg='rm failed';			\
	$(MAKE) -C src-c89 CFLAGS='-Wdeclaration-after-statement -Werror' \
	  || msg='compile failure with extra options';		\
	test "$$msg" = ok && rm -rf src-c89 $@.1 $@.2 || echo "$$msg" 1>&2; \
	test "$$msg" = ok

# Ensure that date's --help output stays in sync with the info
# documentation for GNU strftime.  The only exception is %N,
# which date accepts but GNU strftime does not.
extract_char = sed 's/^[^%][^%]*%\(.\).*/\1/'
strftime-check:
J
Jim Meyering 已提交
456
	@if test -f $(srcdir)/src/date.c; then				\
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
	  grep '^  %.  ' $(srcdir)/src/date.c | sort			\
	    | $(extract_char) > $@-src;					\
	  { echo N;							\
	    info libc date calendar format | grep '^    `%.'\'		\
	      | $(extract_char); } | sort > $@-info;			\
	  diff -u $@-src $@-info || exit 1;				\
	  rm -f $@-src $@-info;						\
	fi

check-AUTHORS:
	$(MAKE) -C src $@

# Ensure that we use only the standard $(VAR) notation,
# not @...@ in Makefile.am, now that we can rely on automake
# to emit a definition for each substituted variable.
makefile-check:
	grep -nE '@[A-Z_0-9]+@' `find . -name Makefile.am` \
	  && { echo 'Makefile.maint: use $$(...), not @...@' 1>&2; exit 1; } || :

news-date-check: NEWS
	today=`date +%Y-%m-%d`;						\
	if head NEWS | grep '^\*.* $(VERSION_REGEXP) ('$$today')'	\
	    >/dev/null; then						\
	  :;								\
	else								\
	  echo "version or today's date is not in NEWS" 1>&2;		\
	  exit 1;							\
	fi

changelog-check:
	if head ChangeLog | grep 'Version $(VERSION_REGEXP)\.$$'	\
	    >/dev/null; then						\
	  :;								\
	else								\
	  echo "$(VERSION) not in ChangeLog" 1>&2;			\
	  exit 1;							\
	fi

m4-check:
496
	@grep -n 'AC_DEFUN([^[]' $(top_srcdir)/m4/*.m4 \
497 498 499
	  && { echo 'Makefile.maint: quote the first arg to AC_DEFUN' 1>&2; \
	       exit 1; } || :

500 501 502 503
fix_po_file_diag = \
'you have changed the set of files with translatable diagnostics;\n\
apply the above patch\n'

504
# Verify that all source files using _() are listed in po/POTFILES.in.
505
po_file = po/POTFILES.in
506
po-check:
J
Jim Meyering 已提交
507
	@if test -f po/POTFILES.in; then					\
508 509 510
	  grep -E -v '^(#|$$)' po/POTFILES.in				\
	    | grep -v '^src/false\.c$$' | sort > $@-1;			\
	  files=;							\
511 512 513 514 515
	  for file in $$($(VC_LIST_EXCEPT)); do				\
	    case $$file in						\
	    djgpp/* | man/*) continue;;					\
	    */c99-to-c89.diff) continue;;				\
	    esac;							\
516 517 518 519
	    case $$file in						\
	    *.[ch])							\
	      base=`expr " $$file" : ' \(.*\)\..'`;			\
	      { test -f $$base.l || test -f $$base.y; } && continue;;	\
520
	    *) continue;;						\
521 522 523 524 525
	    esac;							\
	    files="$$files $$file";					\
	  done;								\
	  grep -E -l '\b(N?_|gettext *)\([^)"]*("|$$)' $$files		\
	    | sort -u > $@-2;						\
526 527
	  diff -u -L $(po_file) -L $(po_file) $@-1 $@-2			\
	    || { printf '$(ME): '$(fix_po_file_diag) 1>&2; exit 1; };	\
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
	  rm -f $@-1 $@-2;						\
	fi

# In a definition of #define AUTHORS "... and ..." where the RHS contains
# the English word `and', the string must be marked with `N_ (...)' so that
# gettext recognizes it as a string requiring translation.
author_mark_check:
	@grep -n '^# *define AUTHORS "[^"]* and ' src/*.c |grep -v ' N_ (' && \
	  { echo 'Makefile.maint: enclose the above strings in N_ (...)' 1>&2; \
	    exit 1; } || :

# Sometimes it is useful to change the PATH environment variable
# in Makefiles.  When doing so, it's better not to use the Unix-centric
# path separator of `:', but rather the automake-provided `@PATH_SEPARATOR@'.
# It'd be better to use `find -print0 ...|xargs -0 ...', but less portable,
# and there probably aren't many projects with so many Makefile.am files
# that we'd have to worry about limits on command line length.
msg = 'Makefile.maint: Do not use `:'\'' above; use @PATH_SEPARATOR@ instead'
makefile_path_separator_check:
	@grep -n 'PATH=.*:' `find $(srcdir) -name Makefile.am` \
	  && { echo $(msg) 1>&2; exit 1; } || :

# Check that `make alpha' will not fail at the end of the process.
writable-files:
	if test -d $(release_archive_dir); then :; else			\
553 554 555 556 557 558 559
	  for file in $(distdir).tar.gz					\
	              $(release_archive_dir)/$(distdir).tar.gz; do	\
	    test -e $$file || continue;					\
	    test -w $$file						\
	      || { echo ERROR: $$file is not writable; fail=1; };	\
	  done;								\
	  test "$$fail" && exit 1 || :
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
	fi

v_etc_file = lib/version-etc.c
sample-test = tests/sample-test
texi = doc/$(PACKAGE).texi
# Make sure that the copyright date in $(v_etc_file) is up to date.
# Do the same for the $(sample-test) and the main doc/.texi file.
copyright-check:
	@if test -f $(v_etc_file); then \
	  grep 'enum { COPYRIGHT_YEAR = '$$(date +%Y)' };' $(v_etc_file) \
	    >/dev/null \
	  || { echo 'out of date copyright in $(v_etc_file); update it' 1>&2; \
	       exit 1; }; \
	fi
	@if test -f $(sample-test); then \
	  grep '# Copyright (C) '$$(date +%Y)' Free' $(sample-test) \
	    >/dev/null \
	  || { echo 'out of date copyright in $(sample-test); update it' 1>&2; \
	       exit 1; }; \
	fi
	@if test -f $(texi); then \
	  grep 'Copyright @copyright{} .*'$$(date +%Y)' Free' $(texi) \
	    >/dev/null \
	  || { echo 'out of date copyright in $(texi); update it' 1>&2; \
	       exit 1; }; \
	fi

vc-diff-check:
	$(VC) diff > vc-diffs || :
	if test -s vc-diffs; then				\
	  cat vc-diffs;						\
	  echo "Some files are locally modified:" 1>&2;		\
	  exit 1;						\
	else							\
	  rm vc-diffs;						\
	fi

cvs-check: vc-diff-check

maintainer-distcheck:
	$(MAKE) distcheck
	$(MAKE) my-distcheck

# Use -Wformat -Werror to detect format-string/arg-list mismatches.
# Also, check for shadowing problems with -Wshadow, and for pointer
# arithmetic problems with -Wpointer-arith.
# These CFLAGS are pretty strict.  If you build this target, you probably
# have to have a recent version of gcc and glibc headers.
# The for-loop below ensures that there is a bin/ directory full of all
# of the programs under test (except the few that are required for basic
# Makefile rules), all symlinked to the just-built "false" program.
# This is to ensure that if ever a test neglects to make PATH include
# the build srcdir, these always-failing programs will run.
# Otherwise, it is too easy to test the wrong programs.
# Note that "false" itself is a symlink to true, so it too will malfunction.
TMPDIR ?= /tmp
t=$(TMPDIR)/$(PACKAGE)/test
my-distcheck: $(local-check) check
	-rm -rf $(t)
	mkdir -p $(t)
	GZIP=$(GZIP_ENV) $(AMTAR) -C $(t) -zxf $(distdir).tar.gz
	cd $(t)/$(distdir)				\
	  && ./configure --disable-nls			\
	  && $(MAKE) CFLAGS='$(warn_cflags)'		\
	      AM_MAKEFLAGS='$(null_AM_MAKEFLAGS)'	\
	  && $(MAKE) dvi				\
	  && $(MAKE) distclean
	(cd $(t) && mv $(distdir) $(distdir).old	\
	  && $(AMTAR) -zxf - ) < $(distdir).tar.gz
	diff -ur $(t)/$(distdir).old $(t)/$(distdir)
	if test -f $(srcdir)/src/c99-to-c89.diff; then			\
	  cd $(t)/$(distdir)						\
	    && (cd src && patch -V never --fuzz=0 <c99-to-c89.diff)	\
	    && ./configure --disable-largefile				\
	         CFLAGS='-Werror -ansi -Wno-long-long'			\
	    && $(MAKE);							\
	fi
	-rm -rf $(t)
	@echo "========================"; \
	echo "$(distdir).tar.gz is ready for distribution"; \
	echo "========================"
641

642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
cvs-to-git = '\#!/usr/bin/perl\n\
use warnings;\n\
use strict;\n\
use File::Find;\n\
use File::Copy;\n\
\n\
find ({wanted =>\n\
       sub {$$_ eq q/.cvsignore/ or return;\n\
	    my $$gi = q/.gitignore/;\n\
	    unlink $$gi;\n\
	    copy($$_, $$gi) or die qq/copy failed: $$_->$$gi: $$!\\n/;\n\
	    chmod 0444, $$gi;\n\
	    }},\n\
      q!.!);\n'

.PHONY: sync-vcs-ignore-files
c2g = cvs-to-git
659
sync-vcs-ignore-files:
660 661 662 663 664 665
	rm -f $(c2g)-t $(c2g)
	printf $(cvs-to-git) > $(c2g)-t
	chmod a+x-w $(c2g)-t
	mv $(c2g)-t $(c2g)
	perl $(c2g)
	rm -f $(c2g)