maint.mk: Don't trigger sc_space_tab check.
[gnulib.git] / top / maint.mk
index 59e9cb5..693e5ab 100644 (file)
@@ -2,7 +2,7 @@
 # This Makefile fragment tries to be general-purpose enough to be
 # used by many projects via the gnulib maintainer-makefile module.
 
-## Copyright (C) 2001-2010 Free Software Foundation, Inc.
+## Copyright (C) 2001-2011 Free Software Foundation, Inc.
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ GZIP_ENV = '--no-name --best $(gzip_rsyncable)'
 
 GIT = git
 VC = $(GIT)
-VC-tag = git tag -s -m '$(VERSION)' -u '$(gpg_key_ID)'
+VC-tag = git tag -s -m '$(VERSION)' 'v$(VERSION)' -u '$(gpg_key_ID)'
 
 VC_LIST = $(build_aux)/vc-list-files -C $(srcdir)
 
@@ -57,11 +57,13 @@ endif
 # In order to be able to consistently filter "."-relative names,
 # (i.e., with no $(srcdir) prefix), this definition is careful to
 # remove any $(srcdir) prefix, and to restore what it removes.
+_sc_excl = \
+  $(if $(exclude_file_name_regexp--$@),$(exclude_file_name_regexp--$@),^$$)
 VC_LIST_EXCEPT = \
   $(VC_LIST) | sed 's|^$(_dot_escaped_srcdir)/||' \
        | if test -f $(srcdir)/.x-$@; then grep -vEf $(srcdir)/.x-$@; \
          else grep -Ev -e "$${VC_LIST_EXCEPT_DEFAULT-ChangeLog}"; fi \
-       | grep -Ev -e '$(VC_LIST_ALWAYS_EXCLUDE_REGEX)' \
+       | grep -Ev -e '($(VC_LIST_ALWAYS_EXCLUDE_REGEX)|$(_sc_excl))' \
        $(_prepend_srcdir_prefix)
 
 ifeq ($(origin prev_version_file), undefined)
@@ -126,8 +128,13 @@ syntax-check-rules := $(sort $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' \
                        $(srcdir)/$(ME) $(_cfg_mk)))
 .PHONY: $(syntax-check-rules)
 
-local-checks-available = \
-  $(syntax-check-rules)
+ifeq ($(shell $(VC_LIST) >/dev/null 2>&1; echo $$?),0)
+local-checks-available += $(syntax-check-rules)
+else
+local-checks-available += no-vc-detected
+no-vc-detected:
+       @echo "No version control files detected; skipping syntax check"
+endif
 .PHONY: $(local-checks-available)
 
 # Arrange to print the name of each syntax-checking rule just before running it.
@@ -191,6 +198,16 @@ syntax-check: $(local-check)
 #  halt
 #
 #     Message to display before to halting execution.
+#
+# Finally, you may exempt files based on an ERE matching file names.
+# For example, to exempt from the sc_space_tab check all files with the
+# .diff suffix, set this Make variable:
+#
+# exclude_file_name_regexp--sc_space_tab = \.diff$
+#
+# Note that while this functionality is mostly inherited via VC_LIST_EXCEPT,
+# when filtering by name via in_files, we explicitly filter out matching
+# names here as well.
 
 # By default, _sc_search_regexp does not ignore case.
 export ignore_case =
@@ -228,7 +245,8 @@ define _sc_search_regexp
                                                                        \
    : Filter by file name;                                              \
    if test -n "$$in_files"; then                                       \
-     files=$$(find $(srcdir) | grep -E "$$in_files");                  \
+     files=$$(find $(srcdir) | grep -E "$$in_files"                    \
+              | grep -Ev '$(exclude_file_name_regexp--$@)');           \
    else                                                                        \
      files=$$($(VC_LIST_EXCEPT));                                      \
      if test -n "$$in_vc_files"; then                                  \
@@ -292,10 +310,10 @@ sc_prohibit_atoi_atof:
 
 # Use STREQ rather than comparing strcmp == 0, or != 0.
 sc_prohibit_strcmp:
-       @grep -nE '! *str''cmp *\(|\<str''cmp *\([^)]+\) *=='           \
+       @grep -nE '! *str''cmp *\(|\<str''cmp *\(.+\) *[!=]='   \
            $$($(VC_LIST_EXCEPT))                                       \
-         | grep -vE ':# *define STREQ\(' &&                            \
-         { echo '$(ME): use STREQ in place of the above uses of str''cmp' \
+         | grep -vE ':# *define STRN?EQ\(' &&                          \
+         { echo '$(ME): replace str''cmp calls above with STREQ/STRNEQ' \
                1>&2; exit 1; } || :
 
 # Pass EXIT_*, not number, to usage, exit, and error (when exiting)
@@ -571,6 +589,13 @@ sc_prohibit_intprops_without_use:
        re='\<($(_intprops_syms_re)) *\('                               \
          $(_sc_header_without_use)
 
+_stddef_syms_re = NULL|offsetof|ptrdiff_t|size_t|wchar_t
+# Prohibit the inclusion of stddef.h without an actual use.
+sc_prohibit_stddef_without_use:
+       @h='<stddef.h>'                                                 \
+       re='\<($(_stddef_syms_re)) *\('                                 \
+         $(_sc_header_without_use)
+
 sc_obsolete_symbols:
        @prohibit='\<(HAVE''_FCNTL_H|O''_NDELAY)\>'                     \
        halt='do not use HAVE''_FCNTL_H or O'_NDELAY                    \
@@ -590,10 +615,19 @@ sc_changelog:
 sc_program_name:
        @require='set_program_name *\(m?argv\[0\]\);'                   \
        in_vc_files='\.c$$'                                             \
-       containing='^main *('                                           \
+       containing='\<main *('                                          \
        halt='the above files do not call set_program_name'             \
          $(_sc_search_regexp)
 
+# Ensure that each .c file containing a "main" function also
+# calls bindtextdomain.
+sc_bindtextdomain:
+       @require='bindtextdomain *\('                                   \
+       in_vc_files='\.c$$'                                             \
+       containing='\<main *('                                          \
+       halt='the above files do not call bindtextdomain'               \
+         $(_sc_search_regexp)
+
 # Require that the final line of each test-lib.sh-using test be this one:
 # Exit $fail
 # Note: this test requires GNU grep's --label= option.
@@ -638,7 +672,7 @@ sc_two_space_separator_in_usage:
 sc_unmarked_diagnostics:
        @grep -nE                                                       \
            '\<error *\([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT))      \
-         | grep -v '_''(' &&                                           \
+         | grep -Ev '(_|ngettext ?)\(' &&                              \
          { echo '$(ME): found unmarked diagnostic(s)' 1>&2;            \
            exit 1; } || :
 
@@ -668,8 +702,9 @@ sc_prohibit_always_true_header_tests:
        @or=$(gl_header_upper_case_or_);                                \
        re="HAVE_($$or)_H";                                             \
        prohibit='\<'"$$re"'\>'                                         \
-       halt='do not test the above HAVE_<header>_H symbol(s);\n'\
-'  with the corresponding gnulib module, they are always true'         \
+       halt=$$(printf '%s\n'                                           \
+       'do not test the above HAVE_<header>_H symbol(s);'              \
+       '  with the corresponding gnulib module, they are always true') \
          $(_sc_search_regexp)
 
 # ==================================================================
@@ -731,7 +766,8 @@ sc_GFDL_version:
        halt='GFDL vN, N!=3'                                            \
          $(_sc_search_regexp)
 
-# Don't use Texinfo @acronym{} as it is not a good idea.
+# Don't use Texinfo's @acronym{}.
+# http://lists.gnu.org/archive/html/bug-gnulib/2010-03/msg00321.html
 texinfo_suffix_re_ ?= \.(txi|texi(nfo)?)$$
 sc_texinfo_acronym:
        @prohibit='@acronym\{'                                          \
@@ -755,17 +791,22 @@ sc_prohibit_cvs_keyword:
 #   perl -ln -0777 -e '/\n(\n+)$/ and print "$ARGV: ".length $1' ...
 # but that would be far less efficient, reading the entire contents
 # of each file, rather than just the last two bytes of each.
+# In addition, while the code below detects both blank lines and a missing
+# newline at EOF, the above detects only the former.
 #
 # This is a perl script that is expected to be the single-quoted argument
 # to a command-line "-le".  The remaining arguments are file names.
-# Print the name of each file that ends in two or more newline bytes.
+# Print the name of each file that ends in exactly one newline byte.
+# I.e., warn if there are blank lines (2 or more newlines), or if the
+# last byte is not a newline.  However, currently we don't complain
+# about any file that contains exactly one byte.
 # Exit nonzero if at least one such file is found, otherwise, exit 0.
 # Warn about, but otherwise ignore open failure.  Ignore seek/read failure.
 #
 # Use this if you want to remove trailing empty lines from selected files:
 #   perl -pi -0777 -e 's/\n\n+$/\n/' files...
 #
-detect_empty_lines_at_EOF_ =                                           \
+require_exactly_one_NL_at_EOF_ =                                       \
   foreach my $$f (@ARGV)                                               \
     {                                                                  \
       open F, "<", $$f or (warn "failed to open $$f: $$!\n"), next;    \
@@ -775,12 +816,14 @@ detect_empty_lines_at_EOF_ =                                              \
       defined $$p and $$p = sysread F, $$last_two_bytes, 2;            \
       close F;                                                         \
       $$c = "ignore read failure";                                     \
-      $$p && $$last_two_bytes eq "\n\n" and (print $$f), $$fail=1;     \
+      $$p && ($$last_two_bytes eq "\n\n"                               \
+              || substr ($$last_two_bytes,1) ne "\n")                  \
+          and (print $$f), $$fail=1;                                   \
     }                                                                  \
   END { exit defined $$fail }
 sc_prohibit_empty_lines_at_EOF:
-       @perl -le '$(detect_empty_lines_at_EOF_)' $$($(VC_LIST_EXCEPT)) \
-          || { echo '$(ME): the above files end with empty line(s)'     \
+       @perl -le '$(require_exactly_one_NL_at_EOF_)' $$($(VC_LIST_EXCEPT)) \
+         || { echo '$(ME): empty line(s) or no newline at EOF'         \
                1>&2; exit 1; } || :;                                   \
 
 # Make sure we don't use st_blocks.  Use ST_NBLOCKS instead.
@@ -807,6 +850,13 @@ sc_prohibit_test_minus_ao:
        halt='$(_ptm1); $(_ptm2)'                                       \
          $(_sc_search_regexp)
 
+# Avoid a test bashism.
+sc_prohibit_test_double_equal:
+       @prohibit='(\<test| \[+) .+ == '                                \
+       containing='#! */bin/[a-z]*sh'                                  \
+       halt='use "test x = x", not "test x =''= x"'                    \
+         $(_sc_search_regexp)
+
 # Each program that uses proper_name_utf8 must link with one of the
 # ICONV libraries.  Otherwise, some ICONV library must appear in LDADD.
 # The perl -0777 invocation below extracts the possibly-multi-line
@@ -905,13 +955,13 @@ fix_po_file_diag = \
 apply the above patch\n'
 
 # Verify that all source files using _() are listed in po/POTFILES.in.
-po_file po/POTFILES.in
+po_file ?= $(srcdir)/po/POTFILES.in
 sc_po_check:
        @if test -f $(po_file); then                                    \
          grep -E -v '^(#|$$)' $(po_file)                               \
            | grep -v '^src/false\.c$$' | sort > $@-1;                  \
          files=;                                                       \
-         for file in $$($(VC_LIST_EXCEPT)) lib/*.[ch]; do              \
+         for file in $$($(VC_LIST_EXCEPT)) $(srcdir)/lib/*.[ch]; do    \
            test -r $$file || continue;                                 \
            case $$file in                                              \
              *.m4|*.mk) continue ;;                                    \
@@ -926,7 +976,7 @@ sc_po_check:
            files="$$files $$file";                                     \
          done;                                                         \
          grep -E -l '\b(N?_|gettext *)\([^)"]*("|$$)' $$files          \
-           | sort -u > $@-2;                                           \
+           | sed 's|^$(_dot_escaped_srcdir)/||' | sort -u > $@-2;      \
          diff -u -L $(po_file) -L $(po_file) $@-1 $@-2                 \
            || { printf '$(ME): '$(fix_po_file_diag) 1>&2; exit 1; };   \
          rm -f $@-1 $@-2;                                              \
@@ -954,7 +1004,7 @@ writable-files:
          test "$$fail" && exit 1 || : ;                                \
        fi
 
-v_etc_file = lib/version-etc.c
+v_etc_file = $(gnulib_dir)/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.
@@ -1012,9 +1062,10 @@ sc_Wundef_boolean:
 sc_vulnerable_makefile_CVE-2009-4029:
        @prohibit='perm -777 -exec chmod a\+rwx|chmod 777 \$$\(distdir\)' \
        in_files=$$(find $(srcdir) -name Makefile.in)                   \
-       halt='the above files are vulnerable; beware of running\n'\
-'"make dist*" rules, and upgrade to fixed automake\n'\
-'see http://bugzilla.redhat.com/542609 for details'                    \
+       halt=$$(printf '%s\n'                                           \
+         'the above files are vulnerable; beware of running'           \
+         '  "make dist*" rules, and upgrade to fixed automake'         \
+         '  see http://bugzilla.redhat.com/542609 for details')        \
          $(_sc_search_regexp)
 
 vc-diff-check:
@@ -1079,7 +1130,6 @@ emit_upload_commands:
        @echo =====================================
        @echo =====================================
 
-noteworthy = * Noteworthy changes in release ?.? (????-??-??) [?]
 define emit-commit-log
   printf '%s\n' 'post-release administrivia' '' \
     '* NEWS: Add header line for next release.' \
@@ -1100,9 +1150,34 @@ no-submodule-changes:
          : ;                                                           \
        fi
 
+submodule-checks ?= no-submodule-changes public-submodule-commit
+
+# Ensure that each sub-module commit we're using is public.
+# Without this, it is too easy to tag and release code that
+# cannot be built from a fresh clone.
+.PHONY: public-submodule-commit
+public-submodule-commit:
+       $(AM_V_GEN)if test -d $(srcdir)/.git; then                      \
+         cd $(srcdir) &&                                               \
+         git submodule --quiet foreach test '$$(git rev-parse $$sha1)' \
+             = '$$(git merge-base origin $$sha1)'                      \
+           || { echo '$(ME): found non-public submodule commit' >&2;   \
+                exit 1; };                                             \
+       else                                                            \
+         : ;                                                           \
+       fi
+# This rule has a high enough utility/cost ratio that it should be a
+# dependent of "check" by default.  However, some of us do occasionally
+# commit a temporary change that deliberately points to a non-public
+# submodule commit, and want to be able to use rules like "make check".
+# In that case, run e.g., "make check gl_public_submodule_commit="
+# to disable this test.
+gl_public_submodule_commit ?= public-submodule-commit
+check: $(gl_public_submodule_commit)
+
 .PHONY: alpha beta stable
 ALL_RECURSIVE_TARGETS += alpha beta stable
-alpha beta stable: $(local-check) writable-files no-submodule-changes
+alpha beta stable: $(local-check) writable-files $(submodule-checks)
        test $@ = stable                                                \
          && { echo $(VERSION) | grep -E '^[0-9]+(\.[0-9]+)+$$'         \
               || { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\
@@ -1117,6 +1192,7 @@ alpha beta stable: $(local-check) writable-files no-submodule-changes
 # Override this in cfg.mk if you follow different procedures.
 release-prep-hook ?= release-prep
 
+gl_noteworthy_news_ = * Noteworthy changes in release ?.? (????-??-??) [?]
 .PHONY: release-prep
 release-prep:
        case $$RELEASE_TYPE in alpha|beta|stable) ;; \
@@ -1128,7 +1204,7 @@ release-prep:
        fi
        echo $(VERSION) > $(prev_version_file)
        $(MAKE) update-NEWS-hash
-       perl -pi -e '$$. == 3 and print "$(noteworthy)\n\n\n"' NEWS
+       perl -pi -e '$$. == 3 and print "$(gl_noteworthy_news_)\n\n\n"' NEWS
        $(emit-commit-log) > .ci-msg
        $(VC) commit -F .ci-msg -a
        rm .ci-msg