comparison autopoop @ 0:d72d5d73b93a

Added Autopoop and mkchangelog.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 22 Apr 2008 14:31:44 +0300
parents
children 5665a846d227
comparison
equal deleted inserted replaced
-1:000000000000 0:d72d5d73b93a
1 #!/usr/bin/perl -w
2 # autopoop v0.57 (C) 2008 Matti 'ccr' Hamalainen
3 #
4 # Tries to generate extra.mk.in from known configure.ac and other
5 # autoconf m4-macros, scanning against Makefiles. Also checks for
6 # missing / unsubstituted symbols, etc.
7 #
8 # Requirements:
9 # - Recent enough GNU Autoconf (and requirements for that)
10 # - Perl 5
11 #
12 # TODO:
13 # - see fixmes
14 # - document this
15 # - find bugs
16 # - ???
17 # - profit
18 #
19 use strict;
20 use Cwd qw(getcwd realpath);
21
22 # List of subdirectories to check for additional Autoconf m4 macros
23 my @m4testdirs = ("m4", "unix");
24
25 # Misc. settings
26 my $makefile = "Makefile";
27 my $extrasys = "extra.mk";
28 my $buildsys = "buildsys.mk";
29 my $tmpfile = "autopoop.tmp";
30 my $autom4te = "autom4te";
31
32 # Things that may be set by user
33 my %bsdefines = (
34 "DESTDIR" => 1,
35 );
36
37 # Special substitutions
38 my %confdefines = (
39 # "VPATH" => "srcdir",
40 # "SET_MAKE" => "",
41 );
42
43
44 ### Function prototypes
45 sub shortpath($);
46 sub scanfile($$$$$$$$);
47
48
49 ### Argument handling
50 my $pcwd = getcwd();
51 my $argc = ($#ARGV + 1);
52 print "Autopoop v0.57 (C) 2008 Matti 'ccr' Hamalainen\n";
53 die("Usage: autopoop <configurefile> <outfile> [autom4te options]\n".
54 "Example: autopoop configure.ac extra.mk.in\n\n".
55 "NOTICE! Assumes following files are used:\n".
56 "$buildsys\[.in\], $extrasys, $makefile\n\n") unless ($argc >= 2);
57 my $configure = shift;
58 my $outfile = shift;
59
60
61 ### Execute Autoconf 'autom4te' ...
62 my @args = (@ARGV);
63 foreach my $dir (@m4testdirs) {
64 if (-d $dir) { push(@args, ("-I", $dir)); }
65 }
66
67 push(@args, (
68 "--force", "--no-cache", "--melt", "--language=autoconf",
69 "--trace=AC_SUBST", "-o", $tmpfile, $configure));
70
71 print "- Running $autom4te ".join(" ", @args)." ...\n";
72 system($autom4te, @args) == 0 or die("Failed to execute $autom4te: $?\n");
73
74
75 ### Paf files
76 $buildsys = realpath($buildsys);
77 $extrasys = realpath($extrasys);
78 $outfile = realpath($outfile);
79
80
81 ### Process results
82 open(INFILE,"<".$tmpfile) or die("Could not open '$tmpfile'!\n");
83 while (<INFILE>) {
84 chop;
85 my @entries = split(/:/);
86 my $key = $entries[3];
87 unless ($key =~ /_(FALSE|TRUE)$/) { $confdefines{$key} = $key; }
88 }
89 close INFILE;
90 unlink($tmpfile);
91
92
93 ### Scan Makefiles and depencies
94 my %makesubsts = ();
95 my %confsubsts = ();
96 my %makedefines = ();
97 my %scanned = ($outfile => 1, $extrasys => 1);
98 scanfile(".", $makefile, \%scanned, \%makesubsts, \%confsubsts, \%makedefines, 1, 1);
99 scanfile("", $buildsys, \%scanned, \%makesubsts, \%confsubsts, \%makedefines, 1, 0);
100
101
102 ### Scan buildsys.mk.in
103 my %bssubsts = ();
104 scanfile("", $buildsys.".in", \%scanned, \%bssubsts, \%bssubsts, \%bsdefines, 0, 0);
105
106
107 my %globdefs = ();
108 foreach my $file (keys %makedefines) {
109 foreach my $s (keys %{$makedefines{$file}}) {
110 $globdefs{$s} = 1;
111 }
112 }
113
114
115 ### Compare results
116 print "- Checking for used, but possibly undefined Make variables:\n";
117 foreach my $file (keys %makesubsts) {
118 foreach my $s (sort { $a cmp $b } keys %{$makesubsts{$file}}) {
119 if (!defined($confdefines{$s}) && !defined($makedefines{$file}{$s}) && !defined($bsdefines{$s})) {
120 my $err = 0;
121 if (!defined($globdefs{$s})) {
122 $err = 1;
123 } elsif ($file ne $buildsys && $file ne $outfile) {
124 $err = 2;
125 }
126 if ($err) {
127 printf " %-20s", "'$s'";
128 print " in ".shortpath($file).":".$makesubsts{$file}{$s}." ($err)\n";
129 }
130 }
131 }
132 }
133 print qq|Legend:
134 (1) = Not defined anywhere (or misdetected).
135 (2) = Defined 'somewhere', but unsure if symbol is propagated.
136
137 |;
138
139
140 print "- Checking for used, but possibly undefined substitutions:\n";
141 foreach my $file (keys %confsubsts) {
142 foreach my $s (keys %{$confsubsts{$file}}) {
143 if (!defined($confdefines{$s})) {
144 printf " %-20s", "'$s'";
145 print " in ".shortpath($file).":".$confsubsts{$file}{$s}."\n";
146 }
147 }
148 }
149 print "\n";
150
151
152 ### Output stuff
153 print "- Outputting '$outfile'\n";
154 open(OUTFILE, ">", $outfile) or die("Could not open '$outfile'!\n");
155 foreach my $s (keys %confdefines) {
156 if ($confdefines{$s} ne "") {
157 print OUTFILE "$s ?= \@".$confdefines{$s}."\@\n";
158 } else {
159 print OUTFILE "\@".$s."\@\n";
160 }
161 }
162 close OUTFILE;
163
164 print "- Done.\n";
165
166
167 ###
168 ### Functions
169 ###
170 sub shortpath($) {
171 if (index($_[0], $pcwd) == 0) {
172 return substr($_[0], length($pcwd) + 1);
173 } else {
174 return $_[0];
175 }
176 }
177
178 sub addhash($$$$$)
179 {
180 # if ($usenames) { $substs->{$filename}{$1} = $line; } else { $substs->{$1} = $line; }
181 if ($_[0]) {
182 $_[1]->{$_[2]}{$_[3]} = $_[4];
183 } else {
184 $_[1]->{$_[3]} = $_[4];
185 }
186 }
187
188 sub scanfile($$$$$$$$) {
189 my $mypath = $_[0];
190 my $myfile = $_[1];
191
192 my $scanned = $_[2];
193 my $substs = $_[3];
194 my $confsubsts = $_[4];
195 my $defines = $_[5];
196
197 my $usenames = $_[6];
198 my $recurse = $_[7];
199
200 # Form real path and check if we have already scanned the file
201 my $filename = realpath($mypath."/".$myfile);
202 if (defined($filename)) {
203 if (defined($scanned->{$filename})) {
204 $scanned->{$filename}++;
205 return;
206 }
207 $scanned->{$filename} = 1;
208 } else {
209 $filename = $mypath."/".$myfile;
210 }
211
212 #print "ASDF: $filename\n";
213
214 # Scan file, if found
215 if (open(my $SCANFILE, "<", $filename)) {
216 print "- Scanning ".shortpath($filename)." ...\n";
217 my $line = 0;
218 while (<$SCANFILE>) {
219 $line++;
220 chop;
221 if (/^#/) {
222 # ignore comment lines
223 } else {
224
225 while (/[^\$]\$\{([A-Za-z0-9_]+)\}/g) {
226 addhash($usenames, $substs, $filename, $1, $line);
227 }
228 while (/[^\$]\$\(([A-Za-z0-9_]+)\)/g) {
229 addhash($usenames, $substs, $filename, $1, $line);
230 }
231 while (/\@([A-Za-z0-9_]+)\@/g) {
232 addhash($usenames, $confsubsts, $filename, $1, $line);
233 }
234
235 if (/^ifdef\s+([A-Za-z0-9_]+)/g) {
236 addhash($usenames, $substs, $filename, $1, $line);
237 } elsif (/^([A-Za-z][A-Za-z0-9_]+)\s*[\+]?=/) {
238 addhash($usenames, $defines, $filename, $1, $line);
239 }
240 elsif (/^include (\S+)/) {
241 scanfile($mypath, "$1", $scanned, $substs, $confsubsts, $defines, $usenames, $recurse);
242 }
243 }
244 }
245 close $SCANFILE;
246 }
247
248 # Recurse into subdirectories
249 if ($recurse) {
250 opendir(DIR, $mypath) || return;
251 my @dirs = grep { /^[^\.]/ && -d "$mypath/$_" } readdir(DIR);
252 closedir(DIR);
253 foreach my $dir (@dirs) {
254 scanfile($mypath."/".$dir, $myfile, $scanned, $substs, $confsubsts, $defines, $usenames, $recurse);
255 }
256 }
257 }