diff options
Diffstat (limited to 'build-aux/prefix-gnulib-mk')
-rwxr-xr-x | build-aux/prefix-gnulib-mk | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/build-aux/prefix-gnulib-mk b/build-aux/prefix-gnulib-mk new file mode 100755 index 0000000..674615a --- /dev/null +++ b/build-aux/prefix-gnulib-mk @@ -0,0 +1,281 @@ +#!/bin/sh +#! -*-perl-*- + +# Rewrite a gnulib.mk, adding prefixes to work with automake's subdir-objects. + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# Written by Jim Meyering + +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is essential for perl and is +# also useful for editing this file in Emacs. The next two lines below +# are valid code in both sh and perl. When executed by sh, they re-execute +# the script through the perl program found in $PATH. The '-x' option +# is essential as well; without it, perl would re-execute the script +# through /bin/sh. When executed by perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; + +my $VERSION = '2012-01-21 17:13'; # UTC +# The definition above must lie within the first 8 lines in order +# for the Emacs time-stamp write hook (at end) to update it. +# If you change this file with Emacs, please let the write hook +# do its job. Otherwise, update this string manually. + +use strict; +use IO::File; +use Getopt::Long; +use File::Basename; # for dirname + +(my $ME = $0) =~ s|.*/||; + +my $prefix; +my $lib_name; + +sub usage ($) +{ + my ($exit_code) = @_; + my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR); + if ($exit_code != 0) + { + print $STREAM "Try '$ME --help' for more information.\n"; + } + else + { + print $STREAM <<EOF; +Usage: $ME --lib-name=NAME FILE + or: $ME [--help|--version] +Rewrite a gnulib-tool-generated FILE like lib/gnulib.mk to work with +automake's subdir-objects. + +OPTIONS: + +This option must be specified: + + --lib-name=NAME library name, often "lib\$project" + +The following are optional: + + --help display this help and exit + --version output version information and exit + +EOF + } + exit $exit_code; +} + +# contents ($FILE_NAME) +# --------------------- +sub contents ($) +{ + my ($file) = @_; + local $/; # Turn on slurp-mode. + my $f = new IO::File "< $file" or die "$file"; + my $contents = $f->getline or die "$file"; + $f->close; + return $contents; +} + +# prefix_word ($WORD) +# ------------------- +# Do not prefix special words such as variable dereferences. Also, +# "Makefile" is really "Makefile", since precisely there is no +# lib/Makefile. +sub prefix_word ($) +{ + local ($_) = @_; + $_ = $prefix . $_ + unless (/^-/ || m{^\$\(\w+\)} || $_ eq "Makefile" || $_ eq '\\' + || $_ eq '@ALLOCA@'); + return $_; +} + + +# prefix_words ($TEXT) +# -------------------- +sub prefix_words ($) +{ + local ($_) = @_; + s{(\S+)}{prefix_word($1)}gem; + return $_; +} + + +# prefix_assignment ($LHS-AND-ASSIGN-OP, $RHS) +# -------------------------------------------- +sub prefix_assignment ($$) +{ + my ($lhs_and_assign_op, $rhs) = @_; + + # Some variables are initialized by gnulib.mk, and we don't want + # that. Change '=' to '+='. + if ($lhs_and_assign_op =~ /^(GPERF|V_GPERF.*) =$/) + { + # Do not change the RHS, which specifies the GPERF program. + } + # Don't change variables such as HAVE_INCLUDE_NEXT. + elsif ($lhs_and_assign_op =~ /^HAVE_/) + { + } + elsif ($lhs_and_assign_op =~ + /^(SUBDIRS|EXTRA_DIST|BUILT_SOURCES|SUFFIXES|MOSTLYCLEANFILES + |CLEANFILES|DISTCLEANFILES|MAINTAINERCLEANFILES + |AM_GNU_GETTEXT)\ =/x) + { + $lhs_and_assign_op =~ s/=/+=/; + } + # We don't want things such as AM_CPPFLAGS += + # -DDEFAULT_TEXT_DOMAIN=\"bison-gnulib\" to apply to the whole + # Makefile.in: scope it to the library: libbison_a_CPPFLAGS = + # $(AM_CPPFLAGS) -DDEFAULT_TEXT_DOMAIN=\"bison-gnulib\". + elsif ($lhs_and_assign_op =~ + /^(AM_CFLAGS|AM_CPPFLAGS)\ \+?=/x) + { + $lhs_and_assign_op =~ s/^AM_(\w+)\ \+?=/${lib_name}_a_$1 =/; + $rhs = " \$(AM_$1)$rhs"; + } + # We don't want to inherit gnulib's AUTOMAKE_OPTIONS, comment them. + elsif ($lhs_and_assign_op =~ /^AUTOMAKE_OPTIONS =/) + { + $lhs_and_assign_op =~ s/^/# /; + } + # Elide any SUFFIXES assignment or concatenation. + elsif ($lhs_and_assign_op =~ /^SUFFIXES /) + { + $lhs_and_assign_op =~ s/^/# /; + } + # The words are (probably) paths to files in lib/: prefix them. + else + { + $rhs = prefix_words($rhs) + } + + # Variables whose name depend on the location: libbison_a_SOURCES => + # lib_libbison_a_SOURCES. + $lhs_and_assign_op =~ s/($lib_name)/lib_$1/g; + + $lhs_and_assign_op . $rhs; +} + +# prefix $CONTENTS +# ---------------- +# $CONTENTS is a Makefile content. Post-process it so that each file-name +# is prefixed with $prefix (e.g., "lib/"). +# +# Relies heavily on the regularity of the file generated by gnulib-tool. +sub prefix ($) +{ + # Work on $_. + local ($_) = @_; + + # Prefix all the occurrence of files in rules. If there is nothing + # after in the :, it's probably a phony target, or a suffix rule. + # Don't touch it. + s{^([-\w+/]+\.[-\w.]+ *: *\S.*)$} + {prefix_words($1)}gem; + + # Prefix files in variables. + s{^([\w.]+\s*\+?=)(.*)$} + {prefix_assignment($1, $2)}gem; + + # $(srcdir)/ is actually $(top_srcdir)/$prefix/. + # The trailing slash is required to avoid matching this rule: + # test '$(srcdir)' = . || rm -f $(top_builddir)/GNUmakefile + s{\$\(srcdir\)/}{\$(top_srcdir)/$prefix}g; + + # Sometimes, t-$@ is used instead of $@-t, which, of course, does + # not work when we have a $@ with a directory in it. + s{t-\$\@}{\$\@-t}g; + + # Some AC_SUBST patterns remain and would better be Make macros. + s{\@(MKDIR_P)\@}{\$($1)}g; + + # Adjust paths in mkdir. + s{(\$\(MKDIR_P\))\s*(\w+)}{$1 $prefix$2}g; + + return $_; +} + +# process ($IN) +# ------------- +sub process ($) +{ + my ($file) = @_; + my ($bak) = "$file.bak"; + rename ($file, $bak) or die "$ME: rename $file $bak failed: $!\n"; + my $contents = contents ($bak); + $contents = prefix ($contents); + my $out = new IO::File(">$file") + or die "$ME: $file: failed to open for writing: $!\n"; + print $out $contents; +} + +{ + GetOptions + ( + 'lib-name=s' => \$lib_name, + help => sub { usage 0 }, + version => sub { print "$ME version $VERSION\n"; exit }, + ) or usage 1; + + my $fail = 0; + defined $lib_name + or (warn "$ME: no library name; use --lib-name=NAME\n"), $fail = 1; + + # There must be exactly one argument. + @ARGV == 0 + and (warn "$ME: missing FILE argument\n"), $fail = 1; + 1 < @ARGV + and (warn "$ME: too many arguments:\n", join ("\n", @ARGV), "\n"), + $fail = 1; + $fail + and usage 1; + + my $file = $ARGV[0]; + $prefix = (dirname $file) . '/'; + warn "prefix=$prefix\n"; + + process $file; +} + +### Setup "GNU" style for perl-mode and cperl-mode. +## Local Variables: +## perl-indent-level: 2 +## perl-continued-statement-offset: 2 +## perl-continued-brace-offset: 0 +## perl-brace-offset: 0 +## perl-brace-imaginary-offset: 0 +## perl-label-offset: -2 +## cperl-indent-level: 2 +## cperl-brace-offset: 0 +## cperl-continued-brace-offset: 0 +## cperl-label-offset: -2 +## cperl-extra-newline-before-brace: t +## cperl-merge-trailing-else: nil +## cperl-continued-statement-offset: 2 +## eval: (add-hook 'before-save-hook 'time-stamp) +## time-stamp-line-limit: 50 +## time-stamp-start: "my $VERSION = '" +## time-stamp-format: "%:y-%02m-%02d %02H:%02M" +## time-stamp-time-zone: "UTC0" +## time-stamp-end: "'; # UTC" +## End: |