|  | #!/usr/bin/env perl | 
|  | use strict; | 
|  | use File::Find; | 
|  | use File::Copy; | 
|  | use Digest::MD5; | 
|  |  | 
|  | my @fileTypes = ("cpp", "c"); | 
|  | my %dirFiles; | 
|  | my %dirCMake; | 
|  |  | 
|  | sub GetFiles { | 
|  | my $dir = shift; | 
|  | my $x = $dirFiles{$dir}; | 
|  | if (!defined $x) { | 
|  | $x = []; | 
|  | $dirFiles{$dir} = $x; | 
|  | } | 
|  | return $x; | 
|  | } | 
|  |  | 
|  | sub ProcessFile { | 
|  | my $file = $_; | 
|  | my $dir = $File::Find::dir; | 
|  | # Record if a CMake file was found. | 
|  | if ($file eq "CMakeLists.txt") { | 
|  | $dirCMake{$dir} = $File::Find::name; | 
|  | return 0; | 
|  | } | 
|  | # Grab the extension of the file. | 
|  | $file =~ /\.([^.]+)$/; | 
|  | my $ext = $1; | 
|  | my $files; | 
|  | foreach my $x (@fileTypes) { | 
|  | if ($ext eq $x) { | 
|  | if (!defined $files) { | 
|  | $files = GetFiles($dir); | 
|  | } | 
|  | push @$files, $file; | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | sub EmitCMakeList { | 
|  | my $dir = shift; | 
|  | my $files = $dirFiles{$dir}; | 
|  |  | 
|  | if (!defined $files) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | foreach my $file (sort @$files) { | 
|  | print OUT "  "; | 
|  | print OUT $file; | 
|  | print OUT "\n"; | 
|  | } | 
|  | } | 
|  |  | 
|  | sub UpdateCMake { | 
|  | my $cmakeList = shift; | 
|  | my $dir = shift; | 
|  | my $cmakeListNew = $cmakeList . ".new"; | 
|  | open(IN, $cmakeList); | 
|  | open(OUT, ">", $cmakeListNew); | 
|  | my $foundLibrary = 0; | 
|  |  | 
|  | while(<IN>) { | 
|  | if (!$foundLibrary) { | 
|  | print OUT $_; | 
|  | if (/^add_clang_library\(/ || /^add_llvm_library\(/ || /^add_llvm_target\(/ | 
|  | || /^add_executable\(/) { | 
|  | $foundLibrary = 1; | 
|  | EmitCMakeList($dir); | 
|  | } | 
|  | } | 
|  | else { | 
|  | if (/\)/) { | 
|  | print OUT $_; | 
|  | $foundLibrary = 0; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | close(IN); | 
|  | close(OUT); | 
|  |  | 
|  | open(FILE, $cmakeList) or | 
|  | die("Cannot open $cmakeList when computing digest\n"); | 
|  | binmode FILE; | 
|  | my $digestA = Digest::MD5->new->addfile(*FILE)->hexdigest; | 
|  | close(FILE); | 
|  |  | 
|  | open(FILE, $cmakeListNew) or | 
|  | die("Cannot open $cmakeListNew when computing digest\n"); | 
|  | binmode FILE; | 
|  | my $digestB = Digest::MD5->new->addfile(*FILE)->hexdigest; | 
|  | close(FILE); | 
|  |  | 
|  | if ($digestA ne $digestB) { | 
|  | move($cmakeListNew, $cmakeList); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | unlink($cmakeListNew); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | sub UpdateCMakeFiles { | 
|  | foreach my $dir (sort keys %dirCMake) { | 
|  | if (UpdateCMake($dirCMake{$dir}, $dir)) { | 
|  | print "Updated: $dir\n"; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | find({ wanted => \&ProcessFile, follow => 1 }, '.'); | 
|  | UpdateCMakeFiles(); | 
|  |  |