Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use warnings;
- use strict;
- use File::Find;
- use File::Spec;
- use Cwd;
- sub handle ($);
- sub addInclude ($$);
- sub canonPath ($);
- sub buildDeps ($);
- sub addError (@);
- File::Find::find {
- 'follow_fast' => 1,
- 'dangling_symlinks' => 0,
- 'no_chdir' => 1,
- 'wanted' => sub {
- return if -d;
- return unless /\.[ch]pp$/;
- handle $_;
- }
- }, 'src';
- my %includes;
- my %errors;
- my $exitCode = 0;
- for (sort keys %includes) {
- if (m~^src/(.*)\.cpp$~) {
- my @deps = buildDeps $_;
- my %saw;
- print "\$(OBJS_DIR)/$1.o: $_ ", join(' ', grep(!$saw{$_}++, @deps)), "\n";
- }
- }
- if (%errors) {
- print STDERR "Cyclic inclusion(s) detected:\n", sort keys %errors;
- $exitCode |= 2;
- }
- exit $exitCode;
- sub handle ($) {
- my $file = canonPath $_[0];
- my $line;
- open my $fh, '<', $file or die "$file: $!\n";
- while (defined ($line = <$fh>)) {
- if ($line =~ /^#\s*include\s*"([^"]*)"/) {
- addInclude $file, $1;
- }
- }
- close $fh;
- }
- sub addInclude ($$) {
- my ($file, $_include, $include) = @_;
- my ($volume, $dir) = File::Spec->splitpath($file);
- $dir = File::Spec->catpath ($volume, $dir, '');
- $include = File::Spec->catfile ($dir, $_include);
- $include = canonPath $include;
- $includes{$file} = [ ] unless exists $includes{$file };
- $includes{$include} = [ ] unless exists $includes{$include};
- push @{ $includes{$file} }, $include;
- if (! -f $include) {
- print STDERR "$file:$.: includes nonexisting file '$_include'\n";
- $exitCode |= 1;
- }
- }
- {
- my $cwd = Cwd::getcwd;
- sub canonPath ($) {
- File::Spec->abs2rel(Cwd::realpath($_[0]), $cwd);
- }
- }
- {
- my %path;
- my $path_depth = 0;
- sub buildDeps ($) {
- my $file = $_[0];
- if (exists $path{$file}) {
- my %p = reverse %path;
- addError @p{$path{$file} .. $path_depth};
- return ( );
- }
- $path{$file} = ++$path_depth;
- my @ret = ( );
- for my $inc (@{ $includes{$file} }) {
- push @ret, $inc, buildDeps $inc;
- }
- delete $path{$file};
- --$path_depth;
- @ret;
- }
- }
- sub addError (@) {
- my $count = @_;
- my $min = $_[0];
- my $pos = 0;
- my $error = '';
- for (my $i = 1; $i < $count; ++$i) {
- if ($_[$i] lt $min) {
- $min = $_[$i];
- $pos = $i;
- }
- }
- for (my $i = 0; $i <= $count; ++$i) {
- $error .= ' -> ' . $_[$pos];
- $pos = ($pos + 1) % $count;
- }
- $errors{substr($error, 4) . "\n"} = 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement