1#!/usr/bin/env perl
2use strict;
3use File::Find;
4use File::Copy;
5use Digest::MD5;
6
7my @fileTypes = ("cpp", "c");
8my %dirFiles;
9my %dirCMake;
10
11sub GetFiles {
12  my $dir = shift;
13  my $x = $dirFiles{$dir};
14  if (!defined $x) {
15    $x = [];
16    $dirFiles{$dir} = $x;
17  }
18  return $x;
19}
20
21sub ProcessFile {
22  my $file = $_;
23  my $dir = $File::Find::dir;
24  # Record if a CMake file was found.
25  if ($file eq "CMakeLists.txt") {
26    $dirCMake{$dir} = $File::Find::name;
27    return 0;
28  }
29  # Grab the extension of the file.
30  $file =~ /\.([^.]+)$/;
31  my $ext = $1;
32  my $files;
33  foreach my $x (@fileTypes) {
34    if ($ext eq $x) {
35      if (!defined $files) {
36        $files = GetFiles($dir);
37      }
38      push @$files, $file;
39      return 0;
40    }
41  }
42  return 0;
43}
44
45sub EmitCMakeList {
46  my $dir = shift;
47  my $files = $dirFiles{$dir};
48
49  if (!defined $files) {
50    return;
51  }
52
53  foreach my $file (sort @$files) {
54    print OUT "  ";
55    print OUT $file;
56    print OUT "\n";
57  }
58}
59
60sub UpdateCMake {
61  my $cmakeList = shift;
62  my $dir = shift;
63  my $cmakeListNew = $cmakeList . ".new";
64  open(IN, $cmakeList);
65  open(OUT, ">", $cmakeListNew);
66  my $foundLibrary = 0;
67
68  while(<IN>) {
69    if (!$foundLibrary) {
70      print OUT $_;
71      if (/^add_clang_library\(/ || /^add_llvm_library\(/ || /^add_llvm_target\(/
72          || /^add_executable\(/) {
73        $foundLibrary = 1;
74        EmitCMakeList($dir);
75      }
76    }
77    else {
78      if (/\)/) {
79        print OUT $_;
80        $foundLibrary = 0;
81      }
82    }
83  }
84
85  close(IN);
86  close(OUT);
87
88  open(FILE, $cmakeList) or
89    die("Cannot open $cmakeList when computing digest\n");
90  binmode FILE;
91  my $digestA = Digest::MD5->new->addfile(*FILE)->hexdigest;
92  close(FILE);
93
94  open(FILE, $cmakeListNew) or
95    die("Cannot open $cmakeListNew when computing digest\n");
96  binmode FILE;
97  my $digestB = Digest::MD5->new->addfile(*FILE)->hexdigest;
98  close(FILE);
99
100  if ($digestA ne $digestB) {
101    move($cmakeListNew, $cmakeList);
102    return 1;
103  }
104
105  unlink($cmakeListNew);
106  return 0;
107}
108
109sub UpdateCMakeFiles {
110  foreach my $dir (sort keys %dirCMake) {
111    if (UpdateCMake($dirCMake{$dir}, $dir)) {
112      print "Updated: $dir\n";
113    }
114  }
115}
116
117find({ wanted => \&ProcessFile, follow => 1 }, '.');
118UpdateCMakeFiles();
119
120