parse-datetime: Make the build rule work with parallel 'make'.
[gnulib.git] / build-aux / prefix-gnulib-mk
blob81ca8a14665f2116d80d60a4c50cf9bfd78a3b11
1 #!/bin/sh
2 #! -*-perl-*-
4 # Rewrite a gnulib.mk, adding prefixes to work with automake's subdir-objects.
6 # Copyright (C) 2012-2020 Free Software Foundation, Inc.
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 # Written by Jim Meyering
23 # This is a prologue that allows to run a perl script as an executable
24 # on systems that are compliant to a POSIX version before POSIX:2017.
25 # On such systems, the usual invocation of an executable through execlp()
26 # or execvp() fails with ENOEXEC if it is a script that does not start
27 # with a #! line. The script interpreter mentioned in the #! line has
28 # to be /bin/sh, because on GuixSD systems that is the only program that
29 # has a fixed file name. The second line is essential for perl and is
30 # also useful for editing this file in Emacs. The next two lines below
31 # are valid code in both sh and perl. When executed by sh, they re-execute
32 # the script through the perl program found in $PATH. The '-x' option
33 # is essential as well; without it, perl would re-execute the script
34 # through /bin/sh. When executed by perl, the next two lines are a no-op.
35 eval 'exec perl -wSx "$0" "$@"'
36 if 0;
38 my $VERSION = '2020-04-04 15:07'; # UTC
39 # The definition above must lie within the first 8 lines in order
40 # for the Emacs time-stamp write hook (at end) to update it.
41 # If you change this file with Emacs, please let the write hook
42 # do its job. Otherwise, update this string manually.
44 use strict;
45 use IO::File;
46 use Getopt::Long;
47 use File::Basename; # for dirname
49 (my $ME = $0) =~ s|.*/||;
51 my $prefix;
52 my $lib_name;
54 sub usage ($)
56 my ($exit_code) = @_;
57 my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
58 if ($exit_code != 0)
60 print $STREAM "Try '$ME --help' for more information.\n";
62 else
64 print $STREAM <<EOF;
65 Usage: $ME --lib-name=NAME FILE
66 or: $ME [--help|--version]
67 Rewrite a gnulib-tool-generated FILE like lib/gnulib.mk to work with
68 automake's subdir-objects.
70 OPTIONS:
72 This option must be specified:
74 --lib-name=NAME library name, often "lib\$project"
76 The following are optional:
78 --help display this help and exit
79 --version output version information and exit
81 EOF
83 exit $exit_code;
86 # contents ($FILE_NAME)
87 # ---------------------
88 sub contents ($)
90 my ($file) = @_;
91 local $/; # Turn on slurp-mode.
92 my $f = new IO::File "< $file" or die "$file";
93 my $contents = $f->getline or die "$file";
94 $f->close;
95 return $contents;
98 # prefix_word ($WORD)
99 # -------------------
100 # Do not prefix special words such as variable dereferences. Also,
101 # "Makefile" is really "Makefile", since precisely there is no
102 # lib/Makefile.
103 sub prefix_word ($)
105 local ($_) = @_;
106 $_ = $prefix . $_
107 unless (/^-/ || m{^\$\(\w+\)} || $_ eq "Makefile" || $_ eq '\\'
108 || $_ eq '@ALLOCA@');
109 return $_;
113 # prefix_words ($TEXT)
114 # --------------------
115 sub prefix_words ($)
117 local ($_) = @_;
118 s{(\S+)}{prefix_word($1)}gem;
119 return $_;
123 # prefix_assignment ($LHS-AND-ASSIGN-OP, $RHS)
124 # --------------------------------------------
125 sub prefix_assignment ($$)
127 my ($lhs_and_assign_op, $rhs) = @_;
129 # Some variables are initialized by gnulib.mk, and we don't want
130 # that. Change '=' to '+='.
131 if ($lhs_and_assign_op =~ /^(GPERF|V_GPERF.*) =$/)
133 # Do not change the RHS, which specifies the GPERF program.
135 # Don't change variables such as HAVE_INCLUDE_NEXT.
136 elsif ($lhs_and_assign_op =~ /^HAVE_/)
139 elsif ($lhs_and_assign_op =~
140 /^(SUBDIRS|EXTRA_DIST|BUILT_SOURCES|SUFFIXES|MOSTLYCLEANFILES
141 |CLEANFILES|DISTCLEANFILES|MAINTAINERCLEANFILES
142 |AM_GNU_GETTEXT)\ =/x)
144 $lhs_and_assign_op =~ s/=/+=/;
146 # We don't want things such as AM_CPPFLAGS +=
147 # -DDEFAULT_TEXT_DOMAIN=\"bison-gnulib\" to apply to the whole
148 # Makefile.in: scope it to the library: libbison_a_CPPFLAGS =
149 # $(AM_CPPFLAGS) -DDEFAULT_TEXT_DOMAIN=\"bison-gnulib\".
150 elsif ($lhs_and_assign_op =~
151 /^(AM_CFLAGS|AM_CPPFLAGS)\ \+?=/x)
153 $lhs_and_assign_op =~ s/^AM_(\w+)\ \+?=/${lib_name}_a_$1 =/;
154 $rhs = " \$(AM_$1)$rhs";
156 # We don't want to inherit gnulib's AUTOMAKE_OPTIONS, comment them.
157 elsif ($lhs_and_assign_op =~ /^AUTOMAKE_OPTIONS =/)
159 $lhs_and_assign_op =~ s/^/# /;
161 # Elide any SUFFIXES assignment or concatenation.
162 elsif ($lhs_and_assign_op =~ /^SUFFIXES /)
164 $lhs_and_assign_op =~ s/^/# /;
166 # The words are (probably) paths to files in lib/: prefix them.
167 else
169 $rhs = prefix_words($rhs)
172 # Variables whose name depend on the location: libbison_a_SOURCES =>
173 # lib_libbison_a_SOURCES.
174 $lhs_and_assign_op =~ s/($lib_name)/lib_$1/g;
176 $lhs_and_assign_op . $rhs;
179 # prefix $CONTENTS
180 # ----------------
181 # $CONTENTS is a Makefile content. Post-process it so that each file-name
182 # is prefixed with $prefix (e.g., "lib/").
184 # Relies heavily on the regularity of the file generated by gnulib-tool.
185 sub prefix ($)
187 # Work on $_.
188 local ($_) = @_;
190 # Prefix all the occurrence of files in rules. If there is nothing
191 # after in the :, it's probably a phony target, or a suffix rule.
192 # Don't touch it.
193 s{^([-\w+/]+\.[-\w.]+ *: *\S.*)$}
194 {prefix_words($1)}gem;
196 # Prefix files in variables.
197 s{^([\w.]+\s*\+?=)(.*)$}
198 {prefix_assignment($1, $2)}gem;
200 # $(srcdir)/ is actually $(top_srcdir)/$prefix/.
201 # The trailing slash is required to avoid matching this rule:
202 # test '$(srcdir)' = . || rm -f $(top_builddir)/GNUmakefile
203 s{\$\(srcdir\)/}{\$(top_srcdir)/$prefix}g;
205 # Sometimes, t-$@ is used instead of $@-t, which, of course, does
206 # not work when we have a $@ with a directory in it.
207 s{t-\$\@}{\$\@-t}g;
209 # Some AC_SUBST patterns remain and would better be Make macros.
210 s{\@(MKDIR_P)\@}{\$($1)}g;
212 # Adjust paths in mkdir.
213 s{(\$\(MKDIR_P\))\s*(\w+)}{$1 $prefix$2}g;
215 return $_;
218 # process ($IN)
219 # -------------
220 sub process ($)
222 my ($file) = @_;
223 my ($bak) = "$file.bak";
224 rename ($file, $bak) or die "$ME: rename $file $bak failed: $!\n";
225 my $contents = contents ($bak);
226 $contents = prefix ($contents);
227 my $out = new IO::File(">$file")
228 or die "$ME: $file: failed to open for writing: $!\n";
229 print $out $contents;
233 GetOptions
235 'lib-name=s' => \$lib_name,
236 help => sub { usage 0 },
237 version => sub { print "$ME version $VERSION\n"; exit },
238 ) or usage 1;
240 my $fail = 0;
241 defined $lib_name
242 or (warn "$ME: no library name; use --lib-name=NAME\n"), $fail = 1;
244 # There must be exactly one argument.
245 @ARGV == 0
246 and (warn "$ME: missing FILE argument\n"), $fail = 1;
247 1 < @ARGV
248 and (warn "$ME: too many arguments:\n", join ("\n", @ARGV), "\n"),
249 $fail = 1;
250 $fail
251 and usage 1;
253 my $file = $ARGV[0];
254 $prefix = (dirname $file) . '/';
255 warn "prefix=$prefix\n";
257 process $file;
260 ### Setup "GNU" style for perl-mode and cperl-mode.
261 ## Local Variables:
262 ## perl-indent-level: 2
263 ## perl-continued-statement-offset: 2
264 ## perl-continued-brace-offset: 0
265 ## perl-brace-offset: 0
266 ## perl-brace-imaginary-offset: 0
267 ## perl-label-offset: -2
268 ## cperl-indent-level: 2
269 ## cperl-brace-offset: 0
270 ## cperl-continued-brace-offset: 0
271 ## cperl-label-offset: -2
272 ## cperl-extra-newline-before-brace: t
273 ## cperl-merge-trailing-else: nil
274 ## cperl-continued-statement-offset: 2
275 ## eval: (add-hook 'before-save-hook 'time-stamp)
276 ## time-stamp-line-limit: 50
277 ## time-stamp-start: "my $VERSION = '"
278 ## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
279 ## time-stamp-time-zone: "UTC0"
280 ## time-stamp-end: "'; # UTC"
281 ## End: