]> git.draconx.ca Git - dxcommon.git/commitdiff
fix-gnulib.pl: Convert rules to dirstamp prerequisites.
authorNick Bowler <nbowler@draconx.ca>
Wed, 6 Dec 2023 04:00:42 +0000 (23:00 -0500)
committerNick Bowler <nbowler@draconx.ca>
Wed, 6 Dec 2023 04:00:42 +0000 (23:00 -0500)
ULTRIX 4.5 make fails during rule lookup when it tries to build a
target in a nonexistent directory that might have inference rules
associated with it (i.e., ends with a defined suffix), for example:

  % echo 'nonexistent/baz.o: ;' | make -f -
  Directory nonexistent/: Make: Cannot open.  Stop.

We can work around this problem by using a prerequisite to create
the output directory instead of creating it directly in the rule.
Automake itself actually does this already using dirstamps, so
let's try to patch things to use the same mechanism.  As a bonus,
this should reduce the number of mkdir invocations.

This breaks some of the relevant tests which are looking for specific
output.  Drop the %reldir% test completely as it appears every usage
in gnulib is for this exact scenario, and patch the subdirectory test
to expect the new output.

scripts/fix-gnulib.pl
tests/scripts.at

index 640f1cd66897b031a769560f40349eb23b8e5c43..9a1f2731c24f477d9e37d8a83ac065ca0c8121c5 100755 (executable)
@@ -63,7 +63,6 @@ open STDOUT, ">", $output or die "$output: $!\n" if (defined $output);
 open STDIN,  "<", $input  or die "$input: $!\n"  if (defined $input);
 
 my $printed_header = 0;
-my $check_mkdir;
 my @cleanfiles;
 
 # Hashes to record make variables used in the automake source.  The allvars
@@ -72,6 +71,13 @@ my @cleanfiles;
 # the value is always set to 1.
 my (%allvars, %sourcevars);
 
+# Collected names of subdirectories that may need to be created at build time.
+# The keys are directory names, the values are targets.
+my %gl_dirstamps;
+
+# State to drop MKDIR_P lines that have been replaced by dirstamps.
+my ($have_dirstamp) = (0);
+
 sub drop {
        undef $_;
        next;
@@ -123,7 +129,21 @@ sub mangle_target {
        @left  = map(mangle_file($_), @left);
        @right = map(mangle_file($_), @right);
 
-       return join(" ", @left) . ": " . join(" ", @right) . "\n";
+       my @dirstamps = get_dirstamps(@left);
+
+       return join(" ", @left) . ": " . join(" ", @dirstamps, @right) . "\n";
+}
+
+sub get_dirstamps {
+       my %h;
+
+       foreach (@_) {
+               next unless $_[0] =~ m|^(lib(/.*)?)/[^/]*$|;
+
+               $h{$gl_dirstamps{$1} = "$1/\$(am__dirstamp)"} = 1;
+       }
+
+       return keys %h;
 }
 
 while (<STDIN>) {
@@ -232,24 +252,11 @@ EOF
        # ordinary variable so we can deal with them later.
        s/BUILT_SOURCES/gnulib_core_headers/;
 
-       # Rules for "toplevel" header files do not include commands to create
-       # the target directory; let's add that.
-       if (defined $check_mkdir) {
-               if (/gl_V_at/ || /AM_V_GEN/ and not /MKDIR_P/) {
-                       my $dir = "lib/$check_mkdir";
-                       $dir =~ s|/[^/]*||;
-
-                       print "\t\$(AM_V_GEN)\$(MKDIR_P) $dir\n";
-                       s/AM_V_GEN|gl_V_at/AM_V_at/;
-               }
-               undef $check_mkdir
-       }
-
        # Targets are similar to variables: the target and its dependencies
        # need to be mangled.
        if (/^([^\t:]*):/) {
-               $check_mkdir = $1;
                $_ = mangle_target($_);
+               $have_dirstamp = /am__dirstamp/;
        }
 
        # MKDIR_P commands need to be fixed up; in principle Gnulib could also
@@ -271,12 +278,28 @@ EOF
        # component.
        s/t-\$@/\$\@-t/g;
 
-       # Finally, $(srcdir), $(builddir) and %reldir% need to be fixed up.
+       # $(srcdir), $(builddir) and %reldir% need to be fixed up.
        s:\$\(srcdir\):\$\(top_srcdir\)/lib:g;
        s:\$\(builddir\):\$\(top_builddir\)/lib:g;
        s:%reldir%:lib:g;
+
+       # If we installed a dirstamp prerequisite for this target, don't
+       # emit the mkdir line which creates the output directory.
+       if ($have_dirstamp && m|\$[({]MKDIR_P[})][ '"]*lib/|) {
+               drop unless s/^(\t\$[({](AM_V_GEN|gl_V_at)[})]).*/\1:/;
+       }
+       undef $have_dirstamp if /^\t/;
 } continue { s/(\n.)/\\\1/g; print; };
 
+# Define a bunch of fake programs which will ensure Automake produces the
+# necessary dirstamp rules, as unfortunately we cannot know in advance which
+# will be generated, and the usual Automake behaviour where generated rules
+# are suppressed by rules in Makefile.am doesn't actaully work for these.
+print <<EOF foreach (keys %gl_dirstamps);
+EXTRA_PROGRAMS += $_/gl-dirstamp
+${\(y|/|_|r)}_gl_dirstamp_SOURCES =
+EOF
+
 print <<'EOF' if ($use_libtool);
 gnulib_lt_objects = $(libgnu_la_OBJECTS) $(gl_LTLIBOBJS)
 gnulib_objects = $(gnulib_lt_objects)
index 7a873a9086fcdaa4b4007f935ad34dcbd938ebb6..92db0a1675ab474b5e6fb15469ebd575c52f23f8 100644 (file)
@@ -910,38 +910,6 @@ grep SED_HEADER test.mk], [0], [expout])
 
 AT_CLEANUP
 
-AT_SETUP([fix-gnulib.pl %reldir% substitution])
-AT_KEYWORDS([fix-gnulib perl script scripts])
-
-test_gnulib_mk sys_types >test.mk.in
-AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
-
-sed -n <test.mk.in >expout '
-$G
-$p
-$b
-/^## begin gnulib/,/^## end   gnulib/!b
-/^#/{
-p
-b
-}
-s|(srcdir)|(top_srcdir)|
-s|%reldir%|lib|
-s|BUILT_SOURCES|gnulib_core_headers|
-s|sys[[/_]]|lib/&|g
-/^MOSTLYCLEANFILES/{
-h
-b
-}
-p'
-
-AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
-sed -n -e '/^## begin gnulib/,/^## end   gnulib/p' \
-       -e '/CLEANFILES/p' test.mk],
-[0], [expout])
-
-AT_CLEANUP
-
 AT_SETUP([fix-gnulib.pl warning removal])
 AT_KEYWORDS([fix-gnulib perl script scripts])
 
@@ -965,34 +933,31 @@ AT_CLEANUP
 AT_SETUP([fix-gnulib.pl header directory creation])
 AT_KEYWORDS([fix-gnulib perl script scripts])
 
-AT_DATA([extract.sed],
-[[/AM_V_GEN/b ok
-/gl_V_at/b ok
-s/:.*/:/
-h
-b
-:ok
-s/'//g
-x
-G
-p
-n
-s/[)].*/)/
-p
+AT_DATA([extract.awk],
+[[$0 !~ /^\t/ && $1 ~ /:$/ {
+  target=$1;
+
+  for (i = 2; i <= NF; i++) {
+    if ($i ~ /am__dirstamp/)
+      target = target " " $i;
+  }
+
+  next;
+}
+
+target != "" && sub(/[$][({](AM_V_GEN|gl_V_at)[})].*$/, "[OK]") {
+  print target, $1;
+}
+
+{ target=""; }
 ]])
 
 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
-sed -n -f extract.sed test.mk], [0],
-[[lib/alloca.h:
-       $(AM_V_GEN)$(MKDIR_P) lib
-       $(AM_V_at)
-lib/sys/types.h:
-       $(AM_V_GEN)$(MKDIR_P) lib/sys
-       $(AM_V_at)
-lib/stddef.h:
-       $(AM_V_GEN)$(MKDIR_P) lib
-       $(AM_V_at)
+$AWK -f extract.awk test.mk], [0],
+[[lib/alloca.h: lib/$(am__dirstamp) [OK]
+lib/sys/types.h: lib/sys/$(am__dirstamp) [OK]
+lib/stddef.h: lib/$(am__dirstamp) [OK]
 ]])
 
 AT_CLEANUP