mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-11-27 08:10:07 +08:00
3a7edd73a3
Sort the dependency lists generated by "mkdep.pl", to make sure that re-running "make alldeps" doesn't change anything unless there has been real dependency changes. The previous version could produce different output between runs and across platforms.
190 lines
4.2 KiB
Perl
Executable File
190 lines
4.2 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
# Script to create Makefile-style dependencies.
|
|
#
|
|
# Usage: perl mkdep.pl [-s path-separator] [-o obj-ext] dir... > deps
|
|
#
|
|
|
|
use File::Spec;
|
|
use File::Basename;
|
|
use Fcntl;
|
|
|
|
$barrier = "#-- Everything below is generated by mkdep.pl - do not edit --#\n";
|
|
|
|
#
|
|
# Scan files for dependencies
|
|
#
|
|
sub scandeps($) {
|
|
my($file) = @_;
|
|
my($line, $nf);
|
|
my(@xdeps) = ();
|
|
my(@mdeps) = ();
|
|
|
|
sysopen(FILE, $file, O_RDONLY)
|
|
or return; # If not openable, assume generated
|
|
|
|
while ( defined($line = <FILE>) ) {
|
|
chomp $line;
|
|
$line =~ s:/\*.*\*/::g;
|
|
$line =~ s://.*$::;
|
|
if ( $line =~ /^\s*\#\s*include\s+\"(.*)\"\s*$/ ) {
|
|
$nf = $1;
|
|
push(@mdeps, $nf);
|
|
push(@xdeps, $nf) unless ( defined($deps{$nf}) );
|
|
}
|
|
}
|
|
close(FILE);
|
|
$deps{$file} = [@mdeps];
|
|
|
|
foreach $file ( @xdeps ) {
|
|
scandeps($file);
|
|
}
|
|
}
|
|
|
|
# %deps contains direct dependencies. This subroutine resolves
|
|
# indirect dependencies that result.
|
|
sub alldeps($) {
|
|
my($file) = @_;
|
|
my(%adeps);
|
|
my($dep,$idep);
|
|
|
|
foreach $dep ( @{$deps{$file}} ) {
|
|
$adeps{$dep} = 1;
|
|
foreach $idep ( alldeps($dep) ) {
|
|
$adeps{$idep} = 1;
|
|
}
|
|
}
|
|
return sort(keys(%adeps));
|
|
}
|
|
|
|
# This converts a filename from host syntax to target syntax
|
|
# This almost certainly works only on relative filenames...
|
|
sub convert_file($$) {
|
|
my($file,$sep) = @_;
|
|
my(@fspec) = (basename($file));
|
|
while ( ($file = dirname($file)) ne File::Spec->curdir() &&
|
|
$file ne File::Spec->rootdir() ) {
|
|
unshift(@fspec, basename($file));
|
|
}
|
|
|
|
if ( $sep eq '' ) {
|
|
# This means kill path completely. Used with Makes who do
|
|
# path searches, but doesn't handle output files in subdirectories,
|
|
# like OpenWatcom WMAKE.
|
|
return $fspec[scalar(@fspec)-1];
|
|
} else {
|
|
return join($sep, @fspec);
|
|
}
|
|
}
|
|
|
|
#
|
|
# Insert dependencies into a Makefile
|
|
#
|
|
sub insert_deps($) {
|
|
my($file) = @_;
|
|
$nexttemp++; # Unique serial number for each temp file
|
|
my($tmp) = File::Spec->catfile(dirname($file), 'tmp.'.$nexttemp);
|
|
|
|
sysopen(IN, $file, O_RDONLY)
|
|
or die "$0: Cannot open input: $file\n";
|
|
sysopen(OUT, $tmp, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
|
or die "$0: Cannot open output: $tmp\n";
|
|
|
|
my($line,$parm,$val);
|
|
my($obj) = '.o'; # Defaults
|
|
my($sep) = '/';
|
|
my($maxline) = 78; # Seems like a reasonable default
|
|
|
|
while ( defined($line = <IN>) ) {
|
|
if ( $line =~ /^\s*\#\s*@([a-z0-9-]+):\s*\"([^\"]*)\"/ ) {
|
|
$parm = $1; $val = $2;
|
|
if ( $parm eq 'object-ending' ) {
|
|
$obj = $val;
|
|
} elsif ( $parm eq 'path-separator' ) {
|
|
$sep = $val;
|
|
} elsif ( $parm eq 'line-width' ) {
|
|
$maxline = $val+0;
|
|
}
|
|
} elsif ( $line eq $barrier ) {
|
|
last; # Stop reading input at barrier line
|
|
}
|
|
print OUT $line;
|
|
}
|
|
close(IN);
|
|
|
|
my $dfile, $ofile, $str, $sl, $len;
|
|
my @deps, $dep;
|
|
|
|
print OUT $barrier;
|
|
|
|
foreach $dfile ( sort(keys(%deps)) ) {
|
|
if ( $dfile =~ /\.[Cc]$/ ) {
|
|
$ofile = $dfile; $ofile =~ s/\.[Cc]$//;
|
|
$str = convert_file($ofile,$sep).$obj.':';
|
|
$len = length($str);
|
|
print OUT $str;
|
|
foreach $dep ($dfile, alldeps($dfile)) {
|
|
$str = convert_file($dep,$sep);
|
|
$sl = length($str)+1;
|
|
if ( $len+$sl > $maxline-2 ) {
|
|
print OUT " \\\n ", $str;
|
|
$len = $sl;
|
|
} else {
|
|
print OUT ' ', $str;
|
|
$len += $sl;
|
|
}
|
|
}
|
|
print OUT "\n";
|
|
}
|
|
}
|
|
close(OUT);
|
|
|
|
(unlink($file) && rename($tmp, $file))
|
|
or die "$0: Failed to change $tmp -> $file\n";
|
|
}
|
|
|
|
#
|
|
# Main program
|
|
#
|
|
|
|
%deps = ();
|
|
@files = ();
|
|
@mkfiles = ();
|
|
$mkmode = 0;
|
|
|
|
while ( defined($arg = shift(@ARGV)) ) {
|
|
if ( $arg eq '-m' ) {
|
|
$arg = shift(@ARGV);
|
|
push(@mkfiles, $arg);
|
|
} elsif ( $arg eq '-M' ) {
|
|
$mkmode = 1; # Futher filenames are output Makefile names
|
|
} elsif ( $arg eq '--' && $mkmode ) {
|
|
$mkmode = 0;
|
|
} elsif ( $arg =~ /^-/ ) {
|
|
die "Unknown option: $arg\n";
|
|
} else {
|
|
if ( $mkmode ) {
|
|
push(@mkfiles, $arg);
|
|
} else {
|
|
push(@files, $arg);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach $dir ( @files ) {
|
|
opendir(DIR, $dir) or die "$0: Cannot open directory: $dir";
|
|
|
|
while ( $file = readdir(DIR) ) {
|
|
$path = ($dir eq File::Spec->curdir())
|
|
? $file : File::Spec->catfile($dir,$file);
|
|
if ( $file =~ /\.[Cc]$/ ) {
|
|
scandeps($path);
|
|
}
|
|
}
|
|
closedir(DIR);
|
|
}
|
|
|
|
foreach $mkfile ( @mkfiles ) {
|
|
insert_deps($mkfile);
|
|
}
|