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