[tz] [PROPOSED] Make Makefile safer for parallelism
Paul Eggert
eggert at cs.ucla.edu
Wed Jun 27 00:57:38 UTC 2018
Although this still does not fully work with GNU Make,
it’s better than what we had.
* Makefile (TIME_T_ALTERNATIVES_HEAD)
(TIME_T_ALTERNATIVES_TAIL): New macros.
(TIME_T_ALTERNATIVES): Use them.
(TZS_CUTOFF_FLAG): New macro.
($(ZDS)): Use it, so that submakes can use -t instead of -c cutoffs.
(EIGHT_YARDS): New macro.
(ENCHILADA): Use it.
(INSTALL_DATA_DEPS, TZS_NEW_DEPS): New macros.
(install_data, posix_only, right_only, posix_packrat, $(TZS_NEW)):
Use them to avoid duplicate work with GNU make -j.
($(TZS_NEW), check_zishrink_posix, check_zishrink_right, check_public)
(check_time_t_alternatives):
Use rule-specific temporary directories so that other rules can
run in parallel.
($(TZS_NEW)): Check for sort failure.
($(TZS)): Simply touch it if it doesn’t exist, so that it’s empty.
(check_tzs): Treat empty $(TZS) as nonexistent.
(check_character_set, check_white_space, check_name_lengths)
(check_sorted, check_links, check_tables, check_tzs, check_web)
(check_zishrink, check_public):
No longer phony.
(check_zishrink_posix, check_zishrink_right)
(typecheck_long_long, typecheck_unsigned):
New rules, so that they can be done in parallel.
(clean_misc): Clean the timestamp files that are now made due
to rules no longer being phony.
(set-timestamps.out): Do not set timestamp of $(TZS).
(set-tzs-timestamp.out): New rule.
(check_time_t_alternatives): Break into subrules, one for each
alternative, so that they can be done in parallel.
(tarballs, rearguard_tarballs, traditional_tarballs)
(signatures, rearguard_signatures, traditional_signatures):
Depend on set-timestamps.out and rearguard.zi.
(tzdb-$(VERSION).tar.lz): Depend on set-tzs-timestamp.out.
(TYPECHECK_CFLAGS): New macro.
---
Makefile | 240 +++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 142 insertions(+), 98 deletions(-)
diff --git a/Makefile b/Makefile
index 2289dff..29058e5 100644
--- a/Makefile
+++ b/Makefile
@@ -106,8 +106,10 @@ MANDIR = $(TOPDIR)/$(USRSHAREDIR)/man
LIBDIR = $(TOPDIR)/$(USRDIR)/lib
-# Types to try, as an alternative to time_t. int64_t should be first.
-TIME_T_ALTERNATIVES = int64_t int32_t uint32_t uint64_t
+# Types to try, as an alternative to time_t.
+TIME_T_ALTERNATIVES = $(TIME_T_ALTERNATIVES_HEAD) $(TIME_T_ALTERNATIVES_TAIL)
+TIME_T_ALTERNATIVES_HEAD = int64_t
+TIME_T_ALTERNATIVES_TAIL = int32_t uint32_t uint64_t
# What kind of TZif data files to generate.
# (TZif is the binary time zone data format that zic generates.)
@@ -493,11 +495,14 @@ AWK_SCRIPTS= checklinks.awk checktab.awk leapseconds.awk \
ziguard.awk zishrink.awk
MISC= $(AWK_SCRIPTS) zoneinfo2tdf.pl
TZS_YEAR= 2050
+TZS_CUTOFF_FLAG= -c $(TZS_YEAR)
TZS= to$(TZS_YEAR).tzs
TZS_NEW= to$(TZS_YEAR)new.tzs
TZS_DEPS= $(PRIMARY_YDATA) asctime.c localtime.c \
private.h tzfile.h zdump.c zic.c
-ENCHILADA= $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC) $(TZS) tzdata.zi
+# EIGHT_YARDS is just a yard short of the whole ENCHILADA.
+EIGHT_YARDS = $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC) tzdata.zi
+ENCHILADA = $(EIGHT_YARDS) $(TZS)
# Consult these files when deciding whether to rebuild the 'version' file.
# This list is not the same as the output of 'git ls-files', since
@@ -606,14 +611,16 @@ INSTALLARGS = \
YEARISTYPE='$(YEARISTYPE)' \
ZIC='$(ZIC)'
+INSTALL_DATA_DEPS = zic leapseconds yearistype tzdata.zi
+
# 'make install_data' installs one set of TZif files.
-install_data: zic leapseconds yearistype tzdata.zi
+install_data: $(INSTALL_DATA_DEPS)
$(ZIC_INSTALL) tzdata.zi
-posix_only:
+posix_only: $(INSTALL_DATA_DEPS)
$(MAKE) $(INSTALLARGS) LEAPSECONDS= install_data
-right_only:
+right_only: $(INSTALL_DATA_DEPS)
$(MAKE) $(INSTALLARGS) LEAPSECONDS='-L leapseconds' \
install_data
@@ -640,7 +647,7 @@ posix_right: posix_only
# This obsolescent rule is present for backwards compatibility with
# tz releases 2014g through 2015g. It should go away eventually.
-posix_packrat:
+posix_packrat: $(INSTALL_DATA_DEPS)
$(MAKE) $(INSTALLARGS) PACKRATDATA=backzone posix_only
zones: $(REDO)
@@ -651,29 +658,33 @@ ZDS = dummy.zd
# Rule used only by submakes invoked by the $(TZS_NEW) rule.
# It is separate so that GNU 'make -j' can run instances in parallel.
$(ZDS): zdump
- ./zdump -i -c $(TZS_YEAR) '$(wd)/'$$(expr $@ : '\(.*\).zd') >$@
-
-$(TZS_NEW): tzdata.zi zdump zic
- rm -fr tzs.dir
- mkdir tzs.dir
- $(zic) -d tzs.dir tzdata.zi
+ ./zdump -i $(TZS_CUTOFF_FLAG) '$(wd)/'$$(expr $@ : '\(.*\).zd') \
+ >$@
+
+TZS_NEW_DEPS = tzdata.zi zdump zic
+$(TZS_NEW): $(TZS_NEW_DEPS)
+ rm -fr tzs$(TZS_YEAR).dir
+ mkdir tzs$(TZS_YEAR).dir
+ $(zic) -d tzs$(TZS_YEAR).dir tzdata.zi
$(AWK) '/^L/{print "Link\t" $$2 "\t" $$3}' \
tzdata.zi | LC_ALL=C sort >$@.out
wd=`pwd` && \
- set x `$(AWK) '/^Z/{print "tzs.dir/" $$2 ".zd"}' tzdata.zi \
+ x=`$(AWK) '/^Z/{print "tzs$(TZS_YEAR).dir/" $$2 ".zd"}' \
+ tzdata.zi \
| LC_ALL=C sort -t . -k 2,2` && \
+ set x $$x && \
shift && \
ZDS=$$* && \
- $(MAKE) wd="$$wd" TZS_YEAR=$(TZS_YEAR) ZDS="$$ZDS" $$ZDS && \
- sed 's,^TZ=".*tzs\.dir/,TZ=",' $$ZDS >>$@.out
- rm -fr tzs.dir
+ $(MAKE) wd="$$wd" TZS_CUTOFF_FLAG="$(TZS_CUTOFF_FLAG)" \
+ ZDS="$$ZDS" $$ZDS && \
+ sed 's,^TZ=".*\.dir/,TZ=",' $$ZDS >>$@.out
+ rm -fr tzs$(TZS_YEAR).dir
mv $@.out $@
-# If $(TZS) does not already exist (e.g., old-format tarballs), create it.
-# If it exists but 'make check_tzs' fails, a maintainer should inspect the
+# If $(TZS) exists but 'make check_tzs' fails, a maintainer should inspect the
# failed output and fix the inconsistency, perhaps by running 'make force_tzs'.
$(TZS):
- $(MAKE) force_tzs
+ touch $@
force_tzs: $(TZS_NEW)
cp $(TZS_NEW) $(TZS)
@@ -718,12 +729,14 @@ check_character_set: $(ENCHILADA)
leapseconds yearistype.sh zone.tab && \
! grep -Env $(OK_LINE) $(ENCHILADA); \
}
+ touch $@
check_white_space: $(ENCHILADA)
patfmt=' \t|[\f\r\v]' && pat=`printf "$$patfmt\\n"` && \
! grep -En "$$pat" $(ENCHILADA)
! grep -n '[[:space:]]$$' \
$$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list)
+ touch $@
PRECEDES_FILE_NAME = ^(Zone|Link[[:space:]]+[^[:space:]]+)[[:space:]]+
FILE_NAME_COMPONENT_TOO_LONG = \
@@ -732,6 +745,7 @@ FILE_NAME_COMPONENT_TOO_LONG = \
check_name_lengths: $(TDATA_TO_CHECK) backzone
! grep -En '$(FILE_NAME_COMPONENT_TOO_LONG)' \
$(TDATA_TO_CHECK) backzone
+ touch $@
CHECK_CC_LIST = { n = split($$1,a,/,/); for (i=2; i<=n; i++) print a[1], a[i]; }
@@ -744,52 +758,61 @@ check_sorted: backward backzone iso3166.tab zone.tab zone1970.tab
LC_ALL=C sort -c
$(AWK) '/^[^#]/ $(CHECK_CC_LIST)' zone1970.tab | \
LC_ALL=C sort -cu
+ touch $@
check_links: checklinks.awk $(TDATA_TO_CHECK) tzdata.zi
$(AWK) -f checklinks.awk $(TDATA_TO_CHECK)
$(AWK) -f checklinks.awk tzdata.zi
+ touch $@
check_tables: checktab.awk $(PRIMARY_YDATA) $(ZONETABLES)
for tab in $(ZONETABLES); do \
$(AWK) -f checktab.awk -v zone_table=$$tab $(PRIMARY_YDATA) \
|| exit; \
done
+ touch $@
check_tzs: $(TZS) $(TZS_NEW)
- diff -u $(TZS) $(TZS_NEW)
+ if test -s $(TZS); then \
+ diff -u $(TZS) $(TZS_NEW); \
+ else \
+ cp $(TZS_NEW) $(TZS); \
+ fi
+ touch $@
# This checks only the HTML 4.01 strict page.
# To check the the other pages, use <https://validator.w3.org/>.
check_web: tz-how-to.html
$(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) tz-how-to.html
+ touch $@
# Check that zishrink.awk does not alter the data, and that ziguard.awk
# preserves main-format data.
-check_zishrink: zic leapseconds $(PACKRATDATA) $(TDATA) \
- $(DATAFORM).zi tzdata.zi
- for type in posix right; do \
- mkdir -p time_t.dir/$$type time_t.dir/$$type-t \
- time_t.dir/$$type-shrunk && \
- case $$type in \
- right) leap='-L leapseconds';; \
- *) leap=;; \
- esac && \
- $(ZIC) $$leap -d time_t.dir/$$type $(DATAFORM).zi && \
+check_zishrink: check_zishrink_posix check_zishrink_right
+check_zishrink_posix check_zishrink_right: \
+ zic leapseconds $(PACKRATDATA) $(TDATA) $(DATAFORM).zi tzdata.zi
+ rm -fr $@.dir $@-t.dir $@-shrunk.dir
+ mkdir $@.dir $@-t.dir $@-shrunk.dir
+ case $@ in \
+ *_right) leap='-L leapseconds';; \
+ *) leap=;; \
+ esac && \
+ $(ZIC) $$leap -d $@.dir $(DATAFORM).zi && \
+ $(ZIC) $$leap -d $@-shrunk.dir tzdata.zi && \
case $(DATAFORM) in \
main) \
- $(ZIC) $$leap -d time_t.dir/$$type-t $(TDATA) && \
+ $(ZIC) $$leap -d $@-t.dir $(TDATA) && \
$(AWK) '/^Rule/' $(TDATA) | \
- $(ZIC) $$leap -d time_t.dir/$$type-t - \
- $(PACKRATDATA) && \
- diff -r time_t.dir/$$type time_t.dir/$$type-t;; \
- esac && \
- $(ZIC) $$leap -d time_t.dir/$$type-shrunk tzdata.zi && \
- diff -r time_t.dir/$$type time_t.dir/$$type-shrunk || exit; \
- done
- rm -fr time_t.dir
+ $(ZIC) $$leap -d $@-t.dir - $(PACKRATDATA) && \
+ diff -r $@.dir $@-t.dir;; \
+ esac
+ diff -r $@.dir $@-shrunk.dir
+ rm -fr $@.dir $@-t.dir $@-shrunk.dir
+ touch $@
clean_misc:
- rm -f core *.o *.out \
+ rm -f *.o *.out $(TIME_T_ALTERNATIVES) \
+ check_* core typecheck_* \
date tzselect version.h zdump zic yearistype libtz.a
clean: clean_misc
rm -fr *.dir *.zi tzdb-*/ $(TZS_NEW)
@@ -826,10 +849,10 @@ $(MANTXTS): workman.sh
# If git or GNU 'touch' is absent, don't bother to sync with git timestamps.
# Also, set the timestamp of each prebuilt file like 'leapseconds'
# to be the maximum of the files it depends on.
-set-timestamps.out: $(ENCHILADA)
+set-timestamps.out: $(EIGHT_YARDS)
rm -f $@
if (type git) >/dev/null 2>&1 && \
- files=`git ls-files $(ENCHILADA)` && \
+ files=`git ls-files $(EIGHT_YARDS)` && \
touch -md @1 test.out; then \
rm -f test.out && \
for file in $$files; do \
@@ -847,62 +870,74 @@ set-timestamps.out: $(ENCHILADA)
exit; \
done
touch -cmr `ls -t $(TZDATA_ZI_DEPS) | sed 1q` tzdata.zi
- touch -cmr `ls -t $(TZS_DEPS) | sed 1q` $(TZS)
touch -cmr `ls -t $(VERSION_DEPS) | sed 1q` version
touch $@
+set-tzs-timestamp.out: $(TZS)
+ touch -cmr `ls -t $(TZS_DEPS) | sed 1q` $(TZS)
+ touch $@
# The zics below ensure that each data file can stand on its own.
# We also do an all-files run to catch links to links.
-check_public:
- $(MAKE) maintainer-clean
- $(MAKE) CFLAGS='$(GCC_DEBUG_FLAGS)' ALL
- mkdir -p public.dir
- for i in $(TDATA_TO_CHECK) tzdata.zi; do \
- $(zic) -v -d public.dir $$i 2>&1 || exit; \
+check_public: $(VERSION_DEPS)
+ rm -fr public.dir
+ mkdir public.dir
+ ln $(VERSION_DEPS) public.dir
+ cd public.dir && $(MAKE) CFLAGS='$(GCC_DEBUG_FLAGS)' ALL
+ for i in $(TDATA_TO_CHECK) public.dir/tzdata.zi; do \
+ public.dir/zic -v -d public.dir/zoneinfo $$i 2>&1 || exit; \
done
- $(zic) -v -d public.dir $(TDATA_TO_CHECK)
+ public.dir/zic -v -d public.dir/zoneinfo-all $(TDATA_TO_CHECK)
rm -fr public.dir
+ touch $@
# Check that the code works under various alternative
# implementations of time_t.
-check_time_t_alternatives:
- if diff -q Makefile Makefile 2>/dev/null; then \
- quiet_option='-q'; \
- else \
- quiet_option=''; \
- fi && \
+check_time_t_alternatives: $(TIME_T_ALTERNATIVES)
+$(TIME_T_ALTERNATIVES_TAIL): $(TIME_T_ALTERNATIVES_HEAD)
+$(TIME_T_ALTERNATIVES): $(VERSION_DEPS)
+ rm -fr $@.dir
+ mkdir $@.dir
+ ln $(VERSION_DEPS) $@.dir
+ case $@ in \
+ int32_t) range=-2147483648,2147483648;; \
+ u*) range=0,4294967296;; \
+ *) range=-4294967296,4294967296;; \
+ esac && \
wd=`pwd` && \
zones=`$(AWK) '/^[^#]/ { print $$3 }' <zone1970.tab` && \
- for type in $(TIME_T_ALTERNATIVES); do \
- mkdir -p time_t.dir/$$type && \
- $(MAKE) clean_misc && \
- $(MAKE) TOPDIR="$$wd/time_t.dir/$$type" \
- CFLAGS='$(CFLAGS) -Dtime_tz='"'$$type'" \
+ if test $@ = $(TIME_T_ALTERNATIVES_HEAD); then \
+ range_target=; \
+ else \
+ range_target=to$$range.tzs; \
+ fi && \
+ (cd $@.dir && \
+ $(MAKE) TOPDIR="$$wd/$@.dir" \
+ CFLAGS='$(CFLAGS) -Dtime_tz='"'$@'" \
REDO='$(REDO)' \
- install && \
- diff $$quiet_option -r \
- time_t.dir/int64_t/etc \
- time_t.dir/$$type/etc && \
- diff $$quiet_option -r \
- time_t.dir/int64_t/usr/share \
- time_t.dir/$$type/usr/share && \
- case $$type in \
- int32_t) range=-2147483648,2147483647;; \
- uint32_t) range=0,4294967296;; \
- int64_t) continue;; \
- *u*) range=0,10000000000;; \
- *) range=-10000000000,10000000000;; \
- esac && \
- echo checking $$type zones ... && \
- time_t.dir/int64_t/usr/bin/zdump -V -t $$range $$zones \
- >time_t.dir/int64_t.out && \
- time_t.dir/$$type/usr/bin/zdump -V -t $$range $$zones \
- >time_t.dir/$$type.out && \
- diff -u time_t.dir/int64_t.out time_t.dir/$$type.out \
- || exit; \
- done
- rm -fr time_t.dir
+ D=$$wd/$@.dir \
+ TZS_YEAR="$$range" TZS_CUTOFF_FLAG="-t $$range" \
+ install $$range_target) && \
+ test $@ = $(TIME_T_ALTERNATIVES_HEAD) || { \
+ (cd $(TIME_T_ALTERNATIVES_HEAD).dir && \
+ $(MAKE) TOPDIR="$$wd/$@.dir" \
+ TZS_YEAR="$$range" TZS_CUTOFF_FLAG="-t $$range" \
+ D=$$wd/$@.dir \
+ to$$range.tzs) && \
+ diff -u $(TIME_T_ALTERNATIVES_HEAD).dir/to$$range.tzs \
+ $@.dir/to$$range.tzs && \
+ if diff -q Makefile Makefile 2>/dev/null; then \
+ quiet_option='-q'; \
+ else \
+ quiet_option=''; \
+ fi && \
+ diff $$quiet_option -r $(TIME_T_ALTERNATIVES_HEAD).dir/etc \
+ $@.dir/etc && \
+ diff $$quiet_option -r \
+ $(TIME_T_ALTERNATIVES_HEAD).dir/usr/share \
+ $@.dir/usr/share; \
+ }
+ touch $@
TRADITIONAL_ASC = \
tzcode$(VERSION).tar.gz.asc \
@@ -913,7 +948,8 @@ ALL_ASC = $(TRADITIONAL_ASC) $(REARGUARD_ASC) \
tzdb-$(VERSION).tar.lz.asc
tarballs rearguard_tarballs traditional_tarballs \
-signatures rearguard_signatures traditional_signatures: version
+signatures rearguard_signatures traditional_signatures: \
+ version set-timestamps.out rearguard.zi
VERSION=`cat version` && \
$(MAKE) VERSION="$$VERSION" $@_version
@@ -963,7 +999,7 @@ tzdata$(VERSION)-rearguard.tar.gz: rearguard.zi set-timestamps.out
gzip $(GZIPFLAGS)) >$@.out
mv $@.out $@
-tzdb-$(VERSION).tar.lz: set-timestamps.out
+tzdb-$(VERSION).tar.lz: set-timestamps.out set-tzs-timestamp.out
rm -fr tzdb-$(VERSION)
mkdir tzdb-$(VERSION)
ln $(ENCHILADA) tzdb-$(VERSION)
@@ -979,14 +1015,24 @@ tzdb-$(VERSION).tar.lz.asc: tzdb-$(VERSION).tar.lz
$(ALL_ASC):
gpg2 --armor --detach-sign $?
-typecheck:
- $(MAKE) clean
- for i in "long long" unsigned; \
- do \
- $(MAKE) CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \
- ./zdump -v Europe/Rome ; \
- $(MAKE) clean ; \
- done
+TYPECHECK_CFLAGS = $(CFLAGS) -DTYPECHECK -D__time_t_defined -D_TIME_T
+typecheck: typecheck_long_long typecheck_unsigned
+typecheck_long_long typecheck_unsigned: $(VERSION_DEPS)
+ rm -fr $@.dir
+ mkdir $@.dir
+ ln $(VERSION_DEPS) $@.dir
+ cd $@.dir && \
+ case $@ in \
+ *_long_long) i="long long";; \
+ *_unsigned ) i="unsigned" ;; \
+ esac && \
+ typecheck_cflags='' && \
+ $(MAKE) \
+ CFLAGS="$(TYPECHECK_CFLAGS) \"-Dtime_t=$$i\"" \
+ TOPDIR="`pwd`" \
+ install
+ $@.dir/zdump -i -c 1970,1971 Europe/Rome
+ touch $@
zonenames: tzdata.zi
@$(AWK) '/^Z/ { print $$2 } /^L/ { print $$3 }' tzdata.zi
@@ -1002,9 +1048,7 @@ zic.o: private.h tzfile.h version.h
.KEEP_STATE:
.PHONY: ALL INSTALL all
-.PHONY: check check_character_set check_links check_name_lengths
-.PHONY: check_public check_sorted check_tables
-.PHONY: check_time_t_alternatives check_tzs check_web check_white_space
+.PHONY: check check_time_t_alternatives
.PHONY: check_zishrink
.PHONY: clean clean_misc dummy.zd force_tzs
.PHONY: install install_data maintainer-clean names
--
2.7.4
More information about the tz
mailing list