]>
Commit | Line | Data |
---|---|---|
8fa36911 JD |
1 | # -*-Makefile-*- |
2 | # This Makefile fragment tries to be general-purpose enough to be | |
3 | # used by at least coreutils, idutils, CPPI, Bison, and Autoconf. | |
4 | ||
5 | ## Copyright (C) 2001-2008 Free Software Foundation, Inc. | |
6 | ## | |
7 | ## This program is free software: you can redistribute it and/or modify | |
8 | ## it under the terms of the GNU General Public License as published by | |
9 | ## the Free Software Foundation, either version 3 of the License, or | |
10 | ## (at your option) any later version. | |
11 | ## | |
12 | ## This program is distributed in the hope that it will be useful, | |
13 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ## GNU General Public License for more details. | |
16 | ## | |
17 | ## You should have received a copy of the GNU General Public License | |
18 | ## along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | ||
20 | # This is reported not to work with make-3.79.1 | |
21 | # ME := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) | |
22 | ME := maint.mk | |
23 | ||
24 | # Do not save the original name or timestamp in the .tar.gz file. | |
25 | # Use --rsyncable if available. | |
26 | gzip_rsyncable := \ | |
27 | $(shell gzip --help 2>/dev/null|grep rsyncable >/dev/null && echo --rsyncable) | |
28 | GZIP_ENV = '--no-name --best $(gzip_rsyncable)' | |
29 | ||
30 | GIT = git | |
31 | VC = $(GIT) | |
32 | VC-tag = git tag -s -m '$(VERSION)' | |
33 | ||
34 | VC_LIST = build-aux/vc-list-files | |
35 | ||
36 | VC_LIST_EXCEPT = \ | |
37 | $(VC_LIST) | if test -f .x-$@; then grep -vEf .x-$@; else grep -v ChangeLog; fi | |
38 | ||
39 | ifeq ($(origin prev_version_file), undefined) | |
40 | prev_version_file = $(srcdir)/.prev-version | |
41 | endif | |
42 | ||
43 | PREV_VERSION := $(shell cat $(prev_version_file)) | |
44 | VERSION_REGEXP = $(subst .,\.,$(VERSION)) | |
45 | PREV_VERSION_REGEXP = $(subst .,\.,$(PREV_VERSION)) | |
46 | ||
47 | ifeq ($(VC),$(GIT)) | |
48 | this-vc-tag = v$(VERSION) | |
49 | this-vc-tag-regexp = v$(VERSION_REGEXP) | |
50 | else | |
51 | tag-package = $(shell echo "$(PACKAGE)" | tr '[:lower:]' '[:upper:]') | |
52 | tag-this-version = $(subst .,_,$(VERSION)) | |
53 | this-vc-tag = $(tag-package)-$(tag-this-version) | |
54 | this-vc-tag-regexp = $(this-vc-tag) | |
55 | endif | |
56 | my_distdir = $(PACKAGE)-$(VERSION) | |
57 | ||
58 | # Old releases are stored here. | |
59 | release_archive_dir ?= ../release | |
60 | ||
61 | # Prevent programs like 'sort' from considering distinct strings to be equal. | |
62 | # Doing it here saves us from having to set LC_ALL elsewhere in this file. | |
63 | export LC_ALL = C | |
64 | ||
65 | ||
66 | ||
67 | ## --------------- ## | |
68 | ## Sanity checks. ## | |
69 | ## --------------- ## | |
70 | ||
71 | # Collect the names of rules starting with `sc_'. | |
72 | syntax-check-rules := $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' \ | |
73 | $(srcdir)/$(ME)) | |
74 | .PHONY: $(syntax-check-rules) | |
75 | ||
76 | local-checks-available = \ | |
77 | po-check copyright-check m4-check author_mark_check \ | |
78 | patch-check strftime-check $(syntax-check-rules) \ | |
79 | makefile_path_separator_check \ | |
80 | makefile-check check-AUTHORS | |
81 | .PHONY: $(local-checks-available) | |
82 | ||
83 | local-check := $(filter-out $(local-checks-to-skip), $(local-checks-available)) | |
84 | ||
85 | syntax-check: $(local-check) | |
86 | # @grep -nE '# *include <(limits|std(def|arg|bool))\.h>' \ | |
87 | # $$(find -type f -name '*.[chly]') && \ | |
88 | # { echo '$(ME): found conditional include' 1>&2; \ | |
89 | # exit 1; } || : | |
90 | ||
91 | # grep -nE '^# *include <(string|stdlib)\.h>' \ | |
92 | # $(srcdir)/{lib,src}/*.[chy] && \ | |
93 | # { echo '$(ME): FIXME' 1>&2; \ | |
94 | # exit 1; } || : | |
95 | # FIXME: don't allow `#include .strings\.h' anywhere | |
96 | ||
97 | sc_avoid_if_before_free: | |
98 | @$(srcdir)/build-aux/useless-if-before-free \ | |
99 | $(useless_free_options) \ | |
100 | $$($(VC_LIST_EXCEPT)) && \ | |
101 | { echo '$(ME): found useless "if" before "free" above' 1>&2; \ | |
102 | exit 1; } || : | |
103 | ||
104 | sc_cast_of_argument_to_free: | |
105 | @grep -nE '\<free *\( *\(' $$($(VC_LIST_EXCEPT)) && \ | |
106 | { echo '$(ME): don'\''t cast free argument' 1>&2; \ | |
107 | exit 1; } || : | |
108 | ||
109 | sc_cast_of_x_alloc_return_value: | |
110 | @grep -nE '\*\) *x(m|c|re)alloc\>' $$($(VC_LIST_EXCEPT)) && \ | |
111 | { echo '$(ME): don'\''t cast x*alloc return value' 1>&2; \ | |
112 | exit 1; } || : | |
113 | ||
114 | sc_cast_of_alloca_return_value: | |
115 | @grep -nE '\*\) *alloca\>' $$($(VC_LIST_EXCEPT)) && \ | |
116 | { echo '$(ME): don'\''t cast alloca return value' 1>&2; \ | |
117 | exit 1; } || : | |
118 | ||
119 | sc_space_tab: | |
120 | @grep -n '[ ] ' $$($(VC_LIST_EXCEPT)) && \ | |
121 | { echo '$(ME): found SPACE-TAB sequence; remove the SPACE' \ | |
122 | 1>&2; exit 1; } || : | |
123 | ||
124 | # Don't use *scanf or the old ato* functions in `real' code. | |
125 | # They provide no error checking mechanism. | |
126 | # Instead, use strto* functions. | |
127 | sc_prohibit_atoi_atof: | |
128 | @grep -nE '\<([fs]?scanf|ato([filq]|ll))\>' $$($(VC_LIST_EXCEPT)) && \ | |
129 | { echo '$(ME): do not use *scan''f, ato''f, ato''i, ato''l, ato''ll, ato''q, or ss''canf' \ | |
130 | 1>&2; exit 1; } || : | |
131 | ||
132 | # Use STREQ rather than comparing strcmp == 0, or != 0. | |
133 | sc_prohibit_strcmp: | |
134 | @grep -nE '! *str''cmp *\(|\<str''cmp *\([^)]+\) *==' \ | |
135 | $$($(VC_LIST_EXCEPT)) && \ | |
136 | { echo '$(ME): use STREQ in place of the above uses of str''cmp' \ | |
137 | 1>&2; exit 1; } || : | |
138 | ||
139 | # Using EXIT_SUCCESS as the first argument to error is misleading, | |
140 | # since when that parameter is 0, error does not exit. Use `0' instead. | |
141 | sc_error_exit_success: | |
142 | @grep -nF 'error (EXIT_SUCCESS,' \ | |
143 | $$(find -type f -name '*.[chly]') && \ | |
144 | { echo '$(ME): found error (EXIT_SUCCESS' 1>&2; \ | |
145 | exit 1; } || : | |
146 | ||
147 | # `FATAL:' should be fully upper-cased in error messages | |
148 | # `WARNING:' should be fully upper-cased, or fully lower-cased | |
149 | sc_error_message_warn_fatal: | |
150 | @grep -nEA2 '[^rp]error \(' $$($(VC_LIST_EXCEPT)) \ | |
151 | | grep -E '"Warning|"Fatal|"fatal' && \ | |
152 | { echo '$(ME): use FATAL, WARNING or warning' 1>&2; \ | |
153 | exit 1; } || : | |
154 | ||
155 | # Error messages should not start with a capital letter | |
156 | sc_error_message_uppercase: | |
157 | @grep -nEA2 '[^rp]error \(' $$($(VC_LIST_EXCEPT)) \ | |
158 | | grep -E '"[A-Z]' \ | |
159 | | grep -vE '"FATAL|"WARNING|"Java|"C#|PRIuMAX' && \ | |
160 | { echo '$(ME): found capitalized error message' 1>&2; \ | |
161 | exit 1; } || : | |
162 | ||
163 | # Error messages should not end with a period | |
164 | sc_error_message_period: | |
165 | @grep -nEA2 '[^rp]error \(' $$($(VC_LIST_EXCEPT)) \ | |
166 | | grep -E '[^."]\."' && \ | |
167 | { echo '$(ME): found error message ending in period' 1>&2; \ | |
168 | exit 1; } || : | |
169 | ||
170 | sc_file_system: | |
171 | @grep -ni 'file''system' $$($(VC_LIST_EXCEPT)) && \ | |
172 | { echo '$(ME): found use of "file''system";' \ | |
173 | 'rewrite to use "file system"' 1>&2; \ | |
174 | exit 1; } || : | |
175 | ||
176 | # Don't use cpp tests of this symbol. All code assumes config.h is included. | |
177 | sc_no_have_config_h: | |
178 | @grep -n '^# *if.*HAVE''_CONFIG_H' $$($(VC_LIST_EXCEPT)) && \ | |
179 | { echo '$(ME): found use of HAVE''_CONFIG_H; remove' \ | |
180 | 1>&2; exit 1; } || : | |
181 | ||
182 | # Nearly all .c files must include <config.h>. | |
183 | sc_require_config_h: | |
184 | @if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then \ | |
185 | grep -L '^# *include <config\.h>' \ | |
186 | $$($(VC_LIST_EXCEPT) | grep '\.c$$') \ | |
187 | | grep . && \ | |
188 | { echo '$(ME): the above files do not include <config.h>' \ | |
189 | 1>&2; exit 1; } || :; \ | |
190 | else :; \ | |
191 | fi | |
192 | ||
193 | # To use this "command" macro, you must first define two shell variables: | |
194 | # h: the header, enclosed in <> or "" | |
195 | # re: a regular expression that matches IFF something provided by $h is used. | |
196 | define _header_without_use | |
197 | h_esc=`echo "$$h"|sed 's/\./\\./'`; \ | |
198 | if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then \ | |
199 | files=$$(grep -l '^# *include '"$$h_esc" \ | |
200 | $$($(VC_LIST_EXCEPT) | grep '\.c$$')) && \ | |
201 | grep -LE "$$re" $$files | grep . && \ | |
202 | { echo "$(ME): the above files include $$h but don't use it" \ | |
203 | 1>&2; exit 1; } || :; \ | |
204 | else :; \ | |
205 | fi | |
206 | endef | |
207 | ||
208 | # Prohibit the inclusion of assert.h without an actual use of assert. | |
209 | sc_prohibit_assert_without_use: | |
210 | @h='<assert.h>' re='\<assert *\(' $(_header_without_use) | |
211 | ||
212 | # Prohibit the inclusion of getopt.h without an actual use. | |
213 | sc_prohibit_getopt_without_use: | |
214 | @h='<getopt.h>' re='\<getopt(_long)? *\(' $(_header_without_use) | |
215 | ||
216 | # Don't include quotearg.h unless you use one of its functions. | |
217 | sc_prohibit_quotearg_without_use: | |
218 | @h='"quotearg.h"' re='\<quotearg(_[^ ]+)? *\(' $(_header_without_use) | |
219 | ||
220 | # Don't include quote.h unless you use one of its functions. | |
221 | sc_prohibit_quote_without_use: | |
222 | @h='"quote.h"' re='\<quote(_n)? *\(' $(_header_without_use) | |
223 | ||
224 | # Don't include this header unless you use one of its functions. | |
225 | sc_prohibit_long_options_without_use: | |
226 | @h='"long-options.h"' re='\<parse_long_options *\(' \ | |
227 | $(_header_without_use) | |
228 | ||
229 | # Don't include this header unless you use one of its functions. | |
230 | sc_prohibit_inttostr_without_use: | |
231 | @h='"inttostr.h"' re='\<(off|[iu]max|uint)tostr *\(' \ | |
232 | $(_header_without_use) | |
233 | ||
234 | # Don't include this header unless you use one of its functions. | |
235 | sc_prohibit_error_without_use: | |
236 | @h='"error.h"' \ | |
237 | re='\<error(_at_line|_print_progname|_one_per_line|_message_count)? *\('\ | |
238 | $(_header_without_use) | |
239 | ||
240 | sc_prohibit_safe_read_without_use: | |
241 | @h='"safe-read.h"' re='(\<SAFE_READ_ERROR\>|\<safe_read *\()' \ | |
242 | $(_header_without_use) | |
243 | ||
244 | sc_prohibit_argmatch_without_use: | |
245 | @h='"argmatch.h"' \ | |
246 | re='(\<(ARRAY_CARDINALITY|X?ARGMATCH(|_TO_ARGUMENT|_VERIFY))\>|\<argmatch(_exit_fn|_(in)?valid) *\()' \ | |
247 | $(_header_without_use) | |
248 | ||
249 | sc_prohibit_root_dev_ino_without_use: | |
250 | @h='"root-dev-ino.h"' \ | |
251 | re='(\<ROOT_DEV_INO_(CHECK|WARN)\>|\<get_root_dev_ino *\()' \ | |
252 | $(_header_without_use) | |
253 | ||
254 | sc_obsolete_symbols: | |
255 | @grep -nE '\<(HAVE''_FCNTL_H|O''_NDELAY)\>' \ | |
256 | $$($(VC_LIST_EXCEPT)) && \ | |
257 | { echo '$(ME): do not use HAVE''_FCNTL_H or O''_NDELAY' \ | |
258 | 1>&2; exit 1; } || : | |
259 | ||
260 | # FIXME: warn about definitions of EXIT_FAILURE, EXIT_SUCCESS, STREQ | |
261 | ||
262 | # Each nonempty line must start with a year number, or a TAB. | |
263 | sc_changelog: | |
264 | @grep -n '^[^12 ]' $$(find . -maxdepth 2 -name ChangeLog) && \ | |
265 | { echo '$(ME): found unexpected prefix in a ChangeLog' 1>&2; \ | |
266 | exit 1; } || : | |
267 | ||
268 | # Ensure that dd's definition of LONGEST_SYMBOL stays in sync | |
269 | # with the strings from the two affected variables. | |
270 | dd_c = $(srcdir)/src/dd.c | |
271 | sc_dd_max_sym_length: | |
272 | ifneq ($(wildcard $(dd_c)),) | |
273 | @len=$$( (sed -n '/conversions\[\] =$$/,/^};/p' $(dd_c);\ | |
274 | sed -n '/flags\[\] =$$/,/^};/p' $(dd_c) ) \ | |
275 | |sed -n '/"/s/^[^"]*"\([^"]*\)".*/\1/p' \ | |
276 | | wc --max-line-length); \ | |
277 | max=$$(sed -n '/^#define LONGEST_SYMBOL /s///p' $(dd_c) \ | |
278 | |tr -d '"' | wc --max-line-length); \ | |
279 | if test "$$len" = "$$max"; then :; else \ | |
280 | echo 'dd.c: LONGEST_SYMBOL is not longest' 1>&2; \ | |
281 | exit 1; \ | |
282 | fi | |
283 | endif | |
284 | ||
285 | # Many m4 macros names once began with `jm_'. | |
286 | # On 2004-04-13, they were all changed to start with gl_ instead. | |
287 | # Make sure that none are inadvertently reintroduced. | |
288 | sc_prohibit_jm_in_m4: | |
289 | @grep -nE 'jm_[A-Z]' \ | |
290 | $$($(VC_LIST) m4 |grep '\.m4$$'; echo /dev/null) && \ | |
291 | { echo '$(ME): do not use jm_ in m4 macro names' \ | |
292 | 1>&2; exit 1; } || : | |
293 | ||
294 | # Ensure that each root-requiring test is run via the "check-root" rule. | |
295 | sc_root_tests: | |
296 | @if test -d tests \ | |
297 | && grep check-root tests/Makefile.am>/dev/null 2>&1; then \ | |
298 | t1=sc-root.expected; t2=sc-root.actual; \ | |
299 | grep -nl '^require_root_$$' \ | |
300 | $$($(VC_LIST) tests) |sed s,tests/,, |sort > $$t1; \ | |
301 | sed -n '/^root_tests =[ ]*\\$$/,/[^\]$$/p' \ | |
302 | $(srcdir)/tests/Makefile.am \ | |
303 | | sed 's/^ *//;/^root_tests =/d' \ | |
304 | | tr -s '\012\\' ' ' | fmt -1 | sort > $$t2; \ | |
305 | diff -u $$t1 $$t2 || diff=1; \ | |
306 | rm -f $$t1 $$t2; \ | |
307 | test "$$diff" \ | |
308 | && { echo 'tests/Makefile.am: missing check-root action'>&2; \ | |
309 | exit 1; } || :; \ | |
310 | fi | |
311 | ||
312 | headers_with_interesting_macro_defs = \ | |
313 | exit.h \ | |
314 | fcntl_.h \ | |
315 | fnmatch_.h \ | |
316 | intprops.h \ | |
317 | inttypes_.h \ | |
318 | lchown.h \ | |
319 | openat.h \ | |
320 | stat-macros.h \ | |
321 | stdint_.h | |
322 | ||
323 | # Create a list of regular expressions matching the names | |
324 | # of macros that are guaranteed by parts of gnulib to be defined. | |
325 | .re-defmac: | |
326 | @(cd $(srcdir)/lib; \ | |
327 | for f in $(headers_with_interesting_macro_defs); do \ | |
328 | test -f $$f && \ | |
329 | sed -n '/^# *define \([^_ (][^ (]*\)[ (].*/s//\1/p' $$f; \ | |
330 | done; \ | |
331 | ) | sort -u \ | |
332 | | grep -Ev 'ATTRIBUTE_NORETURN|SIZE_MAX' \ | |
333 | | sed 's/^/^# *define /' \ | |
334 | > $@-t | |
335 | @mv $@-t $@ | |
336 | ||
337 | # Don't define macros that we already get from gnulib header files. | |
338 | sc_always_defined_macros: .re-defmac | |
339 | @if test -f $(srcdir)/src/system.h; then \ | |
340 | trap 'rc=$$?; rm -f .re-defmac; exit $$rc' 0 1 2 3 15; \ | |
341 | grep -f .re-defmac $$($(VC_LIST)) \ | |
342 | && { echo '$(ME): define the above via some gnulib .h file' \ | |
343 | 1>&2; exit 1; } || :; \ | |
344 | fi | |
345 | ||
346 | # Create a list of regular expressions matching the names | |
347 | # of files included from system.h. Exclude a couple. | |
348 | .re-list: | |
349 | @sed -n '/^# *include /s///p' $(srcdir)/src/system.h \ | |
350 | | grep -Ev 'sys/(param|file)\.h' \ | |
351 | | sed 's/ .*//;;s/^["<]/^# *include [<"]/;s/\.h[">]$$/\\.h[">]/' \ | |
352 | > $@-t | |
353 | @mv $@-t $@ | |
354 | ||
355 | # Files in src/ should not include directly any of | |
356 | # the headers already included via system.h. | |
357 | sc_system_h_headers: .re-list | |
358 | @if test -f $(srcdir)/src/system.h; then \ | |
359 | trap 'rc=$$?; rm -f .re-list; exit $$rc' 0 1 2 3 15; \ | |
360 | grep -nE -f .re-list \ | |
361 | $$($(VC_LIST) src | \ | |
362 | grep -Ev '((copy|system)\.h|parse-gram\.c)$$') \ | |
363 | && { echo '$(ME): the above are already included via system.h'\ | |
364 | 1>&2; exit 1; } || :; \ | |
365 | fi | |
366 | ||
367 | # Ensure that each .c file containing a "main" function also | |
368 | # calls set_program_name. | |
369 | sc_program_name: | |
370 | @if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then \ | |
371 | files=$$(grep -l '^main *(' $$($(VC_LIST_EXCEPT) | grep '\.c$$')); \ | |
372 | grep -LE 'set_program_name *\(m?argv\[0\]\);' $$files \ | |
373 | | grep . && \ | |
374 | { echo '$(ME): the above files do not call set_program_name' \ | |
375 | 1>&2; exit 1; } || :; \ | |
376 | else :; \ | |
377 | fi | |
378 | ||
379 | # Require that the final line of each test-lib.sh-using test be this one: | |
380 | # (exit $fail); exit $fail | |
381 | # Note: this test requires GNU grep's --label= option. | |
382 | sc_require_test_exit_idiom: | |
383 | @if test -f $(srcdir)/tests/test-lib.sh; then \ | |
384 | die=0; \ | |
385 | for i in $$(grep -l -F /../test-lib.sh $$($(VC_LIST) tests)); do \ | |
386 | tail -n1 $$i | grep '^(exit \$$fail); exit \$$fail$$' > /dev/null \ | |
387 | && : || { die=1; echo $$i; } \ | |
388 | done; \ | |
389 | test $$die = 1 && \ | |
390 | { echo 1>&2 '$(ME): the final line in each of the above is not:'; \ | |
391 | echo 1>&2 '(exit $$fail); exit $$fail'; \ | |
392 | exit 1; } || :; \ | |
393 | fi | |
394 | ||
395 | sc_sun_os_names: | |
396 | @grep -nEi \ | |
397 | 'solaris[^[:alnum:]]*2\.(7|8|9|[1-9][0-9])|sunos[^[:alnum:]][6-9]' \ | |
398 | $$($(VC_LIST_EXCEPT)) && \ | |
399 | { echo '$(ME): found misuse of Sun OS version numbers' 1>&2; \ | |
400 | exit 1; } || : | |
401 | ||
402 | sc_the_the: | |
403 | @grep -ni '\<the ''the\>' $$($(VC_LIST_EXCEPT)) && \ | |
404 | { echo '$(ME): found use of "the ''the";' 1>&2; \ | |
405 | exit 1; } || : | |
406 | ||
2ead32e6 AD |
407 | # Most functions in src/*.c should have static scope. |
408 | # Any that don't must be marked with `extern', but `main' | |
409 | # and `usage' are exceptions. They're always extern, but | |
410 | # don't need to be marked. | |
411 | # | |
412 | # The second nm|grep checks for file-scope variables with `extern' scope. | |
413 | sc_tight_scope: $(all_programs) | |
414 | @t=exceptions-$$$$; \ | |
415 | trap 's=$$?; rm -f $$t; exit $$s' 0 1 2 13 15; \ | |
416 | ( printf '^main$$\n^usage$$\n'; \ | |
417 | grep -h -A1 '^extern .*[^;]$$' $(SOURCES) \ | |
418 | | grep -vE '^(extern |--)' |sed 's/^/^/;s/ .*/$$/' ) > $$t; \ | |
419 | if nm -e *.$(OBJEXT) \ | |
420 | | sed -n 's/.* T //p' \ | |
421 | | grep -Ev -f $$t; then \ | |
422 | echo 'the above functions should have static scope' 1>&2; \ | |
423 | exit 1; \ | |
424 | fi; \ | |
425 | ( printf '^program_name$$\n'; \ | |
426 | sed -n 's/^extern .*[* ]\([a-zA-Z_][a-zA-Z_0-9]*\);$$/^\1$$/p' \ | |
427 | $$(ls $(SOURCES) | grep '\.h$$') /dev/null) > $$t; \ | |
428 | if nm -e *.$(OBJEXT) \ | |
429 | | sed -n 's/.* [BD] //p' \ | |
430 | | grep -Ev -f $$t; then \ | |
431 | echo 'the above variables should have static scope' 1>&2; \ | |
432 | exit 1; \ | |
433 | fi | |
8fa36911 JD |
434 | |
435 | sc_trailing_blank: | |
436 | @grep -n '[ ]$$' $$($(VC_LIST_EXCEPT)) && \ | |
437 | { echo '$(ME): found trailing blank(s)' \ | |
438 | 1>&2; exit 1; } || : | |
439 | ||
440 | # Match lines like the following, but where there is only one space | |
441 | # between the options and the description: | |
442 | # -D, --all-repeated[=delimit-method] print all duplicate lines\n | |
443 | longopt_re = --[a-z][0-9A-Za-z-]*(\[?=[0-9A-Za-z-]*\]?)? | |
444 | sc_two_space_separator_in_usage: | |
445 | @grep -nE '^ *(-[A-Za-z],)? $(longopt_re) [^ ].*\\$$' \ | |
446 | $$($(VC_LIST_EXCEPT)) && \ | |
447 | { echo "$(ME): help2man requires at least two spaces between"; \ | |
448 | echo "$(ME): an option and its description"; \ | |
449 | 1>&2; exit 1; } || : | |
450 | ||
451 | # Look for diagnostics that aren't marked for translation. | |
452 | # This won't find any for which error's format string is on a separate line. | |
453 | sc_unmarked_diagnostics: | |
454 | @grep -nE \ | |
455 | '\<error \([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT)) \ | |
456 | | grep -v '_''(' && \ | |
457 | { echo '$(ME): found unmarked diagnostic(s)' 1>&2; \ | |
458 | exit 1; } || : | |
459 | ||
460 | # Avoid useless parentheses like those in this example: | |
461 | # #if defined (SYMBOL) || defined (SYM2) | |
462 | sc_useless_cpp_parens: | |
463 | @grep -n '^# *if .*defined *(' $$($(VC_LIST_EXCEPT)) && \ | |
464 | { echo '$(ME): found useless parentheses in cpp directive' \ | |
465 | 1>&2; exit 1; } || : | |
466 | ||
467 | # Require the latest GPL. | |
468 | sc_GPL_version: | |
469 | @grep -n 'either ''version [^3]' $$($(VC_LIST_EXCEPT)) && \ | |
470 | { echo '$(ME): GPL vN, N!=3' 1>&2; exit 1; } || : | |
471 | ||
472 | # Perl-based tests used to exec perl from a #!/bin/sh script. | |
473 | # Now they all start with #!/usr/bin/perl and the portability | |
474 | # infrastructure is in tests/Makefile.am. Make sure no old-style | |
475 | # script sneaks back in. | |
476 | sc_no_exec_perl_coreutils: | |
477 | @if test -f $(srcdir)/tests/Coreutils.pm; then \ | |
478 | grep '^exec *\$$PERL.*MCoreutils' $$($(VC_LIST) tests) && \ | |
479 | { echo 1>&2 '$(ME): found anachronistic Perl-based tests'; \ | |
480 | exit 1; } || :; \ | |
481 | fi | |
482 | ||
483 | NEWS_hash = \ | |
484 | $$(sed -n '/^\*.* $(PREV_VERSION_REGEXP) ([0-9-]*)/,$$p' \ | |
485 | $(srcdir)/NEWS | md5sum -) | |
486 | ||
487 | # Ensure that we don't accidentally insert an entry into an old NEWS block. | |
488 | sc_immutable_NEWS: | |
489 | @if test -f $(srcdir)/NEWS; then \ | |
490 | test "$(NEWS_hash)" = '$(old_NEWS_hash)' && : || \ | |
491 | { echo '$(ME): you have modified old NEWS' 1>&2; exit 1; }; \ | |
492 | fi | |
493 | ||
494 | # Each program that uses proper_name_utf8 must link with | |
495 | # one of the ICONV libraries. | |
496 | sc_proper_name_utf8_requires_ICONV: | |
497 | @progs=$$(grep -l 'proper_name_utf8 ''("' $$($(VC_LIST_EXCEPT)));\ | |
498 | if test "x$$progs" != x; then \ | |
499 | fail=0; \ | |
500 | for p in $$progs; do \ | |
501 | dir=$$(dirname "$$p"); \ | |
502 | base=$$(basename "$$p" .c); \ | |
503 | grep "$${base}_LDADD.*ICONV)" $$dir/Makefile.am > /dev/null \ | |
504 | || { fail=1; echo 1>&2 "$(ME): $$p uses proper_name_utf8"; }; \ | |
505 | done; \ | |
506 | test $$fail = 1 && \ | |
507 | { echo 1>&2 '$(ME): the above do not link with any ICONV library'; \ | |
508 | exit 1; } || :; \ | |
509 | fi | |
510 | ||
511 | # Warn about "c0nst struct Foo const foo[]", | |
512 | # but not about "char const *const foo" or "#define const const". | |
513 | sc_redundant_const: | |
514 | @grep -E '\bconst\b[[:space:][:alnum:]]{2,}\bconst\b' \ | |
515 | $$($(VC_LIST_EXCEPT)) && \ | |
516 | { echo 1>&2 '$(ME): redundant "const" in declarations'; \ | |
517 | exit 1; } || : | |
518 | ||
519 | sc_const_long_option: | |
520 | @grep '^ *static.*struct option ' $$($(VC_LIST_EXCEPT)) \ | |
521 | | grep -Ev 'const struct option|struct option const' && { \ | |
522 | echo 1>&2 '$(ME): add "const" to the above declarations'; \ | |
523 | exit 1; } || : | |
524 | ||
525 | # Update the hash stored above. Do this after each release and | |
526 | # for any corrections to old entries. | |
527 | update-NEWS-hash: NEWS | |
528 | perl -pi -e 's/^(old_NEWS_hash = ).*/$${1}'"$(NEWS_hash)/" \ | |
529 | $(srcdir)/cfg.mk | |
530 | ||
531 | epoch_date = 1970-01-01 00:00:00.000000000 +0000 | |
532 | # Ensure that the c99-to-c89 patch applies cleanly. | |
533 | patch-check: | |
534 | rm -rf src-c89 $@.1 $@.2 | |
535 | cp -a src src-c89 | |
536 | (cd src-c89; patch -p1 -V never --fuzz=0) < src/c99-to-c89.diff \ | |
537 | > $@.1 2>&1 | |
538 | if test "$(REGEN_PATCH)" = yes; then \ | |
539 | diff -upr src src-c89 | sed 's,src-c89/,src/,' \ | |
540 | | grep -vE '^(Only in|File )' \ | |
541 | | perl -pe 's/^((?:\+\+\+|---) \S+\t).*/$${1}$(epoch_date)/;' \ | |
542 | -e 's/^ $$//' \ | |
543 | > new-diff || : ; fi | |
544 | grep -v '^patching file ' $@.1 > $@.2 || : | |
545 | msg=ok; test -s $@.2 && msg='fuzzy patch' || : ; \ | |
546 | rm -f src-c89/*.o || msg='rm failed'; \ | |
547 | $(MAKE) -C src-c89 CFLAGS='-Wdeclaration-after-statement -Werror' \ | |
548 | || msg='compile failure with extra options'; \ | |
549 | test "$$msg" = ok && rm -rf src-c89 $@.1 $@.2 || echo "$$msg" 1>&2; \ | |
550 | test "$$msg" = ok | |
551 | ||
552 | # Ensure that date's --help output stays in sync with the info | |
553 | # documentation for GNU strftime. The only exception is %N, | |
554 | # which date accepts but GNU strftime does not. | |
555 | extract_char = sed 's/^[^%][^%]*%\(.\).*/\1/' | |
556 | strftime-check: | |
557 | if test -f $(srcdir)/src/date.c; then \ | |
558 | grep '^ %. ' $(srcdir)/src/date.c | sort \ | |
559 | | $(extract_char) > $@-src; \ | |
560 | { echo N; \ | |
561 | info libc date calendar format | grep '^ `%.'\' \ | |
562 | | $(extract_char); } | sort > $@-info; \ | |
563 | diff -u $@-src $@-info || exit 1; \ | |
564 | rm -f $@-src $@-info; \ | |
565 | fi | |
566 | ||
567 | check-AUTHORS: | |
568 | $(MAKE) -C src $@ | |
569 | ||
570 | # Ensure that we use only the standard $(VAR) notation, | |
571 | # not @...@ in Makefile.am, now that we can rely on automake | |
572 | # to emit a definition for each substituted variable. | |
573 | makefile-check: | |
574 | @grep -nE '@[A-Z_0-9]+@' `find . -name Makefile.am` \ | |
575 | && { echo '$(ME): use $$(...), not @...@' 1>&2; exit 1; } || : | |
576 | ||
577 | news-date-check: NEWS | |
578 | today=`date +%Y-%m-%d`; \ | |
579 | if head NEWS | grep '^\*.* $(VERSION_REGEXP) ('$$today')' \ | |
580 | >/dev/null; then \ | |
581 | :; \ | |
582 | else \ | |
583 | echo "version or today's date is not in NEWS" 1>&2; \ | |
584 | exit 1; \ | |
585 | fi | |
586 | ||
587 | changelog-check: | |
588 | if head ChangeLog | grep 'Version $(VERSION_REGEXP)\.$$' \ | |
589 | >/dev/null; then \ | |
590 | :; \ | |
591 | else \ | |
592 | echo "$(VERSION) not in ChangeLog" 1>&2; \ | |
593 | exit 1; \ | |
594 | fi | |
595 | ||
596 | m4-check: | |
597 | @grep -n 'AC_DEFUN([^[]' m4/*.m4 \ | |
598 | && { echo '$(ME): quote the first arg to AC_DEFUN' 1>&2; \ | |
599 | exit 1; } || : | |
600 | ||
601 | # Verify that all source files using _() are listed in po/POTFILES.in. | |
602 | po-check: | |
603 | @if test -f po/POTFILES.in; then \ | |
604 | grep -E -v '^(#|$$)' po/POTFILES.in \ | |
605 | | grep -v '^src/false\.c$$' | sort > $@-1; \ | |
606 | files=; \ | |
607 | for file in $$($(VC_LIST_EXCEPT)) lib/*.[ch]; do \ | |
608 | case $$file in \ | |
609 | *.?|*.??) ;; \ | |
610 | *) continue;; \ | |
611 | esac; \ | |
612 | case $$file in \ | |
613 | *.[ch]) \ | |
614 | base=`expr " $$file" : ' \(.*\)\..'`; \ | |
615 | { test -f $$base.l || test -f $$base.y; } && continue;; \ | |
616 | esac; \ | |
617 | files="$$files $$file"; \ | |
618 | done; \ | |
619 | grep -E -l '\b(N?_|gettext *)\([^)"]*("|$$)' $$files \ | |
620 | | sort -u > $@-2; \ | |
621 | diff -u $@-1 $@-2 || exit 1; \ | |
622 | rm -f $@-1 $@-2; \ | |
623 | fi | |
624 | ||
625 | # In a definition of #define AUTHORS "... and ..." where the RHS contains | |
626 | # the English word `and', the string must be marked with `N_ (...)' so that | |
627 | # gettext recognizes it as a string requiring translation. | |
628 | author_mark_check: | |
629 | @grep -n '^# *define AUTHORS "[^"]* and ' src/*.c |grep -v ' N_ (' && \ | |
630 | { echo '$(ME): enclose the above strings in N_ (...)' 1>&2; \ | |
631 | exit 1; } || : | |
632 | ||
633 | # Sometimes it is useful to change the PATH environment variable | |
634 | # in Makefiles. When doing so, it's better not to use the Unix-centric | |
635 | # path separator of `:', but rather the automake-provided `@PATH_SEPARATOR@'. | |
636 | # It'd be better to use `find -print0 ...|xargs -0 ...', but less portable, | |
637 | # and there probably aren't many projects with so many Makefile.am files | |
638 | # that we'd have to worry about limits on command line length. | |
639 | msg = '$(ME): Do not use `:'\'' above; use @PATH_SEPARATOR@ instead' | |
640 | makefile_path_separator_check: | |
641 | @grep -n 'PATH=.*:' `find $(srcdir) -name Makefile.am` \ | |
642 | && { echo $(msg) 1>&2; exit 1; } || : | |
643 | ||
644 | # Check that `make alpha' will not fail at the end of the process. | |
645 | writable-files: | |
646 | if test -d $(release_archive_dir); then :; else \ | |
647 | for file in $(distdir).tar.gz \ | |
648 | $(release_archive_dir)/$(distdir).tar.gz; do \ | |
649 | test -e $$file || continue; \ | |
650 | test -w $$file \ | |
651 | || { echo ERROR: $$file is not writable; fail=1; }; \ | |
652 | done; \ | |
653 | test "$$fail" && exit 1 || : ; \ | |
654 | fi | |
655 | ||
656 | v_etc_file = lib/version-etc.c | |
657 | sample-test = tests/sample-test | |
658 | texi = doc/$(PACKAGE).texi | |
659 | # Make sure that the copyright date in $(v_etc_file) is up to date. | |
660 | # Do the same for the $(sample-test) and the main doc/.texi file. | |
661 | copyright-check: | |
662 | @if test -f $(v_etc_file); then \ | |
663 | grep 'enum { COPYRIGHT_YEAR = '$$(date +%Y)' };' $(v_etc_file) \ | |
664 | >/dev/null \ | |
665 | || { echo 'out of date copyright in $(v_etc_file); update it' 1>&2; \ | |
666 | exit 1; }; \ | |
667 | fi | |
668 | @if test -f $(sample-test); then \ | |
669 | grep '# Copyright (C) '$$(date +%Y)' Free' $(sample-test) \ | |
670 | >/dev/null \ | |
671 | || { echo 'out of date copyright in $(sample-test); update it' 1>&2; \ | |
672 | exit 1; }; \ | |
673 | fi | |
674 | @if test -f $(texi); then \ | |
675 | grep 'Copyright @copyright{} .*'$$(date +%Y)' Free' $(texi) \ | |
676 | >/dev/null \ | |
677 | || { echo 'out of date copyright in $(texi); update it' 1>&2; \ | |
678 | exit 1; }; \ | |
679 | fi | |
680 | ||
681 | vc-diff-check: | |
682 | $(VC) diff > vc-diffs || : | |
683 | if test -s vc-diffs; then \ | |
684 | cat vc-diffs; \ | |
685 | echo "Some files are locally modified:" 1>&2; \ | |
686 | exit 1; \ | |
687 | else \ | |
688 | rm vc-diffs; \ | |
689 | fi | |
690 | ||
691 | cvs-check: vc-diff-check | |
692 | ||
693 | maintainer-distcheck: | |
694 | $(MAKE) distcheck | |
695 | $(MAKE) my-distcheck | |
696 | ||
697 | ||
698 | # Don't make a distribution if checks fail. | |
699 | # Also, make sure the NEWS file is up-to-date. | |
700 | vc-dist: $(local-check) cvs-check maintainer-distcheck | |
701 | $(MAKE) dist | |
702 | ||
703 | # Use this to make sure we don't run these programs when building | |
704 | # from a virgin tgz file, below. | |
705 | null_AM_MAKEFLAGS = \ | |
706 | ACLOCAL=false \ | |
707 | AUTOCONF=false \ | |
708 | AUTOMAKE=false \ | |
709 | AUTOHEADER=false \ | |
710 | MAKEINFO=false | |
711 | ||
712 | built_programs = $$(cd src && MAKEFLAGS= $(MAKE) -s built_programs.list) | |
713 | ||
714 | warn_cflags = -Dlint -O -Werror -Wall -Wformat -Wshadow -Wpointer-arith | |
715 | bin=bin-$$$$ | |
716 | ||
717 | write_loser = printf '\#!%s\necho $$0: bad path 1>&2; exit 1\n' '$(SHELL)' | |
718 | ||
719 | TMPDIR ?= /tmp | |
720 | t=$(TMPDIR)/$(PACKAGE)/test | |
721 | pfx=$(t)/i | |
722 | ||
723 | # Verify that a twisted use of --program-transform-name=PROGRAM works. | |
724 | define install-transform-check | |
725 | rm -rf $(pfx); \ | |
726 | $(MAKE) program_transform_name='s/.*/zyx/' \ | |
727 | prefix=$(pfx) install \ | |
728 | && test "$$(echo $(pfx)/bin/*)" = "$(pfx)/bin/zyx" \ | |
729 | && test "$$(echo $(pfx)/share/man/man1/*)" = \ | |
730 | "$(pfx)/share/man/man1/zyx.1" | |
731 | endef | |
732 | ||
733 | # Install, then verify that all binaries and man pages are in place. | |
734 | # Note that neither the binary, ginstall, nor the ].1 man page is installed. | |
735 | define my-instcheck | |
736 | $(MAKE) prefix=$(pfx) install \ | |
737 | && test ! -f $(pfx)/bin/ginstall \ | |
738 | && { fail=0; \ | |
739 | for i in $(built_programs); do \ | |
740 | test "$$i" = ginstall && i=install; \ | |
741 | for j in "$(pfx)/bin/$$i" \ | |
742 | "$(pfx)/share/man/man1/$$i.1"; do \ | |
743 | case $$j in *'[.1') continue;; esac; \ | |
744 | test -f "$$j" && : \ | |
745 | || { echo "$$j not installed"; fail=1; }; \ | |
746 | done; \ | |
747 | done; \ | |
748 | test $$fail = 1 && exit 1 || :; \ | |
749 | } | |
750 | endef | |
751 | ||
752 | # Use -Wformat -Werror to detect format-string/arg-list mismatches. | |
753 | # Also, check for shadowing problems with -Wshadow, and for pointer | |
754 | # arithmetic problems with -Wpointer-arith. | |
755 | # These CFLAGS are pretty strict. If you build this target, you probably | |
756 | # have to have a recent version of gcc and glibc headers. | |
757 | # The hard-linking for-loop below ensures that there is a bin/ directory | |
758 | # full of all of the programs under test (except the ones that are required | |
759 | # for basic Makefile rules), all symlinked to the just-built "false" program. | |
760 | # This is to ensure that if ever a test neglects to make PATH include | |
761 | # the build srcdir, these always-failing programs will run. | |
762 | # Otherwise, it is too easy to test the wrong programs. | |
763 | # Note that "false" itself is a symlink to true, so it too will malfunction. | |
764 | my-distcheck: $(DIST_ARCHIVES) $(local-check) | |
765 | $(MAKE) syntax-check | |
766 | $(MAKE) check | |
767 | -rm -rf $(t) | |
768 | mkdir -p $(t) | |
769 | GZIP=$(GZIP_ENV) $(AMTAR) -C $(t) -zxf $(distdir).tar.gz | |
770 | cd $(t)/$(distdir) \ | |
771 | && ./configure --disable-nls \ | |
772 | && $(MAKE) CFLAGS='$(warn_cflags)' \ | |
773 | AM_MAKEFLAGS='$(null_AM_MAKEFLAGS)' \ | |
774 | && $(MAKE) dvi \ | |
775 | && $(install-transform-check) \ | |
776 | && $(my-instcheck) \ | |
777 | && mkdir $(bin) \ | |
778 | && ($(write_loser)) > $(bin)/loser \ | |
779 | && chmod a+x $(bin)/loser \ | |
780 | && for i in $(built_programs); do \ | |
781 | case $$i in \ | |
782 | rm|expr|basename|echo|sort|ls|tr);; \ | |
783 | cat|dirname|mv|wc);; \ | |
784 | *) ln $(bin)/loser $(bin)/$$i;; \ | |
785 | esac; \ | |
786 | done \ | |
787 | && ln -sf ../src/true $(bin)/false \ | |
788 | && PATH=`pwd`/$(bin):$$PATH $(MAKE) -C tests check \ | |
789 | && { test -d gnulib-tests \ | |
790 | && $(MAKE) -C gnulib-tests check \ | |
791 | || :; } \ | |
792 | && rm -rf $(bin) \ | |
793 | && $(MAKE) distclean | |
794 | (cd $(t) && mv $(distdir) $(distdir).old \ | |
795 | && $(AMTAR) -zxf - ) < $(distdir).tar.gz | |
796 | diff -ur $(t)/$(distdir).old $(t)/$(distdir) | |
797 | if test -f $(srcdir)/src/c99-to-c89.diff; then \ | |
798 | cd $(t)/$(distdir) \ | |
799 | && (cd src && patch -V never --fuzz=0 <c99-to-c89.diff) \ | |
800 | && ./configure --disable-largefile \ | |
801 | CFLAGS='-Werror -ansi -Wno-long-long' \ | |
802 | && $(MAKE); \ | |
803 | fi | |
804 | -rm -rf $(t) | |
805 | @echo "========================"; \ | |
806 | echo "$(distdir).tar.gz is ready for distribution"; \ | |
807 | echo "========================" | |
808 | ||
809 | WGET = wget | |
810 | WGETFLAGS = -C off | |
811 | ||
812 | rel-check: | |
813 | tarz=/tmp/rel-check-tarz-$$$$; \ | |
814 | md5_tmp=/tmp/rel-check-md5-$$$$; \ | |
815 | set -e; \ | |
816 | trap 'status=$$?; rm -f $$tarz $$md5_tmp; exit $$status' 0 1 2 3 15; \ | |
817 | $(WGET) $(WGETFLAGS) -q --output-document=$$tarz $(url); \ | |
818 | echo "$(md5) -" > $$md5_tmp; \ | |
819 | md5sum -c $$md5_tmp < $$tarz | |
820 | ||
821 | rel-files = $(DIST_ARCHIVES) | |
822 | ||
823 | gnulib-version = $$(cd $(gnulib_dir) && git describe) | |
824 | ||
825 | announcement: NEWS ChangeLog $(rel-files) | |
826 | @./build-aux/announce-gen \ | |
827 | --release-type=$(RELEASE_TYPE) \ | |
828 | --package=$(PACKAGE) \ | |
829 | --prev=$(PREV_VERSION) \ | |
830 | --curr=$(VERSION) \ | |
831 | --gpg-key-id=$(gpg_key_ID) \ | |
832 | --news=NEWS \ | |
548e2104 | 833 | --bootstrap-tools=autoconf,automake,flex,gnulib \ |
8fa36911 JD |
834 | --gnulib-version=$(gnulib-version) \ |
835 | $(addprefix --url-dir=, $(url_dir_list)) | |
836 | ||
837 | ## ---------------- ## | |
838 | ## Updating files. ## | |
839 | ## ---------------- ## | |
840 | ||
841 | ftp-gnu = ftp://ftp.gnu.org/gnu | |
842 | www-gnu = http://www.gnu.org | |
843 | ||
844 | # Use mv, if you don't have/want move-if-change. | |
845 | move_if_change ?= move-if-change | |
846 | ||
847 | emit_upload_commands: | |
848 | @echo ===================================== | |
849 | @echo ===================================== | |
850 | @echo "$(srcdir)/build-aux/gnupload $(GNUPLOADFLAGS) \\" | |
851 | @echo " --to $(gnu_rel_host):$(PACKAGE) \\" | |
852 | @echo " $(rel-files)" | |
853 | @echo '# send the /tmp/announcement e-mail' | |
854 | @echo ===================================== | |
855 | @echo ===================================== | |
856 | ||
857 | noteworthy = * Noteworthy changes in release ?.? (????-??-??) [?] | |
858 | define emit-commit-log | |
859 | printf '%s\n' 'post-release administrivia' '' \ | |
860 | '* NEWS: Add header line for next release.' \ | |
861 | '* .prev-version: Record previous version.' \ | |
862 | '* cfg.mk (old_NEWS_hash): Auto-update.' | |
863 | endef | |
864 | ||
865 | .PHONY: alpha beta major | |
866 | alpha beta major: $(local-check) writable-files | |
867 | test $@ = major \ | |
868 | && { echo $(VERSION) | grep -E '^[0-9]+(\.[0-9]+)+$$' \ | |
869 | || { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\ | |
870 | || : | |
871 | $(MAKE) vc-dist | |
872 | $(MAKE) news-date-check | |
873 | $(MAKE) -s announcement RELEASE_TYPE=$@ > /tmp/announce-$(my_distdir) | |
874 | if test -d $(release_archive_dir); then \ | |
875 | ln $(rel-files) $(release_archive_dir); \ | |
876 | chmod a-w $(rel-files); \ | |
877 | fi | |
878 | $(MAKE) -s emit_upload_commands RELEASE_TYPE=$@ | |
879 | echo $(VERSION) > $(prev_version_file) | |
880 | $(MAKE) update-NEWS-hash | |
881 | perl -pi -e '$$. == 3 and print "$(noteworthy)\n\n\n"' NEWS | |
882 | $(emit-commit-log) > .ci-msg | |
883 | $(VC) commit -F .ci-msg |