File: convert-to-cmake-automoc.pl

package info (click to toggle)
kde-dev-scripts 4%3A18.08.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 3,496 kB
  • sloc: perl: 15,466; lisp: 5,627; sh: 4,157; python: 3,892; ruby: 2,158; makefile: 16; sed: 9
file content (71 lines) | stat: -rwxr-xr-x 2,747 bytes parent folder | download | duplicates (2)
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" );