10554
|
1 #!/usr/bin/perl
|
|
2 ## --------------------------------------------------------------------------
|
|
3 ##
|
|
4 ## Copyright 1996-2016 The NASM Authors - All Rights Reserved
|
|
5 ## See the file AUTHORS included with the NASM distribution for
|
|
6 ## the specific copyright holders.
|
|
7 ##
|
|
8 ## Redistribution and use in source and binary forms, with or without
|
|
9 ## modification, are permitted provided that the following
|
|
10 ## conditions are met:
|
|
11 ##
|
|
12 ## * Redistributions of source code must retain the above copyright
|
|
13 ## notice, this list of conditions and the following disclaimer.
|
|
14 ## * Redistributions in binary form must reproduce the above
|
|
15 ## copyright notice, this list of conditions and the following
|
|
16 ## disclaimer in the documentation and/or other materials provided
|
|
17 ## with the distribution.
|
|
18 ##
|
|
19 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
20 ## CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
21 ## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
22 ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23 ## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
24 ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
25 ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
26 ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
27 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
28 ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
29 ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
30 ## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
31 ## EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32 ##
|
|
33 ## --------------------------------------------------------------------------
|
|
34
|
|
35 #
|
|
36 # Script to create Makefile-style dependencies.
|
|
37 #
|
|
38 # Usage: perl mkdep.pl [-s path-separator] [-o obj-ext] dir... > deps
|
|
39 #
|
|
40
|
|
41 use File::Spec;
|
|
42 use File::Basename;
|
|
43 use Fcntl;
|
|
44
|
|
45 $barrier = "#-- Everything below is generated by mkdep.pl - do not edit --#\n";
|
|
46
|
|
47 # This converts from filenames to full pathnames for our dependencies
|
|
48 %dep_path = {};
|
|
49
|
|
50 #
|
|
51 # Scan files for dependencies
|
|
52 #
|
|
53 sub scandeps($) {
|
|
54 my($file) = @_;
|
|
55 my $line;
|
|
56 my @xdeps = ();
|
|
57 my @mdeps = ();
|
|
58
|
|
59 open(my $fh, '<', $file)
|
|
60 or return; # If not openable, assume generated
|
|
61
|
|
62 while ( defined($line = <$fh>) ) {
|
|
63 chomp $line;
|
|
64 $line =~ s:/\*.*\*/::g;
|
|
65 $line =~ s://.*$::;
|
|
66 if ( $line =~ /^\s*\#\s*include\s+\"(.*)\"\s*$/ ) {
|
|
67 my $nf = $1;
|
|
68 if (!defined($dep_path{$nf})) {
|
|
69 die "$0: cannot determine path for dependency: $file -> $nf\n";
|
|
70 }
|
|
71 $nf = $dep_path{$nf};
|
|
72 push(@mdeps, $nf);
|
|
73 push(@xdeps, $nf) unless ( defined($deps{$nf}) );
|
|
74 }
|
|
75 }
|
|
76 close($fh);
|
|
77 $deps{$file} = [@mdeps];
|
|
78
|
|
79 foreach my $xf ( @xdeps ) {
|
|
80 scandeps($xf);
|
|
81 }
|
|
82 }
|
|
83
|
|
84 # %deps contains direct dependencies. This subroutine resolves
|
|
85 # indirect dependencies that result.
|
|
86 sub alldeps($$) {
|
|
87 my($file, $level) = @_;
|
|
88 my %adeps;
|
|
89
|
|
90 foreach my $dep ( @{$deps{$file}} ) {
|
|
91 $adeps{$dep} = 1;
|
|
92 foreach my $idep ( alldeps($dep, $level+1) ) {
|
|
93 $adeps{$idep} = 1;
|
|
94 }
|
|
95 }
|
|
96 return sort(keys(%adeps));
|
|
97 }
|
|
98
|
|
99 # This converts a filename from host syntax to target syntax
|
|
100 # This almost certainly works only on relative filenames...
|
|
101 sub convert_file($$) {
|
|
102 my($file,$sep) = @_;
|
|
103 my @fspec = (basename($file));
|
|
104 while ( ($file = dirname($file)) ne File::Spec->curdir() &&
|
|
105 $file ne File::Spec->rootdir() ) {
|
|
106 unshift(@fspec, basename($file));
|
|
107 }
|
|
108
|
|
109 if ( $sep eq '' ) {
|
|
110 # This means kill path completely. Used with Makes who do
|
|
111 # path searches, but doesn't handle output files in subdirectories,
|
|
112 # like OpenWatcom WMAKE.
|
|
113 return $fspec[scalar(@fspec)-1];
|
|
114 } else {
|
|
115 return join($sep, @fspec);
|
|
116 }
|
|
117 }
|
|
118
|
|
119 #
|
|
120 # Insert dependencies into a Makefile
|
|
121 #
|
|
122 sub insert_deps($) {
|
|
123 my($file) = @_;
|
|
124 $nexttemp++; # Unique serial number for each temp file
|
|
125 my $tmp = File::Spec->catfile(dirname($file), 'tmp.'.$nexttemp);
|
|
126
|
|
127 open(my $in, '<', $file)
|
|
128 or die "$0: Cannot open input: $file\n";
|
|
129 open(my $out, '>', $tmp)
|
|
130 or die "$0: Cannot open output: $tmp\n";
|
|
131
|
|
132 my($line,$parm,$val);
|
|
133 my($obj) = '.o'; # Defaults
|
|
134 my($sep) = '/';
|
|
135 my($cont) = "\\";
|
|
136 my($maxline) = 78; # Seems like a reasonable default
|
|
137 my @exclude = (); # Don't exclude anything
|
|
138 my @genhdrs = ();
|
|
139
|
|
140 while ( defined($line = <$in>) ) {
|
|
141 if ( $line =~ /^([^\s\#\$\:]+\.h):/ ) {
|
|
142 # Note: we trust the first Makefile given best
|
|
143 my $fpath = $1;
|
|
144 my $fbase = basename($fpath);
|
|
145 if (!defined($dep_path{$fbase})) {
|
|
146 $dep_path{$fbase} = $fpath;
|
|
147 print STDERR "Makefile: $fbase -> $fpath\n";
|
|
148 }
|
|
149 } elsif ( $line =~ /^\s*\#\s*@([a-z0-9-]+):\s*\"([^\"]*)\"/ ) {
|
|
150 $parm = $1; $val = $2;
|
|
151 if ( $parm eq 'object-ending' ) {
|
|
152 $obj = $val;
|
|
153 } elsif ( $parm eq 'path-separator' ) {
|
|
154 $sep = $val;
|
|
155 } elsif ( $parm eq 'line-width' ) {
|
|
156 $maxline = $val+0;
|
|
157 } elsif ( $parm eq 'continuation' ) {
|
|
158 $cont = $val;
|
|
159 } elsif ( $parm eq 'exclude' ) {
|
|
160 @exclude = split(/\,/, $val);
|
|
161 }
|
|
162 } elsif ( $line eq $barrier ) {
|
|
163 last; # Stop reading input at barrier line
|
|
164 }
|
|
165 print $out $line;
|
|
166 }
|
|
167 close($in);
|
|
168
|
|
169 my $e;
|
|
170 my %do_exclude = ();
|
|
171 foreach $e (@exclude) {
|
|
172 $do_exclude{$e} = 1;
|
|
173 }
|
|
174
|
|
175 my $dfile, $ofile, $str, $sl, $len;
|
|
176 my @deps, $dep;
|
|
177
|
|
178 print $out $barrier;
|
|
179
|
|
180 foreach $dfile ( sort(keys(%deps)) ) {
|
|
181 if ( $dfile =~ /^(.*)\.[Cc]$/ ) {
|
|
182 $ofile = $1;
|
|
183 $str = convert_file($ofile, $sep).$obj.':';
|
|
184 $len = length($str);
|
|
185 print $out $str;
|
|
186 foreach $dep ($dfile, alldeps($dfile,1)) {
|
|
187 unless ($do_exclude{$dep}) {
|
|
188 $str = convert_file($dep, $sep);
|
|
189 $sl = length($str)+1;
|
|
190 if ( $len+$sl > $maxline-2 ) {
|
|
191 print $out ' ', $cont, "\n ", $str;
|
|
192 $len = $sl;
|
|
193 } else {
|
|
194 print $out ' ', $str;
|
|
195 $len += $sl;
|
|
196 }
|
|
197 }
|
|
198 }
|
|
199 print $out "\n";
|
|
200 }
|
|
201 }
|
|
202 close($out);
|
|
203
|
|
204 (unlink($file) && rename($tmp, $file))
|
|
205 or die "$0: Failed to change $tmp -> $file\n";
|
|
206 }
|
|
207
|
|
208 #
|
|
209 # Main program
|
|
210 #
|
|
211
|
|
212 my %deps = ();
|
|
213 my @files = ();
|
|
214 my @mkfiles = ();
|
|
215 my $mkmode = 0;
|
|
216
|
|
217 while ( defined(my $arg = shift(@ARGV)) ) {
|
|
218 if ( $arg eq '-m' ) {
|
|
219 $arg = shift(@ARGV);
|
|
220 push(@mkfiles, $arg);
|
|
221 } elsif ( $arg eq '-M' ) {
|
|
222 $mkmode = 1; # Futher filenames are output Makefile names
|
|
223 } elsif ( $arg eq '--' && $mkmode ) {
|
|
224 $mkmode = 0;
|
|
225 } elsif ( $arg =~ /^-/ ) {
|
|
226 die "Unknown option: $arg\n";
|
|
227 } else {
|
|
228 if ( $mkmode ) {
|
|
229 push(@mkfiles, $arg);
|
|
230 } else {
|
|
231 push(@files, $arg);
|
|
232 }
|
|
233 }
|
|
234 }
|
|
235
|
|
236 my @cfiles = ();
|
|
237
|
|
238 foreach my $dir ( @files ) {
|
|
239 opendir(DIR, $dir) or die "$0: Cannot open directory: $dir";
|
|
240
|
|
241 while ( my $file = readdir(DIR) ) {
|
|
242 $path = ($dir eq File::Spec->curdir())
|
|
243 ? $file : File::Spec->catfile($dir,$file);
|
|
244 if ( $file =~ /\.[Cc]$/ ) {
|
|
245 push(@cfiles, $path);
|
|
246 } elsif ( $file =~ /\.[Hh]$/ ) {
|
|
247 print STDERR "Filesystem: $file -> $path\n";
|
|
248 $dep_path{$file} = $path; # Allow the blank filename
|
|
249 $dep_path{$path} = $path; # Also allow the full pathname
|
|
250 }
|
|
251 }
|
|
252 closedir(DIR);
|
|
253 }
|
|
254
|
|
255 foreach my $cfile ( @cfiles ) {
|
|
256 scandeps($cfile);
|
|
257 }
|
|
258
|
|
259 foreach my $mkfile ( @mkfiles ) {
|
|
260 insert_deps($mkfile);
|
|
261 }
|