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_[^_]+_library\(/ || /^add_llvm_target\(/ || /^add_[^_]+_executable\(/) { 72 $foundLibrary = 1; 73 EmitCMakeList($dir); 74 } 75 } 76 else { 77 if (/\)/) { 78 print OUT $_; 79 $foundLibrary = 0; 80 } 81 } 82 } 83 84 close(IN); 85 close(OUT); 86 87 open(FILE, $cmakeList) or 88 die("Cannot open $cmakeList when computing digest\n"); 89 binmode FILE; 90 my $digestA = Digest::MD5->new->addfile(*FILE)->hexdigest; 91 close(FILE); 92 93 open(FILE, $cmakeListNew) or 94 die("Cannot open $cmakeListNew when computing digest\n"); 95 binmode FILE; 96 my $digestB = Digest::MD5->new->addfile(*FILE)->hexdigest; 97 close(FILE); 98 99 if ($digestA ne $digestB) { 100 move($cmakeListNew, $cmakeList); 101 return 1; 102 } 103 104 unlink($cmakeListNew); 105 return 0; 106} 107 108sub UpdateCMakeFiles { 109 foreach my $dir (sort keys %dirCMake) { 110 if (UpdateCMake($dirCMake{$dir}, $dir)) { 111 print "Updated: $dir\n"; 112 } 113 } 114} 115 116find({ wanted => \&ProcessFile, follow => 1 }, '.'); 117UpdateCMakeFiles(); 118 119