#!@PERL@ -w # -*- perl -*- # @configure_input@ use strict; use Carp; use File::Basename; use FileHandle; ######################################################################## # # Globals # # map from each file to other files it directly includes my %includes; # directories to be searched, in the manner of "-I" my @search; # cache of files already found using @search my %found; ######################################################################## # # Supporting cast # sub findFile ($) { my $filename = shift; unless (exists $found{$filename}) { foreach (@search) { my $candidate = "$_/$filename"; if (-r $candidate) { $found{$filename} = $candidate; last; } } } return $found{$filename}; } sub collectDependencies (@) { my @pending = @_; while (@pending) { my $filename = shift @pending; my $file = new FileHandle $filename or die "Could not open $filename: $!\n"; while (<$file>) { /^#include "(.*)"$/ or next; if (my $header = findFile $1) { push @{$includes{$filename}}, $header; unless (exists $includes{$header}) { push @pending, $header; $includes{$header} = []; } } else { local $" = ':'; warn "$filename:$.: warning: could not find $1 in @search\n"; } } } } sub printDependencies (@) { foreach my $filename (@_) { my @pending = $filename; my %seen = ( $filename => 1 ); while (@pending) { foreach (@{$includes{shift @pending}}) { unless ($seen{$_}) { push @pending, $_; $seen{$_} = 1; } } } my @dependencies = keys %seen; my $object = basename $filename; $object =~ s/\.c$/.o/; local $" = " \\\n\t"; print "\$(cache_dir)/$object: \\\n\t@dependencies\n"; } } ######################################################################## # # Main event # while (@ARGV && $ARGV[0] ne "--") { local $_ = shift; /^-I(.*)?$/ or next; push @search, ($1 eq '' ? shift : $1); } shift; @ARGV or die "Usage: $0 [ -I ... ] -- ...\n"; collectDependencies @ARGV; printDependencies @ARGV;