#!/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_[^_]+_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();