1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
#!/usr/bin/perl
# Kevin Funk <kfunk@kde.org> (2015)
#
# Attempts to remove lines such as '#include "<basename>.moc"' from cpp files
#
# Automoc conventions:
# - include moc_<basename>.cpp <=> Q_OBJECT/Q_GADGET inside header
# - include <basename>.moc <=> Q_OBJECT/Q_GADGET inside source file
#
# Additionally, if K_PLUGIN_FACTORY is used, we'll *have* to use '<basename>.moc'
#
# Now, if <basename>.moc is included, and the source file does *not* need a moc run,
# CMake's automoc still performs a moc run and moc will give warnings, such as:
# "foo.cpp:0: Note: No relevant classes found. No output generated."
# => Remove the include in this case
#
# More info: http://www.cmake.org/cmake/help/v3.0/manual/cmake-qt.7.html#automoc
#
# Usual invocation:
# find -iname "*.cpp" | xargs kde-dev-scripts/kf5/convert-to-cmake-automoc.pl
use strict;
use warnings;
use File::Basename;
use lib dirname($0);
use functionUtilkde;
foreach my $file (@ARGV) {
open(my $FILE, "<", $file) or die "We can't open file $file:$!\n";
my $content = do { local $/; <$FILE> };
my $regexRequiresMoc = qr/(Q_OBJECT|Q_GADGET|K_PLUGIN_FACTORY|EXPORT_KONTACT_PLUGIN|_WITH_JSON|K_EXPORT_PLASMA_)/;
my ($filenameWithoutExtension, $dirs,) = fileparse($file, qr/\.[^.]*/);
# In some cases, we cannot just get rid off the '#include <basename>.moc',
# and need to include '#include moc_<basename>.cpp'
# E.g. in case when the moc-generated file needs information about a class declared inside the .cpp file
# Try to detect these cases and include '#include moc_<basename>.cpp' instead
my $headerFile = $dirs . "$filenameWithoutExtension.h";
my $requiresHeaderMocInclude = (-e $headerFile) ?
`grep Q_PRIVATE_SLOT -q $headerFile` :
0;
my $sourceMocFilename = "$filenameWithoutExtension.moc";
my $requiresSourceMocInclude = ($content =~ /$regexRequiresMoc/);
my $includesSourceMocInclude = ($content =~ /#include \"$sourceMocFilename\"/);
# rewrite file and fix moc includes
if (!$requiresSourceMocInclude && $includesSourceMocInclude) {
open (my $OUT, ">", $file);
# TODO: Refactor, then use functionUtilkde::removeIncludeInFile?
# Cannot use, because it a) only accepts <>-style includes and b) creates redundant newlines
for (split /^/, $content) {
# strip or replace unwanted includes
if (/#include \"$sourceMocFilename\"/) {
if ($requiresHeaderMocInclude) {
print $OUT "#include \"moc_$filenameWithoutExtension.cpp\"\n";
}
next; # remove line
}
print $OUT $_;
}
close ($OUT);
}
}
functionUtilkde::diffFile( "@ARGV" );
|