X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=top%2Fmaint.mk;h=d364934549eb2efa3f1c535891a33388e521e81c;hb=e901c96e0151d00195c60e9efb1a7668c4b5e3bd;hp=bc8a5810c41d9e129b3e149cbdb460338e0cf4f4;hpb=01995a99d9e6f934f057fd37a55292c1dac05bdf;p=gnulib.git diff --git a/top/maint.mk b/top/maint.mk index bc8a5810c..d36493454 100644 --- a/top/maint.mk +++ b/top/maint.mk @@ -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 @@ -27,12 +27,12 @@ build_aux ?= $(srcdir)/build-aux # 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) + $(shell gzip --help 2>/dev/null|grep rsyncable >/dev/null \ + && printf %s --rsyncable) GZIP_ENV = '--no-name --best $(gzip_rsyncable)' GIT = git VC = $(GIT) -VC-tag = git tag -s -m '$(VERSION)' -u '$(gpg_key_ID)' VC_LIST = $(build_aux)/vc-list-files -C $(srcdir) @@ -56,11 +56,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) @@ -102,6 +104,12 @@ endif # Override this in cfg.mk if you are using a different format in your # NEWS file. today = $(shell date +%Y-%m-%d) + +# Select which lines of NEWS are searched for $(news-check-regexp). +# This is a sed line number spec. The default says that we search +# lines 1..10 of NEWS for $(news-check-regexp). +# If you want to search only line 3 or only lines 20-22, use "3" or "20,22". +news-check-lines-spec ?= 1,10 news-check-regexp ?= '^\*.* $(VERSION_REGEXP) \($(today)\)' # Prevent programs like 'sort' from considering distinct strings to be equal. @@ -119,8 +127,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. @@ -139,7 +152,7 @@ $(sc_z_rules_): %.z: % start=$$(cat .sc-start-$*); \ rm -f .sc-start-$*; \ awk -v s=$$start -v e=$$end \ - 'END {printf "%.2f: $* done\n", e - s}' < /dev/null + 'END {printf "%.2f $(patsubst sc_%,%,$*)\n", e - s}' < /dev/null # The patsubst here is to replace each sc_% rule with its sc_%.z wrapper # that computes and prints elapsed time. @@ -148,16 +161,6 @@ local-check := \ $(filter-out $(local-checks-to-skip), $(local-checks-available))) syntax-check: $(local-check) -# @grep -nE '# *include <(limits|std(def|arg|bool))\.h>' \ -# $$(find -type f -name '*.[chly]') && \ -# { echo '$(ME): found conditional include' 1>&2; \ -# exit 1; } || : - -# 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 # _sc_search_regexp # @@ -194,14 +197,24 @@ 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 = -_ignore_case = $$(test -n "$$ignore_case" && echo -i || :) +_ignore_case = $$(test -n "$$ignore_case" && printf %s -i || :) define _sc_say_and_exit dummy=; : so we do not need a semicolon before each use; \ - { echo -e "$(ME): $$msg" 1>&2; exit 1; }; + { printf '%s\n' "$(ME): $$msg" 1>&2; exit 1; }; endef # _sc_search_regexp used to be named _prohibit_regexp. However, @@ -231,7 +244,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 \ @@ -295,10 +309,10 @@ sc_prohibit_atoi_atof: # Use STREQ rather than comparing strcmp == 0, or != 0. sc_prohibit_strcmp: - @grep -nE '! *str''cmp *\(|\&2; exit 1; } || : # Pass EXIT_*, not number, to usage, exit, and error (when exiting) @@ -391,11 +405,11 @@ sc_prohibit_HAVE_MBRTOWC: $(_sc_search_regexp) # To use this "command" macro, you must first define two shell variables: -# h: the header, enclosed in <> or "" +# h: the header name, with no enclosing <> or "" # re: a regular expression that matches IFF something provided by $h is used. define _sc_header_without_use dummy=; : so we do not need a semicolon before each use; \ - h_esc=`echo "$$h"|sed 's/\./\\\\./g'`; \ + h_esc=`echo '[<"]'"$$h"'[">]'|sed 's/\./\\\\./g'`; \ if $(VC_LIST_EXCEPT) | grep -l '\.c$$' > /dev/null; then \ files=$$(grep -l '^# *include '"$$h_esc" \ $$($(VC_LIST_EXCEPT) | grep '\.c$$')) && \ @@ -408,42 +422,42 @@ endef # Prohibit the inclusion of assert.h without an actual use of assert. sc_prohibit_assert_without_use: - @h='' re='\ sc_prohibit_hash_without_use: - @h='"hash.h"' \ + @h='hash.h' \ re='$(_hash_fn)|$(_hash_struct)'\ $(_sc_header_without_use) +sc_prohibit_cloexec_without_use: + @h='cloexec.h' re='\<(set_cloexec_flag|dup_cloexec) *\(' \ + $(_sc_header_without_use) + +sc_prohibit_posixver_without_use: + @h='posixver.h' re='\' \ halt='do not use HAVE''_FCNTL_H or O'_NDELAY \ @@ -586,10 +650,19 @@ sc_changelog: sc_program_name: @require='set_program_name *\(m?argv\[0\]\);' \ in_vc_files='\.c$$' \ - containing='^main *(' \ + containing='\
' \ - ignore_case=1 \ - halt='found use of "the ''the";' \ - $(_sc_search_regexp) - sc_trailing_blank: @prohibit='[ ]$$' \ halt='found trailing blank(s)' \ @@ -629,12 +696,17 @@ sc_two_space_separator_in_usage: halt='help2man requires at least two spaces between an option and its description'\ $(_sc_search_regexp) +# A regexp matching function names like "error" that may be used +# to emit translatable messages. +_gl_translatable_diag_func_re ?= error + # 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. sc_unmarked_diagnostics: @grep -nE \ - '\&2; \ exit 1; } || : @@ -645,6 +717,75 @@ sc_useless_cpp_parens: halt='found useless parentheses in cpp directive' \ $(_sc_search_regexp) +# List headers for which HAVE_HEADER_H is always true, assuming you are +# using the appropriate gnulib module. CAUTION: for each "unnecessary" +# #if HAVE_HEADER_H that you remove, be sure that your project explicitly +# requires the gnulib module that guarantees the usability of that header. +gl_assured_headers_ = \ + cd $(gnulib_dir)/lib && echo *.in.h|sed 's/\.in\.h//g' + +# Convert the list of names to upper case, and replace each space with "|". +az_ = abcdefghijklmnopqrstuvwxyz +AZ_ = ABCDEFGHIJKLMNOPQRSTUVWXYZ +gl_header_upper_case_or_ = \ + $$($(gl_assured_headers_) \ + | tr $(az_)/.- $(AZ_)___ \ + | tr -s ' ' '|' \ + ) +sc_prohibit_always_true_header_tests: + @or=$(gl_header_upper_case_or_); \ + re="HAVE_($$or)_H"; \ + prohibit='\<'"$$re"'\>' \ + halt=$$(printf '%s\n' \ + 'do not test the above HAVE_
_H symbol(s);' \ + ' with the corresponding gnulib module, they are always true') \ + $(_sc_search_regexp) + +# ================================================================== +gl_other_headers_ ?= \ + intprops.h \ + openat.h \ + stat-macros.h + +# Perl -lne code to extract "significant" cpp-defined symbols from a +# gnulib header file, eliminating a few common false-positives. +gl_extract_significant_defines_ = \ + /^\# *define ([^_ (][^ (]*)(\s*\(|\s+\w+)/\ + && $$2 !~ /(?:rpl_|_used_without_)/\ + && $$1 !~ /^(?:NSIG)$$/\ + && $$1 !~ /^(?:SA_RESETHAND|SA_RESTART)$$/\ + and print $$1 + +# Create a list of regular expressions matching the names +# of macros that are guaranteed to be defined by parts of gnulib. +define def_sym_regex + gen_h=$(gl_generated_headers_); \ + (cd $(gnulib_dir)/lib; \ + for f in *.in.h $(gl_other_headers_); do \ + perl -lne '$(gl_extract_significant_defines_)' $$f; \ + done; \ + ) | sort -u \ + | sed 's/^/^ *# *(define|undef) */;s/$$/\\>/' +endef + +# Don't define macros that we already get from gnulib header files. +sc_prohibit_always-defined_macros: + @if test -d $(gnulib_dir); then \ + case $$(echo all: | grep -l -f - Makefile) in Makefile);; *) \ + echo '$(ME): skipping $@: you lack GNU grep' 1>&2; exit 0;; \ + esac; \ + $(def_sym_regex) | grep -E -f - $$($(VC_LIST_EXCEPT)) \ + && { echo '$(ME): define the above via some gnulib .h file' \ + 1>&2; exit 1; } || :; \ + fi +# ================================================================== + +# Prohibit checked in backup files. +sc_prohibit_backup_files: + @$(VC_LIST) | grep '~$$' && \ + { echo '$(ME): found version controlled backup file' 1>&2; \ + exit 1; } || : + # Require the latest GPL. sc_GPL_version: @prohibit='either ''version [^3]' \ @@ -659,10 +800,12 @@ 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{' \ - in_vc_files='\.texi$$' \ + @prohibit='@acronym\{' \ + in_vc_files='$(texinfo_suffix_re_)' \ halt='found use of Texinfo @acronym{}' \ $(_sc_search_regexp) @@ -674,8 +817,6 @@ sc_prohibit_cvs_keyword: halt='do not use CVS keyword expansion' \ $(_sc_search_regexp) - include $(srcdir)/dist-check.mk - # This Perl code is slightly obfuscated. Not only is each "$" doubled # because it's in a Makefile, but the $$c's are comments; we cannot # use "#" due to the way the script ends up concatenated onto one line. @@ -684,31 +825,40 @@ 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_ = \ - foreach my $$f (@ARGV) { \ - open F, "<", $$f or (warn "failed to open $$f: $$!\n"), next; \ - my $$p = sysseek (F, -2, 2); \ - my $$c = "seek failure probably means file has < 2 bytes; ignore"; \ - my $$two; \ - defined $$p and $$p = sysread F, $$two, 2; \ - close F; \ - $$c = "ignore read failure"; \ - $$p && $$two eq "\n\n" and (print $$f), $$fail=1; \ - } END { exit defined $$fail } +require_exactly_one_NL_at_EOF_ = \ + foreach my $$f (@ARGV) \ + { \ + open F, "<", $$f or (warn "failed to open $$f: $$!\n"), next; \ + my $$p = sysseek (F, -2, 2); \ + my $$c = "seek failure probably means file has < 2 bytes; ignore"; \ + my $$last_two_bytes; \ + defined $$p and $$p = sysread F, $$last_two_bytes, 2; \ + close F; \ + $$c = "ignore read failure"; \ + $$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)' \ - 1>&2; exit 1; } || :; \ + @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. # This is a bit of a kludge, since it prevents use of the string @@ -725,6 +875,50 @@ sc_prohibit_S_IS_definition: halt='do not define S_IS* macros; include ' \ $(_sc_search_regexp) +# Perl block to convert a match to FILE_NAME:LINENO:TEST, +# that is shared by two definitions below. +perl_filename_lineno_text_ = \ + -e ' {' \ + -e ' $$n = ($$` =~ tr/\n/\n/ + 1);' \ + -e ' ($$v = $$&) =~ s/\n/\\n/g;' \ + -e ' print "$$ARGV:$$n:$$v\n";' \ + -e ' }' + +prohibit_doubled_word_RE_ ?= \ + /\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b/gims +prohibit_doubled_word_ = \ + -e 'while ($(prohibit_doubled_word_RE_))' \ + $(perl_filename_lineno_text_) + +# Define this to a regular expression that matches +# any filename:dd:match lines you want to ignore. +# The default is to ignore no matches. +ignore_doubled_word_match_RE_ ?= ^$$ + +sc_prohibit_doubled_word: + @perl -n -0777 $(prohibit_doubled_word_) $$($(VC_LIST_EXCEPT)) \ + | grep -vE '$(ignore_doubled_word_match_RE_)' \ + | grep . && { echo '$(ME): doubled words' 1>&2; exit 1; } || : + +# A regular expression matching undesirable combinations of words like +# "can not"; this matches them even when the two words appear on different +# lines, but not when there is an intervening delimiter like "#" or "*". +prohibit_undesirable_word_seq_RE_ ?= \ + /\bcan\s+not\b/gims +prohibit_undesirable_word_seq_ = \ + -e 'while ($(prohibit_undesirable_word_seq_RE_))' \ + $(perl_filename_lineno_text_) +# Define this to a regular expression that matches +# any filename:dd:match lines you want to ignore. +# The default is to ignore no matches. +ignore_undesirable_word_sequence_RE_ ?= ^$$ + +sc_prohibit_undesirable_word_seq: + @perl -n -0777 $(prohibit_undesirable_word_seq_) \ + $$($(VC_LIST_EXCEPT)) \ + | grep -vE '$(ignore_undesirable_word_sequence_RE_)' | grep . \ + && { echo '$(ME): undesirable word sequence' >&2; exit 1; } || : + _ptm1 = use "test C1 && test C2", not "test C1 -''a C2" _ptm2 = use "test C1 || test C2", not "test C1 -''o C2" # Using test's -a and -o operators is not portable. @@ -734,6 +928,13 @@ sc_prohibit_test_minus_ao: halt='$(_ptm1); $(_ptm2)' \ $(_sc_search_regexp) +# Avoid a test bashism. +sc_prohibit_test_double_equal: + @prohibit='(\&2; exit 1; } || : news-check: NEWS - if head $(srcdir)/NEWS | grep -E $(news-check-regexp) \ - >/dev/null; then \ + if sed -n $(news-check-lines-spec)p $(srcdir)/NEWS \ + | grep -E $(news-check-regexp) >/dev/null; then \ :; \ else \ echo 'NEWS: $$(news-check-regexp) failed to match' 1>&2; \ @@ -832,13 +1040,14 @@ 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 +generated_files ?= $(srcdir)/lib/*.[ch] 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)) $(generated_files); do \ test -r $$file || continue; \ case $$file in \ *.m4|*.mk) continue ;; \ @@ -853,7 +1062,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; \ @@ -881,7 +1090,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. @@ -908,20 +1117,23 @@ sc_copyright_check: # sets PATH correctly. This is an inexpensive way to ensure that # the other init.sh-using tests also get it right. _hv_file ?= $(srcdir)/tests/help-version -_hv_regex ?= ^ *\. [^ ]*/init\.sh +_hv_regex_weak ?= ^ *\. .*/init\.sh" +# Fix syntax-highlighters " +_hv_regex_strong ?= ^ *\. "\$${srcdir=\.}/init\.sh" sc_cross_check_PATH_usage_in_tests: @if test -f $(_hv_file); then \ - if grep -l 'VERSION mismatch' $(_hv_file) >/dev/null \ - && grep -lE '$(_hv_regex)' $(_hv_file) >/dev/null; then \ - good=$$(grep -E '$(_hv_regex)' < $(_hv_file)); \ - grep -LFx "$$good" \ - $$(grep -lE '$(_hv_regex)' $$($(VC_LIST_EXCEPT))) \ - | grep . && \ - { echo "$(ME): the above files use path_prepend_ inconsistently" \ - 1>&2; exit 1; } || :; \ - fi; \ - else \ - echo "$@: skipped: no such file: $(_hv_file)"; \ + grep -l 'VERSION mismatch' $(_hv_file) >/dev/null \ + || { echo "$@: skipped: no such file: $(_hv_file)" 1>&2; \ + exit 0; }; \ + grep -lE '$(_hv_regex_strong)' $(_hv_file) >/dev/null \ + || { echo "$@: $(_hv_file) lacks conforming use of init.sh" 1>&2; \ + exit 1; }; \ + good=$$(grep -E '$(_hv_regex_strong)' $(_hv_file)); \ + grep -LFx "$$good" \ + $$(grep -lE '$(_hv_regex_weak)' $$($(VC_LIST_EXCEPT))) \ + | grep . && \ + { echo "$(ME): the above files use path_prepend_ inconsistently" \ + 1>&2; exit 1; } || :; \ fi # #if HAVE_... will evaluate to false for any non numeric string. @@ -934,12 +1146,21 @@ sc_Wundef_boolean: halt='Use 0 or 1 for macro values' \ $(_sc_search_regexp) +# Even if you use pathmax.h to guarantee that PATH_MAX is defined, it might +# not be constant, or might overflow a stack. In general, use PATH_MAX as +# a limit, not an array or alloca size. +sc_prohibit_path_max_allocation: + @prohibit='(\balloca *\([^)]*|\[[^]]*)PATH_MAX' \ + halt='Avoid stack allocations of size PATH_MAX' \ + $(_sc_search_regexp) + 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: @@ -965,8 +1186,25 @@ gpg_key_ID ?= \ && gpgv .ann-sig - < /dev/null 2>&1 \ | sed -n '/.*key ID \([0-9A-F]*\)/s//\1/p'; rm -f .ann-sig) +translation_project_ ?= coordinator@translationproject.org + +# Make info-gnu the default only for a stable release. +ifeq ($(RELEASE_TYPE),stable) + announcement_Cc_ ?= $(translation_project_), $(PACKAGE_BUGREPORT) + announcement_mail_headers_ ?= \ + To: info-gnu@gnu.org \ + Cc: $(announcement_Cc_) \ + Mail-Followup-To: $(PACKAGE_BUGREPORT) +else + announcement_Cc_ ?= $(translation_project_) + announcement_mail_headers_ ?= \ + To: $(PACKAGE_BUGREPORT) \ + Cc: $(announcement_Cc_) +endif + announcement: NEWS ChangeLog $(rel-files) @$(build_aux)/announce-gen \ + --mail-headers='$(announcement_mail_headers_)' \ --release-type=$(RELEASE_TYPE) \ --package=$(PACKAGE) \ --prev=$(PREV_VERSION) \ @@ -996,7 +1234,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.' \ @@ -1017,9 +1254,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;};}\ @@ -1034,28 +1296,34 @@ 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) ;; \ *) echo "invalid RELEASE_TYPE: $$RELEASE_TYPE" 1>&2; exit 1;; esac - $(MAKE) -s announcement > ~/announce-$(my_distdir) + $(MAKE) --no-print-directory -s announcement > ~/announce-$(my_distdir) if test -d $(release_archive_dir); then \ ln $(rel-files) $(release_archive_dir); \ chmod a-w $(rel-files); \ 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 +# Override this with e.g., -s $(srcdir)/some_other_name.texi +# if the default $(PACKAGE)-derived name doesn't apply. +gendocs_options_ ?= + .PHONY: web-manual web-manual: @test -z "$(manual_title)" \ && { echo define manual_title in cfg.mk 1>&2; exit 1; } || : @cd '$(srcdir)/doc'; \ - $(SHELL) ../build-aux/gendocs.sh -o '$(abs_builddir)/doc/manual' \ + $(SHELL) ../build-aux/gendocs.sh $(gendocs_options_) \ + -o '$(abs_builddir)/doc/manual' \ --email $(PACKAGE_BUGREPORT) $(PACKAGE) \ "$(PACKAGE_NAME) - $(manual_title)" @echo " *** Upload the doc/manual directory to web-cvs." @@ -1097,10 +1365,12 @@ refresh-po: echo 'en@quot' >> $(PODIR)/LINGUAS && \ ls $(PODIR)/*.po | sed 's/\.po//' | sed 's,$(PODIR)/,,' | sort >> $(PODIR)/LINGUAS + # Running indent once is not idempotent, but running it twice is. INDENT_SOURCES ?= $(C_SOURCES) .PHONY: indent indent: indent $(INDENT_SOURCES) + indent $(INDENT_SOURCES) # If you want to set UPDATE_COPYRIGHT_* environment variables, # put the assignments in this variable. @@ -1118,3 +1388,101 @@ update-copyright: grep -l -w Copyright \ $$(export VC_LIST_EXCEPT_DEFAULT=COPYING && $(VC_LIST_EXCEPT)) \ | $(update-copyright-env) xargs $(build_aux)/$@ + +# This tight_scope test is skipped with a warning if $(_gl_TS_headers) is not +# overridden and $(_gl_TS_dir)/Makefile.am does not mention noinst_HEADERS. + +# NOTE: to override any _gl_TS_* default value, you must +# define the variable(s) using "export" in cfg.mk. +_gl_TS_dir ?= src + +ALL_RECURSIVE_TARGETS += sc_tight_scope +sc_tight_scope: tight-scope.mk + @if ! grep '^ *export _gl_TS_headers *=' $(srcdir)/cfg.mk \ + > /dev/null \ + && ! grep -w noinst_HEADERS $(srcdir)/$(_gl_TS_dir)/Makefile.am \ + > /dev/null 2>&1; then \ + echo '$(ME): skipping $@'; \ + else \ + $(MAKE) -s -C $(_gl_TS_dir) \ + -f Makefile \ + -f $(abs_top_srcdir)/cfg.mk \ + -f $(abs_top_builddir)/$< \ + _gl_tight_scope \ + || fail=1; \ + fi + @rm -f $< + +tight-scope.mk: $(ME) + @rm -f $@ $@-t + @perl -ne '/^# TS-start/.../^# TS-end/ and print' $(ME) > $@-t + @chmod a=r $@-t && mv $@-t $@ + +ifeq (a,b) +# TS-start + +# Most functions should have static scope. +# Any that don't must be marked with `extern', but `main' +# and `usage' are exceptions: they're always extern, but +# do not need to be marked. Symbols matching `__.*' are +# reserved by the compiler, so are automatically excluded below. +_gl_TS_unmarked_extern_functions ?= main usage +_gl_TS_function_match ?= /^(?:$(_gl_TS_extern)) +.*?(\S+) *\(/ + +# If your project uses a macro like "XTERN", then put +# the following in cfg.mk to override this default: +# export _gl_TS_extern = extern|XTERN +_gl_TS_extern ?= extern + +# The second nm|grep checks for file-scope variables with `extern' scope. +# Without gnulib's progname module, you might put program_name here. +# Symbols matching `__.*' are reserved by the compiler, +# so are automatically excluded below. +_gl_TS_unmarked_extern_vars ?= + +# NOTE: the _match variables are perl expressions -- not mere regular +# expressions -- so that you can extend them to match other patterns +# and easily extract matched variable names. +# For example, if your project declares some global variables via +# a macro like this: GLOBAL(type, var_name, initializer), then you +# can override this definition to automatically extract those names: +# export _gl_TS_var_match = \ +# /^(?:$(_gl_TS_extern)) .*?\**(\w+)(\[.*?\])?;/ || /\bGLOBAL\(.*?,\s*(.*?),/ +_gl_TS_var_match ?= /^(?:$(_gl_TS_extern)) .*?(\w+)(\[.*?\])?;/ + +# The names of object files in (or relative to) $(_gl_TS_dir). +_gl_TS_obj_files ?= *.$(OBJEXT) + +# Files in which to search for the one-line style extern declarations. +# $(_gl_TS_dir)-relative. +_gl_TS_headers ?= $(noinst_HEADERS) + +.PHONY: _gl_tight_scope +_gl_tight_scope: $(bin_PROGRAMS) + t=exceptions-$$$$; \ + trap 's=$$?; rm -f $$t; exit $$s' 0; \ + for sig in 1 2 3 13 15; do \ + eval "trap 'v=`expr $$sig + 128`; (exit $$v); exit $$v' $$sig"; \ + done; \ + src=`for f in $(SOURCES); do \ + test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`; \ + hdr=`for f in $(_gl_TS_headers); do \ + test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`; \ + ( printf '^%s$$\n' '__.*' $(_gl_TS_unmarked_extern_functions); \ + grep -h -A1 '^extern .*[^;]$$' $$src \ + | grep -vE '^(extern |--)' | sed 's/ .*//'; \ + perl -lne \ + '$(_gl_TS_function_match) and print "^$$1\$$"' $$hdr; \ + ) | sort -u > $$t; \ + nm -e $(_gl_TS_obj_files) | sed -n 's/.* T //p'|grep -Ev -f $$t \ + && { echo the above functions should have static scope >&2; \ + exit 1; } || : ; \ + ( printf '^%s$$\n' '__.*' $(_gl_TS_unmarked_extern_vars); \ + perl -lne '$(_gl_TS_var_match) and print "^$$1\$$"' $$hdr *.h \ + ) | sort -u > $$t; \ + nm -e $(_gl_TS_obj_files) | sed -n 's/.* [BCDGRS] //p' \ + | sort -u | grep -Ev -f $$t \ + && { echo the above variables should have static scope >&2; \ + exit 1; } || : +# TS-end +endif