]> git.draconx.ca Git - dxcommon.git/commitdiff
fix-ltdl: New script to fix up nonrecursive libltdl.
authorNick Bowler <nbowler@draconx.ca>
Thu, 10 May 2012 22:11:33 +0000 (18:11 -0400)
committerNick Bowler <nbowler@draconx.ca>
Thu, 10 May 2012 22:11:33 +0000 (18:11 -0400)
Similar in spirit to fix-gnulib, this one improves the nonrecursive
libltdl integration.

scripts/fix-ltdl.pl [new file with mode: 0755]

diff --git a/scripts/fix-ltdl.pl b/scripts/fix-ltdl.pl
new file mode 100755 (executable)
index 0000000..8065545
--- /dev/null
@@ -0,0 +1,161 @@
+#!/usr/bin/env perl
+#
+# Copyright © 2012 Nick Bowler
+#
+# Fixup a non-recursive libltdl makefile fragment.  While libltdl purports to
+# support inclusion into non-recursive automake builds, it does a few things
+# that are less than ideal.  The most dire problem is that it modifies
+# AM_CPPFLAGS and AM_LDFLAGS in a manner that can negatively affect the
+# rest of the project.
+#
+# This script postprocesses Makefile.inc in the libltdl directory and attempts
+# to fix these integration problems.  The output can then included normally
+# into Makefile.am.
+#
+# Most of the specific transformations are documented below.
+#
+# 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 Getopt::Long;
+
+my $output   = undef;
+my $input    = undef;
+
+my $line     = 0;
+
+Getopt::Long::Configure("gnu_getopt", "no_auto_abbrev");
+GetOptions(
+       "o|output=s"   => \$output,
+       "i|input=s"    => \$input,
+);
+
+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 ($ltdl_dir, $am_dir_prefix);
+my (%libtargets, %libtargetflags);
+my @libobjfiles;
+
+sub drop {
+       undef $_;
+       next;
+}
+
+sub basename {
+       my $file = shift;
+       $file =~ m|(?:.+/)?([^/]+)/?|;
+       return $1;
+}
+
+sub handle_libobj {
+       my $distfile = shift;
+       my $base;
+
+       return 1 if (!($distfile =~ /(.*)\.c/));
+       $base = basename($1);
+
+       die if (!defined $am_dir_prefix);
+       print <<EOF;
+${am_dir_prefix}libobj_la_SOURCES += $distfile
+$ltdl_dir/$base.lo: $ltdl_dir/${am_dir_prefix}libobj_la-$base.lo
+\t\$(AM_V_at)(cd \$(\@D) && \$(LN_S) ${am_dir_prefix}libobj_la-\$(\@F) \$(\@F))
+EOF
+
+       return 0;
+}
+
+sub fixup_libobjs {
+       my $raw = shift;
+
+       $raw =~ /([^=]+=)[[:space:]]*(.*)/s;
+       my ($left, @right) = ($1, split(/[[:space:]]+/, $2));
+
+       @right = grep(handle_libobj($_), @right);
+       return "" if (!@right);
+       return join(" ", ($left, @right)) . "\n";
+}
+
+while (<STDIN>) {
+       $line++;
+
+       # Combine line splices.
+       while (s/\\$//) {
+               $line++;
+               $_ = $_ . <STDIN>
+       }
+
+       # I cannot resist...
+       drop if (/DO NOT REMOVE THIS LINE/);
+
+       next if (/^#/);
+
+       if (!$printed_header) {
+               print "# Postprocessed by ", basename($0), "\n";
+               print <<'EOF';
+# This trick should define ltdl_orderonly to | iff we're using GNU make.
+ltdl_have_orderonly = $(findstring order-only,$(.FEATURES))
+ltdl_orderonly = $(ltdl_have_orderonly:order-only=|)
+ltdl_core_headers =
+ltdl_src_headers = $(ltdl_orderonly) $(ltdl_core_headers)
+EOF
+               $printed_header = 1;
+       }
+
+       # Don't pollute the global AM_CPPFLAGS/AM_LDFLAGS environment with
+       # stuff totally specific to libltdl.
+       s/^AM_((?:CPPFLAGS|LDFLAGS)[[:space:]]*)\+=/LTDL_\1 =/;
+
+       # Augment references to AM_xFLAGS with the corresponding LTDL_xFLAGS.
+       s/\$\(AM_(CPPFLAGS|LDFLAGS)\)/$& \$(LTDL_\1)/;
+
+       # Since some of the targets rely on the automatic use of AM_xFLAGS,
+       # we need to track which libraries do not have explicit xFLAGS
+       # settings, and add references to LTDL_xFLAGS as appropriate.
+       if (/^((lib[[:alpha:]_]+_la_)[[:upper:]]+)/) {
+               $libtargetflags{$1} = 1;
+               $libtargets{$2} = 1;
+       }
+
+       # The use of LIBOBJ makes passing required CPPFLAGS tricky.  We will
+       # handle this specially by defining a fake convenience library.
+       if (/^([[:alnum:]_]+)libltdl_la_SOURCES[[:space:]]*=/) {
+               $am_dir_prefix=$1;
+               m|\b([^[:space:]]*)/ltdl\.c\b|s;
+               $ltdl_dir = $1;
+               print <<EOF;
+EXTRA_LTLIBRARIES += $ltdl_dir/libobj.la
+\$(${am_dir_prefix}libobj_la_OBJECTS): \$(ltdl_src_headers)
+${am_dir_prefix}libobj_la_SOURCES =
+${am_dir_prefix}libobj_la_CPPFLAGS = \$(AM_CPPFLAGS) \$(LTDL_CPPFLAGS)
+${am_dir_prefix}libobj_la_LINK = false
+EOF
+       }
+
+       # Handle the relevant LIBOBJ source files, which appear in EXTRA_DIST.
+       if (/^EXTRA_DIST[[:space:]]*\+=/) {
+               $_ = fixup_libobjs($_);
+       }
+
+       # BUILT_SOURCES has similar problems to recursive make: inadequate
+       # dependencies lead to incorrect builds.  Collect them into an
+       # ordinary variable so we can deal with them later.
+       s/BUILT_SOURCES/ltdl_core_headers/;
+
+       # Add explicit dependencies on generated header files to each library.
+       if (/^([[:alnum:]_]+)_SOURCES[[:space:]]*=/) {
+               print "\$($1_OBJECTS): \$(ltdl_src_headers)\n";
+       }
+} continue { s/(\n.)/\\\1/g; print; };
+
+print "\n# Automatic default flags for libraries\n";
+foreach my $lib (keys %libtargets) {
+       foreach my $flag ("CPPFLAGS", "LDFLAGS") {
+               if (!$libtargetflags{"$lib$flag"}) {
+                       print "$lib$flag = \$(AM_$flag) \$(LTDL_$flag)\n";
+               }
+       }
+}