]> git.draconx.ca Git - dxcommon.git/blob - scripts/fix-ltdl.pl
fix-ltdl: Delete libobj symlink before attempting to create it.
[dxcommon.git] / scripts / fix-ltdl.pl
1 #!/usr/bin/env perl
2 #
3 # Copyright © 2012 Nick Bowler
4 #
5 # Fixup a non-recursive libltdl makefile fragment.  While libltdl purports to
6 # support inclusion into non-recursive automake builds, it does a few things
7 # that are less than ideal.  The most dire problem is that it modifies
8 # AM_CPPFLAGS and AM_LDFLAGS in a manner that can negatively affect the
9 # rest of the project.
10 #
11 # This script postprocesses Makefile.inc in the libltdl directory and attempts
12 # to fix these integration problems.  The output can then included normally
13 # into Makefile.am.
14 #
15 # Most of the specific transformations are documented below.
16 #
17 # License WTFPL2: Do What The Fuck You Want To Public License, version 2.
18 # This is free software: you are free to do what the fuck you want to.
19 # There is NO WARRANTY, to the extent permitted by law.
20
21 use strict;
22 use Getopt::Long;
23
24 my $output   = undef;
25 my $input    = undef;
26
27 my $line     = 0;
28
29 Getopt::Long::Configure("gnu_getopt", "no_auto_abbrev");
30 GetOptions(
31         "o|output=s"   => \$output,
32         "i|input=s"    => \$input,
33 );
34
35 open STDOUT, ">", $output or die "$output: $!\n" if (defined $output);
36 open STDIN,  "<", $input  or die "$input: $!\n"  if (defined $input);
37
38 my $printed_header = 0;
39 my ($ltdl_dir, $am_dir_prefix);
40 my (%libtargets, %libtargetflags);
41 my @libobjfiles;
42
43 sub drop {
44         undef $_;
45         next;
46 }
47
48 sub basename {
49         my $file = shift;
50         $file =~ m|(?:.+/)?([^/]+)/?|;
51         return $1;
52 }
53
54 sub handle_libobj {
55         my $distfile = shift;
56         my $base;
57
58         return 1 if (!($distfile =~ /(.*)\.c/));
59         $base = basename($1);
60
61         die if (!defined $am_dir_prefix);
62         print <<EOF;
63 ${am_dir_prefix}libobj_la_SOURCES += $distfile
64 $ltdl_dir/$base.lo: $ltdl_dir/${am_dir_prefix}libobj_la-$base.lo
65 \t\$(AM_V_at)-rm -f \$@
66 \t\$(AM_V_at)(cd \$(\@D) && \$(LN_S) ${am_dir_prefix}libobj_la-\$(\@F) \$(\@F))
67 EOF
68
69         return 0;
70 }
71
72 sub fixup_libobjs {
73         my $raw = shift;
74
75         $raw =~ /([^=]+=)[[:space:]]*(.*)/s;
76         my ($left, @right) = ($1, split(/[[:space:]]+/, $2));
77
78         @right = grep(handle_libobj($_), @right);
79         return "" if (!@right);
80         return join(" ", ($left, @right)) . "\n";
81 }
82
83 while (<STDIN>) {
84         $line++;
85
86         # Combine line splices.
87         while (s/\\$//) {
88                 $line++;
89                 $_ = $_ . <STDIN>
90         }
91
92         # I cannot resist...
93         drop if (/DO NOT REMOVE THIS LINE/);
94
95         next if (/^#/);
96
97         if (!$printed_header) {
98                 print "# Postprocessed by ", basename($0), "\n";
99                 print <<'EOF';
100 # This trick should define ltdl_orderonly to | iff we're using GNU make.
101 ltdl_have_orderonly = $(findstring order-only,$(.FEATURES))
102 ltdl_orderonly = $(ltdl_have_orderonly:order-only=|)
103 ltdl_core_headers =
104 ltdl_src_headers = $(ltdl_orderonly) $(ltdl_core_headers)
105 EOF
106                 $printed_header = 1;
107         }
108
109         # Don't pollute the global AM_CPPFLAGS/AM_LDFLAGS environment with
110         # stuff totally specific to libltdl.
111         s/^AM_((?:CPPFLAGS|LDFLAGS)[[:space:]]*)\+=/LTDL_\1 =/;
112
113         # Augment references to AM_xFLAGS with the corresponding LTDL_xFLAGS.
114         s/\$\(AM_(CPPFLAGS|LDFLAGS)\)/$& \$(LTDL_\1)/;
115
116         # Since some of the targets rely on the automatic use of AM_xFLAGS,
117         # we need to track which libraries do not have explicit xFLAGS
118         # settings, and add references to LTDL_xFLAGS as appropriate.
119         if (/^((lib[[:alpha:]_]+_la_)[[:upper:]]+)/) {
120                 $libtargetflags{$1} = 1;
121                 $libtargets{$2} = 1;
122         }
123
124         # The use of LIBOBJ makes passing required CPPFLAGS tricky.  We will
125         # handle this specially by defining a fake convenience library.
126         if (/^([[:alnum:]_]+)libltdl_la_SOURCES[[:space:]]*=/) {
127                 $am_dir_prefix=$1;
128                 m|\b([^[:space:]]*)/ltdl\.c\b|s;
129                 $ltdl_dir = $1;
130                 print <<EOF;
131 EXTRA_LTLIBRARIES += $ltdl_dir/libobj.la
132 \$(${am_dir_prefix}libobj_la_OBJECTS): \$(ltdl_src_headers)
133 ${am_dir_prefix}libobj_la_SOURCES =
134 ${am_dir_prefix}libobj_la_CPPFLAGS = \$(AM_CPPFLAGS) \$(LTDL_CPPFLAGS)
135 ${am_dir_prefix}libobj_la_LINK = false
136 EOF
137         }
138
139         # Handle the relevant LIBOBJ source files, which appear in EXTRA_DIST.
140         if (/^EXTRA_DIST[[:space:]]*\+=/) {
141                 $_ = fixup_libobjs($_);
142         }
143
144         # BUILT_SOURCES has similar problems to recursive make: inadequate
145         # dependencies lead to incorrect builds.  Collect them into an
146         # ordinary variable so we can deal with them later.
147         s/BUILT_SOURCES/ltdl_core_headers/;
148
149         # Add explicit dependencies on generated header files to each library.
150         if (/^([[:alnum:]_]+)_SOURCES[[:space:]]*=/) {
151                 print "\$($1_OBJECTS): \$(ltdl_src_headers)\n";
152         }
153 } continue { s/(\n.)/\\\1/g; print; };
154
155 print "\n# Automatic default flags for libraries\n";
156 foreach my $lib (keys %libtargets) {
157         foreach my $flag ("CPPFLAGS", "LDFLAGS") {
158                 if (!$libtargetflags{"$lib$flag"}) {
159                         print "$lib$flag = \$(AM_$flag) \$(LTDL_$flag)\n";
160                 }
161         }
162 }