#! /usr/bin/env perl use strict; use Cwd; use File::Find; my %dir2files=(); my $cppExt=" cpp cc cxx C c++ "; my $cppFiles="*.cpp *.cc *.cxx *.C *.c++"; sub collectthing() { if (/\.([^.]+)$/) { my $ext=$1; if (" h H hh hxx h++ " =~ / $ext /) { my $line=`grep -l '^[{ \t]*Q_OBJECT' $_ 2> /dev/null`; chomp($line); if ($line) { $dir2files{$File::Find::dir}->{headers}->{$_} = 1; } } elsif ($cppExt =~ / $ext /) { $dir2files{$File::Find::dir}->{sources}->{$_} = 1; } } } sub checkdir($) { my ($dir)=@_; chdir($dir); my $hdrs=$dir2files{$dir}->{headers}; my $srcs=$dir2files{$dir}->{sources}; foreach my $h (keys %$hdrs) { (my $name=$h) =~ s/\.[^.]+$//; my @answer = `grep -l "^#include[ ]*.$name\.tqmoc." $cppFiles 2> /dev/null`; if (@answer == 0) { my $s; foreach my $e (split(/\s+/, $cppExt)) { if (exists $srcs->{$name.".".$e}) { $s=$dir."/".$name.".".$e; last; } } if ($s) { print "echo >> $s ;\n"; print "echo '#include \"$name.tqmoc\"' >> $s ;\n"; } else { print "echo \"can't guess a C++ file for $dir/$h\" ;\n"; } } } } find (\&collectthing, cwd()); foreach my $k (keys %dir2files) { print STDERR "Directory $k:\n headers=["; print STDERR join(", ", keys %{$dir2files{$k}->{headers}}); print STDERR "]\n sources=["; print STDERR join(", ", keys %{$dir2files{$k}->{sources}}); print STDERR "]\n"; checkdir($k); } =head1 NAME includetqmocs -- handle tqmocifyable headers, whose .tqmoc file is nowhere included. =head1 SYNOPSIS includetqmocs =head1 DESCRIPTION Header files declaring a QObject descendant have to be run through tqmoc to produce a .tqmoc file. This .tqmoc file has to be compiled, for which two possibilities exists: compile it separately, or #include it in the C++ file implementing that above mentioned class. The latter is more efficient in term of compilation speed. This script searches in the current directory and its subdirs for header files declaring a QObject descendant class. If it finds some, it looks, if there is a C++ file containing an '#include' for the generated .tqmoc file. If thats not the case, it tries to guess into which C++ file that '#include' is placed best (based on the filename). If it fails to guess a proper place, it mentions that. On stdout commands are ouput, suitable for a shell, which, when evaluated, add the suggested '#include' at the end of the files. On stderr some informational messages are printed. =head1 EXAMPLES cd tdebase ; includetqmocs cd tdebase ; `eval includetqmocs 2> /dev/null` =head1 AUTHOR Michael Matz =cut