Mercurial > hg > buildtools
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 } |