From 525d25e1c7e98987353bf0a7a92e43a3fe52043d 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. --- Makefile.am | 10 ++- README | 5 ++ bootstrap | 4 ++ configure.ac | 3 +- fix-gnulib.pl | 154 +++++++++++++++++++++++++++++++++++++++++++++ m4/.gitignore | 1 + m4/gnulib-cache.m4 | 4 +- 7 files changed, 176 insertions(+), 5 deletions(-) create mode 100755 fix-gnulib.pl diff --git a/Makefile.am b/Makefile.am index 094c309..dcc43c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,11 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = lib . +# For Gnulib +BUILT_SOURCES = +MOSTLYCLEANFILES = +noinst_LTLIBRARIES = + AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src \ -I$(top_builddir)/lib -I$(top_srcdir)/lib \ -DBISON_LOCALEDIR=\"$(BISON_LOCALEDIR)\" \ @@ -36,7 +40,7 @@ libcdecl_la_LIBADD = $(LTLIBINTL) $(LTLIBTHREAD) bin_PROGRAMS = cdecl99 cdecl99_SOURCES = src/cdecl99.c -cdecl99_LDADD = libcdecl.la lib/libgnu.la +cdecl99_LDADD = libcdecl.la libgnu.la src/parse.lo: src/scan.h src/scan.lo: src/parse.h @@ -132,3 +136,5 @@ FLEX_V_0 = @echo " FLEX " $<; rm -f $<; \ $(MAKE) $(AM_MAKEFLAGS) $<; \ fi + +include $(top_srcdir)/lib/gnulib.mk diff --git a/README b/README index cdf8d05..7781aae 100644 --- a/README +++ b/README @@ -33,6 +33,11 @@ but older versions should not be expected to. * GNU Gettext version 0.18.1 * GNU Bison version 2.4.3 * flex version 2.5.35 + * perl version 5.12 + +Additionally, the following perl modules from CPAN are used: + + * List::Compare version 0.37 To generate the build system from Git, run the 'bootstrap' script in the top-level directory. This will automatically check out the full Gnulib diff --git a/bootstrap b/bootstrap index 94d0bc8..a9ad671 100755 --- a/bootstrap +++ b/bootstrap @@ -6,6 +6,7 @@ die() { printf '%s\n' "$@" 1>&2; kill -USR1 $$; } : ${AUTORECONF=autoreconf} : ${GNULIB=gnulib} : ${GIT=git} +: ${PERL=perl} $GIT submodule update --init \ || echo "Failed to update Gnulib sources from git." @@ -16,4 +17,7 @@ else die "Gnulib sources are not properly installed in gnulib/." fi +$PERL fix-gnulib.pl -o lib/gnulib.mk -i lib/gnulib.mk.in -m m4/fix-gnulib.m4 \ + || die "Failed to fixup Gnulib makefile fragment." + $AUTORECONF -fis diff --git a/configure.ac b/configure.ac index 103bae2..50eaf75 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,8 @@ gl_EARLY LT_INIT gl_INIT +DX_FIX_GNULIB + dnl We provide our own makefile rules for gettext. Disable tracing of dnl AM_GNU_GETTEXT to prevent autoreconf from running autopoint, and to dnl prevent automake from growing gratuitous error conditions. @@ -35,7 +37,6 @@ AC_CHECK_PROGS([BISON], [bison], [bison]) BISON_I18N AC_CONFIG_FILES([ - lib/Makefile Makefile ]) AC_OUTPUT diff --git a/fix-gnulib.pl b/fix-gnulib.pl new file mode 100755 index 0000000..6663e6e --- /dev/null +++ b/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; +} diff --git a/m4/.gitignore b/m4/.gitignore index c23c58b..14287ab 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -3,6 +3,7 @@ codeset.m4 errno_h.m4 extensions.m4 fcntl-o.m4 +fix-gnulib.m4 getdelim.m4 getline.m4 getopt.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 6acb89f..09fc0cd 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --conditional-dependencies --libtool --macro-prefix=gl --no-vc-files getopt-gnu gettext lock readline +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk.in --conditional-dependencies --libtool --macro-prefix=gl --no-vc-files getopt-gnu gettext lock readline # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -32,7 +32,7 @@ gl_PO_BASE([]) gl_DOC_BASE([doc]) gl_TESTS_BASE([tests]) gl_LIB([libgnu]) -gl_MAKEFILE_NAME([]) +gl_MAKEFILE_NAME([gnulib.mk.in]) gl_CONDITIONAL_DEPENDENCIES gl_LIBTOOL gl_MACRO_PREFIX([gl]) -- 2.43.2