locale: rebuild the host generators when the generated headers change
gen_ldc includes c8tables.h, wctables.h, locale_tables.h and
locale_collate.h, all of which this Makefile generates; gen_locale includes
c8tables.h. DEPH-gen_ldc and DEPH-gen_locale name those headers correctly and
have done so since 2005, but since b46830f8b ("fix locale dependencies",
2008-10-14) they are attached to $(locale_DIR)/gen_ldc.c -- a target with no
recipe. make marks the .c up to date and never propagates anything to the
binary, so two things are lost:
- ordering. Nothing says the headers must exist before the compile runs.
Before 2008 this was an order-only prerequisite of the binary, which did
guarantee it.
- rebuilding. A generator built against an older layout of the tables is
never recompiled, however often the tables change.
The second one is silent and does not need -j to bite. Seen while building
arc from a long-lived tree: after a config change regenerated the tables, the
existing gen_ldc kept running and wrote locale_data.c in its old layout,
932841 bytes instead of 1247559, with the multi-byte digit strings missing.
At runtime every outdigit offset was zero, so all ten outdigit pointers aimed
at the same '\0' and the assert in libc/misc/locale/locale.c fired. Only arc
noticed, because config.arc is the one that sets DOASSERTS=y; elsewhere the
same blob just yields wrong locale data.
The first one used to be covered by accident. 4c68c74d9 ("locale: disable
parallel build as it is broken here", 2016-09-27) added a bare .NOTPARALLEL:,
which -- because this file is include-d into the top-level Makefile -- ran the
entire build serially and thereby happened to order the headers first. That
is very likely the race the commit message means. Scoping .NOTPARALLEL to the
locale targets in 755281340 restored parallel builds and, on GNU make 4.4 or
newer, exposed the undeclared edge again.
Fix it where it belongs: make the headers ordinary prerequisites of the
binaries. That gives ordering and rebuilding at once, independent of the make
version and of -jN, and is strictly stronger than the order-only form of 2005.
The recipe-less .c lines are left alone; they are now redundant.
hcompile.u passes $^ to the compiler, so the added prerequisites would land on
the gcc command line as input files. Restrict that to %.c and %.o -- the only
things it was ever meant to pass -- so header prerequisites can be declared
anywhere hcompile.u is used.
Signed-off-by: Ramin Moussavi <lordrasmus@gmail.com>