From 27fd2e6316f403905a9a946a9a6b9ea9bab843ed Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Sun, 18 Sep 2011 21:46:14 -0400 Subject: [PATCH] Integrate Gnulib non-recursively. With a little bit of mangling, it's possible to make the makefile fragment produced by gnulib-tool suitable for use in our non-recursive makefile. --- scripts/fix-gnulib.pl | 154 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100755 scripts/fix-gnulib.pl diff --git a/scripts/fix-gnulib.pl b/scripts/fix-gnulib.pl new file mode 100755 index 0000000..6663e6e --- /dev/null +++ b/scripts/fix-gnulib.pl @@ -0,0 +1,154 @@ +#!/usr/bin/env perl +# +# Copyright © 2011 Nick Bowler +# +# Prepare the Gnulib tree for inclusion into a non-recursive automake build. +# +# License WTFPL2: Do What The Fuck You Want To Public License, version 2. +# This is free software: you are free to do what the fuck you want to. +# There is NO WARRANTY, to the extent permitted by law. + +use strict; +use List::Compare; +use Getopt::Long; + +my $output = undef; +my $input = undef; +my $m4output = undef; +my $m4macro = "DX_FIX_GNULIB"; + +Getopt::Long::Configure("gnu_getopt", "no_auto_abbrev"); +GetOptions( + "o|output=s" => \$output, + "i|input=s" => \$input, + "m|m4output=s" => \$m4output, + "M|m4macro=s" => \$m4macro, +); + +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 (%allvars, %sourcevars); + +sub drop { + undef $_; + next; +} + +sub basename { + my $file = shift; + $file =~ m|(?:.+/)?([^/]+)/?|; + return $1; +} + +sub mangle_file { + my $word = shift; + + if ($word =~ /^\$\(([[:word:].]+)\)$/) { + # Don't touch variables now, but record them for later. + $sourcevars{$1} = 1; + } elsif ($word =~ /^\$\((?:top_)?(?:srcdir|builddir)\)/) { + # Do nothing. Generic transformation will take care of + # $(srcdir) and $(builddir). + } elsif ($word =~ /^[[:word:].+\/-]+$/) { + # Fix up things that look like filenames. + $word = "lib/$word"; + } else { + print STDERR "$0: warning: unrecognized source file: $word\n"; + } + + return "$word"; +} + +sub mangle_variable { + my $raw = shift; + + $raw =~ /([^=]+=)[[:space:]]*(.*)/; + my ($left, @right) = ($1, split(/[[:space:]]+/, $2)); + + return join(" ", ($left, map(mangle_file($_), @right))) . "\n"; +} + +sub mangle_target { + my $raw = shift; + + $raw =~ /([^:]+):[[:space:]]*(.*)/; + my @left = split(/[[:space:]]+/, $1); + my @right = split(/[[:space:]]+/, $2); + + @left = map(mangle_file($_), @left); + @right = map(mangle_file($_), @right); + + return join(" ", @left) . ": " . join(" ", @right) . "\n"; +} + +while () { + next if (/^#/); + + if (!$printed_header) { + print "# Postprocessed by ", basename($0), "\n"; + $printed_header = 1; + drop; + } + + # For some reason, gnulib-tool adds core dumps to "make mostlyclean". + # Since these files are (hopefully!) not created by make, they should + # not be cleaned. + drop if (/^MOSTLYCLEANFILES.*core/); + + # Some modules set AM_CPPFLAGS/AM_CFLAGS/etc. in a manner that is not + # useful for non-recursive builds. Strip them out. + drop if (/^(AM_CPPFLAGS|AM_CFLAGS)/); + + # Rewrite automake hook targets to be more generic. + if (s/^(.*)-local:/\1-gnulib:/) { + print ".PHONY: $1-gnulib\n"; + print "$1-local: $1-gnulib\n"; + s/$1-generic//; + + # Don't let these targets get confused with filenames below. + next; + } + + # We need to mangle filenames in make variables; prepending a lib/ on + # relative paths. The following should catch all variable assignments + # that need mangling. + if (/^([[:word:]]+)[[:space:]]*\+?=/) { + $allvars{$1} = 1; + + if (/_SOURCES|CLEANFILES|EXTRA_DIST|[[:upper:]]+_H/) { + $_ = mangle_variable($_); + } + } + + # Targets are similar to variables: the target and its dependencies + # need to be mangled. + if (/:/) { + $_ = mangle_target($_); + } + + # Finally, references to $(srcdir) and $(builddir) need to be fixed up. + s:\$\(srcdir\):\$\(top_srcdir\)/lib:g; + s:\$\(builddir\):\$\(top_builddir\)/lib:g; +} continue { print }; + +# Some filenames are AC_SUBSTed by the Gnulib macros, and thus we need to +# prepend lib/ if and only if they're not empty. Unfortunately, make is not +# powerful to do this, so we need to put this transformation into configure +# itself by defining a new autoconf macro. +if (defined $m4output) { + my $lc = List::Compare->new('-u', '-a', \%sourcevars, \%allvars); + my @vars = $lc->get_unique; + + open(M4OUT, '>', $m4output) or die "$m4output: $!\n"; + + print M4OUT "dnl This file was generated by fix-gnulib.pl\n"; + print M4OUT "AC_DEFUN([$m4macro], [dnl\n"; + foreach (@vars) { + print M4OUT "$_=\${$_:+lib/\$$_}\n"; + } + print M4OUT "])\n"; + + close M4OUT; +} -- 2.43.2