File indexing completed on 2024-04-21 05:41:57

0001 #!/usr/bin/perl -w
0002 
0003 ###############################################################################
0004 # Sanity checks CMakeLists.txt files.                                         #
0005 # Copyright (C) 2006-2012,2017 by Allen Winter <winter@kde.org>               #
0006 # Copyright (C) 2008-2010 by Laurent Montel <montel@kde.org>                  #
0007 #                                                                             #
0008 # This program is free software; you can redistribute it and/or modify        #
0009 # it under the terms of the GNU General Public License as published by        #
0010 # the Free Software Foundation; either version 2 of the License, or           #
0011 # (at your option) any later version.                                         #
0012 #                                                                             #
0013 # This program is distributed in the hope that it will be useful,             #
0014 # but WITHOUT ANY WARRANTY; without even the implied warranty of              #
0015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                #
0016 # GNU General Public License for more details.                                #
0017 #                                                                             #
0018 # You should have received a copy of the GNU General Public License along     #
0019 # with this program; if not, write to the Free Software Foundation, Inc.,     #
0020 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.               #
0021 #                                                                             #
0022 ###############################################################################
0023 #
0024 # A program to check KDE CMakeLists.txt files for common errors.
0025 #
0026 
0027 # Program options:
0028 #   --help:          display help message and exit
0029 #   --version:       display version information and exit
0030 #
0031 
0032 use strict;
0033 use Getopt::Long;
0034 use Cwd 'abs_path';
0035 
0036 my($Prog) = 'cmakelint.pl';
0037 my($Version) = '1.31';
0038 
0039 my($help) = '';
0040 my($version) = '';
0041 my($verbose) = '';
0042 
0043 exit 1
0044 if (!GetOptions('help' => \$help, 'version' => \$version, 'verbose' => \$verbose));
0045 
0046 &Help() if ($help);
0047 if ($#ARGV < 0){ &Help(); exit 0; }
0048 &Version() if ($version);
0049 
0050 my($f,$tot_issues);
0051 $tot_issues=0;
0052 for $f (@ARGV) {
0053   $tot_issues += &processFile($f);
0054 }
0055 exit $tot_issues;
0056 
0057 sub processFile() {
0058   my($in) = @_;
0059   print "Processing $in:\n";
0060   open(IN,"<$in") || die "Couldn't open $in";
0061 
0062   my($apath) = abs_path($in);
0063   my($in_kdelibs)=0;
0064   $in_kdelibs=1 if ($apath =~ m+/kdelibs/+);
0065   my($in_kdepimlibs)=0;
0066   $in_kdepimlibs=1 if ($apath =~ m+/kdepimlibs/+);
0067   my($in_kdebase)=0;
0068   $in_kdebase=1 if ($apath =~ m+/kdebase/+);
0069   my($in_kdegames)=0;
0070   $in_kdegames=1 if ($apath =~ m+/kdegames/+);
0071 
0072   my($top_of_module)=0;
0073   $top_of_module=1 if ($apath =~ m+/koffice/CMakeLists.txt+);
0074   $top_of_module=1 if ($apath =~ m+/kdereview/CMakeLists.txt+);
0075   $top_of_module=1 if ($apath =~ m+/playground/[a-zA-Z_1-9]*/CMakeLists.txt+);
0076   $top_of_module=1 if ($apath =~ m+/extragear/[a-zA-Z_1-9]*/CMakeLists.txt+);
0077   $top_of_module=1 if ($apath =~ m+/kdebase/(apps|runtime|workspace)/CMakeLists.txt+);
0078   $top_of_module=1 if ($apath =~ m+/kde(libs|pimlibs|base|base-apps|base-runtime|base-workspace|accessibility|addons|admin|artwork|bindings|edu|games|graphics|multimedia|network|pim|sdk|toys|utils|develop|devplatform|webdev|plasma-addons)/CMakeLists.txt+);
0079 
0080   my($top_of_project)=0;
0081   $top_of_project=1 if ($apath =~ m+/koffice/[a-zA-Z_1-9]*/CMakeLists.txt+);
0082   $top_of_project=1 if ($apath =~ m+/kdereview/[a-zA-Z_1-9]*/CMakeLists.txt+);
0083   $top_of_project=1 if ($apath =~ m+/playground/[a-zA-Z_1-9]*/[a-zA-Z_1-9]*/CMakeLists.txt+);
0084   $top_of_project=1 if ($apath =~ m+/extragear/[a-zA-Z_1-9]*/[a-zA-Z_1-9]*/CMakeLists.txt+);
0085   $top_of_project=1 if ($apath =~ m+/kde(libs|pimlibs|base|accessibility|addons|admin|artwork|bindings|edu|games|graphics|multimedia|network|pim|sdk|toys|utils|develop|devplatform|webdev|plasma-addons)/[a-zA-Z_1-9]*/CMakeLists.txt+);
0086   $top_of_project=0 if ($apath =~ m+/(cmake|pics)/+);
0087 
0088   my(@lines);
0089   my($line,$nextline);
0090   my($linecnt)=0;
0091   my($issues)=0;
0092   my(@ch,$c);
0093   my($nob,$ncb)=(0,0);
0094   my($nop,$ncp)=(0,0);
0095   my($pack,%optpacks);
0096 
0097   #look for "bad" stuff
0098   my($prevline)="";
0099   while ( $line = <IN> ) {
0100     $linecnt++;
0101     chomp($line);
0102 
0103     $line =~ s/#.*$//; #remove comments
0104 
0105     if ( $line !~ m/\)\s*$/ || $line =~ m/"\s*$/ ) {
0106       $nextline = <IN>;
0107       if (defined($nextline)) {
0108         $nextline =~ s/#.*$//; #remove comments
0109         $linecnt++;
0110         chomp($nextline);
0111         $line .= $nextline;
0112       }
0113       redo unless eof(IN);
0114     }
0115 
0116     next if (! $line);           #skip empty lines
0117     next if ($line =~ m/^\s*$/); #skip blank lines
0118 
0119     push(@lines, $line);
0120 
0121     @ch = split(//,$line);
0122     $nob = $ncb = 0;
0123     foreach $c (@ch) {
0124       $nop++ if ($c eq '(');
0125       $ncp++ if ($c eq ')');
0126       $nob++ if ($c eq '{');
0127       $ncb++ if ($c eq '}');
0128     }
0129 
0130     if ($in !~ m+kjsembed/qtonly/CMakeLists.txt+) {
0131       if ($line =~ m/macro_optional_find_package\s*\(\s*([a-zA-Z0-9]*).*\)/i ||
0132           $line =~ m/find_package\s*\(\s*([a-zA-Z0-9]*).*\)/i ||
0133           $line =~ m/find_program\s*\(\s*([a-zA-Z0-9_]*).*\)/i ||
0134           $line =~ m/find_path\s*\(\s*([a-zA-Z0-9_]*).*\)/i) {
0135         $pack = lc($1);
0136         $pack = "libusb" if ($pack eq "usb");
0137         $pack = "mysql_embedded" if ($pack eq "mysql");
0138         if ($pack !~ m/^(carbon|iokit|qt4|qt5|kde4internal|kde4|kf|kdewin32|x11|kdepimlibs|kdevplatform|gpgme|kdcraw|kexiv2|kdesubversion|git_executable)/) {
0139           $optpacks{$pack}{'name'} = $pack;
0140           $optpacks{$pack}{'log'} = 0;
0141         }
0142       }
0143       if ($line =~ m/macro_log_feature\(\s*([A-Z0-9_]*).*\)/i ||
0144           $line =~ m/set_package_properties\(\s*([A-Z0-9_]*).*\)/i) {
0145         $pack = lc($1);
0146         if ($pack !~ m/^(compositing|strigiqtdbusclient|xsltproc_executable|qt_qtopengl|qt_qtxmlpatterns_library|qt_qtdeclarative|ggzconfig)_/ &&
0147             $pack !~ m/x11_.*_found/ &&
0148             $pack !~ m/true/i && $pack !~ m/false/i) {
0149           $pack =~ s/_xcb//;
0150           $pack =~ s/have_//;
0151           $pack =~ s/_found//;
0152           $pack =~ s/_video//;
0153           $pack =~ s/shared_mime_info/sharedmimeinfo/;
0154           if($pack eq "xsltproc_executable") {
0155             $pack = "libxslt";
0156           }
0157           if (!defined($optpacks{$pack}{'name'})) {
0158 #           if ($pack !~ m/^(kwin_compositing|current_alsa)/) {
0159               $issues++;
0160               &printIssue($line,$linecnt,"macro_log_feature($pack) used without a corresponding find_package");
0161             }
0162 #         }
0163           $optpacks{$pack}{'log'} = 1;
0164         }
0165       }
0166     }
0167 
0168     $issues += &checkLine($line,$linecnt,
0169                           '[[:space:]]\{\$',
0170                           'replace "{$" with "${", or garbage detected');
0171 
0172     $issues += &checkLine($line,$linecnt,
0173                           '[^[:print:]]\{\$',
0174                           'non-printable characters detected');
0175 
0176     $issues += &checkLine($line,$linecnt,
0177                           '[Kk][Dd][Ee]4_[Aa][Uu][Tt][Oo][Mm][Oo][Cc]',
0178                           'KDE4_AUTOMOC() is obsolete. Remove it.');
0179 
0180     $issues += &checkLine($line,$linecnt,
0181                           '^[[:space:]]*[Qq][Tt]4_[Aa][Uu][Tt][Oo][Mm][Oo][Cc]',
0182                           'No need for QT4_AUTOMOC(). Remove it.');
0183 
0184     #$issues += &checkLine($line,$linecnt,
0185     #                     '[Kk][Dd][Ee]3_[Aa][Dd][Dd]_[Kk][Pp][Aa][Rr][Tt]',
0186     #                     'Use KDE4_ADD_PLUGIN() instead of KDE3_ADD_KPART()');
0187 
0188     #ONLY KDE4
0189     #$issues += &checkLine($line,$linecnt,
0190     #                      '^[[:space:]]*[Aa][Dd][Dd]_[Ll][Ii][Bb][Rr][Aa][Rr][Yy]',
0191     #                      'Use KDE4_ADD_LIBRARY() instead of ADD_LIBRARY()');
0192 
0193     $issues += &checkLine($line,$linecnt,
0194                           'DESTINATION[[:space:]]\$\{APPLNK_INSTALL_DIR}',
0195                           'APPLNK_INSTALL_DIR is dead with kde4 replace "${APPLNK_INSTALL_DIR}" with "${XDG_APPS_INSTALL_DIR}" and convert desktop file to xdg format (add Categories)');
0196 
0197     $issues += &checkLine($line,$linecnt,
0198                           'DESTINATION[[:space:]]\$\{MIME_INSTALL_DIR}',
0199                           'Files installed into MIME_INSTALL_DIR will not read. Port them on freedesktop xdg mimetypes.');
0200 
0201     $issues += &checkLine($line,$linecnt,
0202                           'DESTINATION[[:space:]]/lib/kde[[:digit:]]',
0203                           'replace /lib/kde" with "$\{PLUGIN_INSTALL_DIR}"');
0204 
0205     if ($line !~ m/^\s*[Ss][Ee][Tt]\s*\(/) {
0206       $issues += &checkLine($line,$linecnt,
0207                             'DESTINATION[[:space:]]\$\\{LIB_INSTALL_DIR\}\s*\)',
0208                             'replace "DESTINATION ${LIB_INSTALL_DIR}" with "${INSTALL_TARGETS_DEFAULT_ARGS}"');
0209       $issues += &checkLine($line,$linecnt,
0210                             'DESTINATION[[:space:]]lib',
0211                             'replace "DESTINATION lib" with "${INSTALL_TARGETS_DEFAULT_ARGS}"');
0212     }
0213 
0214     $issues += &checkLine($line,$linecnt,
0215                           'DESTINATION[[:space:]]\$\{LIB_INSTALL_DIR}/\$',
0216                           'replace "${LIB_INSTALL_DIR}/${...}" with "${LIB_INSTALL_DIR}/realname"');
0217 
0218     $issues += &checkLine($line,$linecnt,
0219                           'DESTINATION[[:space:]]/*include/*',
0220                           'replace "include" or "/include" with "${INCLUDE_INSTALL_DIR}"');
0221     $issues += &checkLine($line,$linecnt,
0222                           'DESTINATION[[:space:]]\$\{INCLUDE_INSTALL_DIR}/\$',
0223                           'replace "${INCLUDE_INSTALL_DIR}/${...}" with "${INCLUDE_INSTALL_DIR}/realname"');
0224 
0225     if ($line !~ m/PROGRAMS/ && $line !~ m/FILES/ &&
0226         $line !~ m/PERMISSIONS/ &&
0227         $line !~ m/OWNER/ && $line !~ m/GROUP/ && $line !~ m/WORLD/) {
0228       $issues += &checkLine($line,$linecnt,
0229                             'DESTINATION[[:space:]]\$\{BIN_INSTALL_DIR\}\s*\)',
0230                             'replace "DESTINATION ${BIN_INSTALL_DIR}" with "${INSTALL_TARGETS_DEFAULT_ARGS}"');
0231 
0232       $issues += &checkLine($line,$linecnt,
0233                             'DESTINATION[[:space:]]/*bin/*',
0234                             'replace "DESTINATION bin" or "/bin" with "${INSTALL_TARGETS_DEFAULT_ARGS}"');
0235     }
0236 
0237     $issues += &checkLine($line,$linecnt,
0238                           'DESTINATION[[:space:]]\$\{BIN_INSTALL_DIR}/\$',
0239                           'replace "${BIN_INSTALL_DIR}/${...}" with "${BIN_INSTALL_DIR}/realname"');
0240 
0241     $issues += &checkLine($line,$linecnt,
0242                           'DESTINATION[[:space:]]/*share/doc/HTML/*',
0243                           'replace "share/doc/HTML/" or "/share/doc/HTML/" with "${HTML_INSTALL_DIR}"');
0244 
0245     $issues += &checkLine($line,$linecnt,
0246                           'DESTINATION[[:space:]]/*share/apps/*',
0247                           'replace "share/apps" or "/share/apps" with "${DATA_INSTALL_DIR}"');
0248     $issues += &checkLine($line,$linecnt,
0249                           'DESTINATION[[:space:]]\$\{DATA_INSTALL_DIR}/\$',
0250                           'replace "${DATA_INSTALL_DIR}/${...}" with "${DATA_INSTALL_DIR}/realname"');
0251 
0252     $issues += &checkLine($line,$linecnt,
0253                           'DESTINATION[[:space:]]/*share/applications/*',
0254                           'replace "share/applications" or "/share/applications" with "${XDG_APPS_INSTALL_DIR}"');
0255 
0256     $issues += &checkLine($line,$linecnt,
0257                           'DESTINATION[[:space:]]/*share/autostart/*',
0258                           'replace "share/autostart" or "/share/autostart" with "${AUTOSTART_INSTALL_DIR}"');
0259     $issues += &checkLine($line,$linecnt,
0260                           'DESTINATION[[:space:]]\$\{AUTOSTART_INSTALL_DIR}/\$',
0261                           'replace "${AUTOSTART_INSTALL_DIR}/${...}" with "${AUTOSTART_INSTALL_DIR}/realname"');
0262 
0263     $issues += &checkLine($line,$linecnt,
0264                           'DESTINATION[[:space:]]/*share/icons/*',
0265                           'replace "share/icons" or "/share/icons" with "${ICON_INSTALL_DIR}"');
0266     if ($in !~ m/IconThemes/) {
0267       $issues += &checkLine($line,$linecnt,
0268                             'DESTINATION[[:space:]]\$\{ICON_INSTALL_DIR}/\$',
0269                             'replace "${ICON_INSTALL_DIR}/${...}" with "${ICON_INSTALL_DIR}/realname"');
0270     }
0271     $issues += &checkLine($line,$linecnt,
0272                           'DESTINATION[[:space:]]/*share/locale/*',
0273                           'replace "share/locale" or "/share/locale" with "${LOCALE_INSTALL_DIR}"');
0274     $issues += &checkLine($line,$linecnt,
0275                           'DESTINATION[[:space:]]\$\{LOCALE_INSTALL_DIR}/\$',
0276                           'replace "${LOCALE_INSTALL_DIR}/${...}" with "${LOCALE_INSTALL_DIR}/realname"');
0277 
0278     $issues += &checkLine($line,$linecnt,
0279                           'DESTINATION[[:space:]]/*share/services/*',
0280                           'replace "share/services" or "/share/services" with "${SERVICES_INSTALL_DIR}"');
0281     $issues += &checkLine($line,$linecnt,
0282                           'DESTINATION[[:space:]]\$\{SERVICES_INSTALL_DIR}/\$',
0283                           'replace "${SERVICES_INSTALL_DIR}/${...}" with "${SERVICES_INSTALL_DIR}/realname"');
0284 
0285     $issues += &checkLine($line,$linecnt,
0286                           'DESTINATION[[:space:]]/*share/sounds/*',
0287                           'replace "share/sounds" or "/share/sounds" with "${SOUND_INSTALL_DIR}"');
0288     $issues += &checkLine($line,$linecnt,
0289                           'DESTINATION[[:space:]]\$\{SOUND_INSTALL_DIR}/\$',
0290                           'replace "${SOUND_INSTALL_DIR}/${...}" with "${SOUND_INSTALL_DIR}/realname"');
0291 
0292     $issues += &checkLine($line,$linecnt,
0293                           'install_targets[[:space:]]*\(',
0294                           'replace "install_targets" with "install(TARGETS...)');
0295 
0296     $issues += &checkLine($line,$linecnt,
0297                           'INSTALL_TARGETS[[:space:]]*\(',
0298                           'replace "install_targets" with "install(TARGETS...)');
0299     $issues += &checkLine($line,$linecnt,
0300                           'install_files[[:space:]]*\(',
0301                           'replace "install_files" with "install(FILES...)');
0302     $issues += &checkLine($line,$linecnt,
0303                           'INSTALL_FILES[[:space:]]*\(',
0304                           'replace "install_files" with "install(FILES...)');
0305     $issues += &checkLine($line,$linecnt,
0306                           '\sFILES\sDESTINATION',
0307                           'missing list of files between FILES and DESTINATION');
0308     $issues += &checkLine($line,$linecnt,
0309                           '\sTARGETS\sDESTINATION',
0310                           'missing list of files between TARGETS and DESTINATION');
0311 
0312     $issues += &checkLine($line,$linecnt,
0313                           'DESTINATION\s\$\{INSTALL_TARGETS_DEFAULT_ARGS\}',
0314                           'remove DESTINATION keyword before ${INSTALL_TARGETS_DEFAULT_ARGS}');
0315 
0316     $issues += &checkLine($line,$linecnt,
0317                           'macro_bool_to_01[[:space:]]*\(.*[[:space:]][[:digit:]][[:space:]]*\)',
0318                           'do not use a digit as a variable');
0319     $issues += &checkLine($line,$linecnt,
0320                           'MACRO_BOOL_TO_01[[:space:]]*\(.*[[:space:]][[:digit:]][[:space:]]*\)',
0321                           'do not use a digit as a variable');
0322     $issues += &checkLine($line,$linecnt,
0323                           '-fexceptions',
0324                           'replace "-fexceptions" with "${KDE4_ENABLE_EXCEPTIONS}"');
0325     if ($in !~ m+/(phonon|okular|kopete|kdevelop|libkdegames|kdgantt2)/+) {
0326       $issues +=
0327         &checkLine($line,$linecnt,
0328                    'set_target_properties.*PROPERTIES.*[[:space:]]VERSION[[:space:]][[:digit:]]',
0329                    'replace a hard-coded VERSION with "${GENERIC_LIB_VERSION}"');
0330       $issues +=
0331         &checkLine($line,$linecnt,
0332                    'set_target_properties.*PROPERTIES.*[[:space:]]SOVERSION[[:space:]][[:digit:]]',
0333                    'replace a hard-coded SOVERSION with "${GENERIC_LIB_SOVERSION}"');
0334     }
0335 
0336     #Qt variable
0337     $issues +=
0338       &checkLine($line,$linecnt,
0339                  'target_link_libraries.*[[:space:]]QtDBus[\s/)]',
0340                  'replace "QtDBus" with "${QT_QTDBUS_LIBRARY}"');
0341 
0342     $issues +=
0343       &checkLine($line,$linecnt,
0344                  'target_link_libraries.*[[:space:]]Qt3Support[\s/)]',
0345                  'replace "Qt3Support" with "${QT_QT3SUPPORT_LIBRARY}"');
0346 
0347     $issues +=
0348       &checkLine($line,$linecnt,
0349                  'target_link_libraries.*[[:space:]]QtGui[\s/)]',
0350                  'replace "QtGui" with "${QT_QTGUI_LIBRARY}"');
0351 
0352     $issues +=
0353       &checkLine($line,$linecnt,
0354                  'target_link_libraries.*[[:space:]]QtNetwork[\s/)]',
0355                  'replace "QtNetwork" with "${QT_QTNETWORK_LIBRARY}"');
0356 
0357     $issues +=
0358       &checkLine($line,$linecnt,
0359                  'target_link_libraries.*[[:space:]]QtCore[\s/)]',
0360                  'replace "QtCore" with "${QT_QTCORE_LIBRARY}"');
0361 
0362     $issues +=
0363       &checkLine($line,$linecnt,
0364                  'target_link_libraries.*[[:space:]]QtSql[\s/)]',
0365                  'replace "QtSql" with "${QT_QTSQL_LIBRARY}"');
0366 
0367     $issues +=
0368       &checkLine($line,$linecnt,
0369                  'target_link_libraries.*[[:space:]]QtSvg[\s/)]',
0370                  'replace "QtSvg" with "${QT_QTSVG_LIBRARY}"');
0371 
0372     $issues +=
0373       &checkLine($line,$linecnt,
0374                  'target_link_libraries.*[[:space:]]QtSvg[\s/)]',
0375                  'replace "QtSvg" with "${QT_QTSVG_LIBRARY}"');
0376 
0377     $issues +=
0378       &checkLine($line,$linecnt,
0379                  'target_link_libraries.*[[:space:]]QtTest[\s/)]',
0380                  'replace "QtTest" with "${QT_QTTEST_LIBRARY}"');
0381 
0382     $issues +=
0383       &checkLine($line,$linecnt,
0384                  'target_link_libraries.*[[:space:]]QtXml[\s/)]',
0385                  'replace "QtXml" with "${QT_QTXML_LIBRARY}"');
0386 
0387     $issues +=
0388       &checkLine($line,$linecnt,
0389                  'target_link_libraries.*[[:space:]]QtScript[\s/)]',
0390                  'replace "QtScript" with "${QT_QTSCRIPT_LIBRARY}"');
0391 
0392     $issues +=
0393       &checkLine($line,$linecnt,
0394                  'target_link_libraries.*[[:space:]]QtAssistantClient[\s/)]',
0395                  'replace "QtAssistantClient" with "${QT_QTASSISTANTCLIENT_LIBRARY}"');
0396     $issues +=
0397       &checkLine($line,$linecnt,
0398                  'target_link_libraries.*[[:space:]]QtHelp[\s/)]',
0399                  'replace "QtHelp" with "${QT_QTHELP_LIBRARY}"');
0400     $issues +=
0401       &checkLine($line,$linecnt,
0402                  'target_link_libraries.*[[:space:]]QtWebKit[\s/)]',
0403                  'replace "QtWebKit" with "${QT_QTWEBKIT_LIBRARY}"');
0404     $issues +=
0405       &checkLine($line,$linecnt,
0406                  'target_link_libraries.*[[:space:]]QtXmlPatterns[\s/)]',
0407                  'replace "QtXmlPatterns" with "${QT_QTXMLPATTERNS_LIBRARY}"');
0408 
0409     $issues +=
0410       &checkLine($line,$linecnt,
0411                  'target_link_libraries.*[[:space:]]QtMultimedia[\s/)]',
0412                  'replace "QtMultimedia" with "${QT_QTMULTIMEDIA_LIBRARY}"');
0413 
0414 
0415     # kdegames variables
0416     if (! $in_kdegames) {
0417       $issues +=
0418         &checkLine($line,$linecnt,
0419                    'target_link_libraries.*[[:space:]]kdegames[\s/)]',
0420                    'replace "kdegames" with "${KDEGAMES_LIBRARY}"');
0421     }
0422 
0423     $issues +=
0424       &checkLine($line,$linecnt,
0425                  'install.*\([[:space:]]FILES[[:space:]].*\.desktop\s*DESTINATION\s*\$\{XDG_APPS_INSTALL_DIR}[\s/)]',
0426                  'replace "FILES" with "PROGRAMS"');
0427 
0428     # kdelibs variables
0429     if (! $in_kdelibs) {
0430       $issues +=
0431         &checkLine($line,$linecnt,
0432                    'target_link_libraries.*[[:space:]]kdeui[\s/)]',
0433                    'replace "kdeui" with "${KDE4_KDEUI_LIBS}"');
0434       $issues +=
0435         &checkLine($line,$linecnt,
0436                    'target_link_libraries.*[[:space:]]kio[\s/)]',
0437                    'replace "kio" with "${KDE4_KIO_LIBS}"');
0438       $issues +=
0439         &checkLine($line,$linecnt,
0440                    'target_link_libraries.*[[:space:]]kdesu[\s/)]',
0441                    'replace "kdesu" with "${KDE4_KDESU_LIBS}"');
0442 
0443       $issues +=
0444         &checkLine($line,$linecnt,
0445                    'target_link_libraries.*[[:space:]]khtml[\s/)]',
0446                    'replace "khtml" with "${KDE4_KHTML_LIBS}"');
0447       $issues +=
0448         &checkLine($line,$linecnt,
0449                    'target_link_libraries.*[[:space:]]kparts[\s/)]',
0450                    'replace "kparts" with "${KDE4_KPARTS_LIBS}"');
0451 
0452       $issues +=
0453         &checkLine($line,$linecnt,
0454                    'target_link_libraries.*[[:space:]]kde3support[\s/)]',
0455                    'replace "kde3support" with "${KDE4_KDE3SUPPORT_LIBS}"');
0456 
0457       $issues +=
0458         &checkLine($line,$linecnt,
0459                    'target_link_libraries.*[[:space:]]kutils[\s/)]',
0460                    'replace "kutils" with "${KDE4_KUTILS_LIBS}"');
0461 
0462       $issues +=
0463         &checkLine($line,$linecnt,
0464                    'target_link_libraries.*[[:space:]]kdnssd[\s/)]',
0465                    'replace "kdnssd" with "${KDE4_KDNSSD_LIBS}"');
0466 
0467       $issues +=
0468         &checkLine($line,$linecnt,
0469                    'target_link_libraries.*[[:space:]]knewstuff2[\s/)]',
0470                    'replace "knewstuff2" with "${KDE4_KNEWSTUFF2_LIBS}"');
0471 
0472       $issues +=
0473         &checkLine($line,$linecnt,
0474                    'target_link_libraries.*[[:space:]]knewstuff3[\s/)]',
0475                    'replace "knewstuff3" with "${KDE4_KNEWSTUFF3_LIBS}"');
0476 
0477       $issues +=
0478         &checkLine($line,$linecnt,
0479                    'target_link_libraries.*[[:space:]]knotifyconfig[\s/)]',
0480                    'replace "knotifyconfig" with "${KDE4_KNOTIFYCONFIG_LIBS}"');
0481 
0482       $issues +=
0483         &checkLine($line,$linecnt,
0484                    'target_link_libraries.*[[:space:]]threadweaver[\s/)]',
0485                    'replace "threadweaver" with "${KDE4_THREADWEAVER_LIBRARIES}"');
0486 
0487       $issues +=
0488         &checkLine($line,$linecnt,
0489                    'target_link_libraries.*[[:space:]]krosscore[\s/)]',
0490                    'replace "krosscore" with "${KDE4_KROSSCORE_LIBS}"');
0491 
0492       $issues +=
0493         &checkLine($line,$linecnt,
0494                    'target_link_libraries.*[[:space:]]krossui[\s/)]',
0495                    'replace "krossui" with "${KDE4_KROSSUI_LIBS}"');
0496 
0497       $issues +=
0498         &checkLine($line,$linecnt,
0499                    'target_link_libraries.*[[:space:]]phonon[\s/)]',
0500                    'replace "phonon" with "${PHONON_LIBRARY}"');
0501 
0502       $issues +=
0503         &checkLine($line,$linecnt,
0504                    'target_link_libraries.*[[:space:]]kaudiodevicelist[\s/)]',
0505                    'replace "kaudiodevicelist" with "${KDE4_KAUDIODEVICELIST_LIBS}"');
0506 
0507       $issues +=
0508         &checkLine($line,$linecnt,
0509                    'target_link_libraries.*[[:space:]]solidifaces[\s/)]',
0510                    'replace "solidifaces" with "${KDE4_SOLIDIFACES_LIBS}"');
0511 
0512       $issues +=
0513         &checkLine($line,$linecnt,
0514                    'target_link_libraries.*[[:space:]]solid[\s/)]',
0515                    'replace "solid" with "${KDE4_SOLID_LIBS}"');
0516 
0517       $issues +=
0518         &checkLine($line,$linecnt,
0519                    'target_link_libraries.*[[:space:]]ktexteditor[\s/)]',
0520                    'replace "ktexteditor" with "${KDE4_KTEXTEDITOR_LIBS}"');
0521 
0522       $issues +=
0523         &checkLine($line,$linecnt,
0524                    'target_link_libraries.*[[:space:]]kfile[\s/)]',
0525                    'replace "kfile" with "${KDE4_KFILE_LIBS}"');
0526 
0527       $issues +=
0528         &checkLine($line,$linecnt,
0529                    'target_link_libraries.*[[:space:]]knepomuk[\s/)]',
0530                    'replace "knepomuk" with "${KDE4_KNEPOMUK_LIBS}"');
0531 
0532       $issues +=
0533         &checkLine($line,$linecnt,
0534                    'target_link_libraries.*[[:space:]]nepomukquery[\s/)]',
0535                    'replace "nepomukquery" with "${NEPOMUK_QUERY_LIBRARIES}"');
0536 
0537       $issues +=
0538         &checkLine($line,$linecnt,
0539                    'target_link_libraries.*[[:space:]]nepomukutils[\s/)]',
0540                    'replace "nepomukutils" with "${NEPOMUK_UTILS_LIBRARIES}"');
0541 
0542 
0543       $issues +=
0544         &checkLine($line,$linecnt,
0545                    'target_link_libraries.*[[:space:]]kmetadata[\s/)]',
0546                    'replace "kmetadata" with "${KDE4_KMETADATA_LIBS}"');
0547 
0548       $issues +=
0549         &checkLine($line,$linecnt,
0550                    'target_link_libraries.*[[:space:]]kjs[\s/)]',
0551                    'replace "kjs" with "${KDE4_KJS_LIBS}"');
0552 
0553       $issues +=
0554         &checkLine($line,$linecnt,
0555                    'target_link_libraries.*[[:space:]]kjsapi[\s/)]',
0556                    'replace "kjsapi" with "${KDE4_KJSAPI_LIBS}"');
0557 
0558       $issues +=
0559         &checkLine($line,$linecnt,
0560                    'target_link_libraries.*[[:space:]]kformula[\s/)]',
0561                    'replace "kformula" with "${KDE4_KFORMULA_LIBS}"');
0562 
0563       $issues +=
0564         &checkLine($line,$linecnt,
0565                    'target_link_libraries.*[[:space:]]plasma[\s/)]',
0566                    'replace "plasma" with "${KDE4_PLASMA_LIBS}"');
0567 
0568       $issues +=
0569         &checkLine($line,$linecnt,
0570                    'target_link_libraries.*[[:space:]]kunitconversion[\s/)]',
0571                    'replace "kunitconversion" with "${KDE4_KUNITCONVERSION_LIBS}"');
0572 
0573       $issues +=
0574         &checkLine($line,$linecnt,
0575                    'target_link_libraries.*[[:space:]]kdewebkit[\s/)]',
0576                    'replace "kdewebkit" with "${KDE4_KDEWEBKIT_LIBS}"');
0577 
0578       $issues +=
0579         &checkLine($line,$linecnt,
0580                    'target_link_libraries.*[[:space:]]kprintutils[\s/)]',
0581                    'replace "kprintutils" with "${KDE4_KPRINTUTILS_LIBS}"');
0582 
0583       $issues +=
0584         &checkLine($line,$linecnt,
0585                    'target_link_libraries.*[[:space:]]kcmutils[\s/)]',
0586                    'replace "kcmutils" with "${KDE4_KCMUTILS_LIBS}"');
0587 
0588       $issues +=
0589         &checkLine($line,$linecnt,
0590                    'target_link_libraries.*[[:space:]]kemoticons[\s/)]',
0591                    'replace "kemoticons" with "${KDE4_KEMOTICONS_LIBS}"');
0592 
0593       $issues +=
0594         &checkLine($line,$linecnt,
0595                    'target_link_libraries.*[[:space:]]kidletime[\s/)]',
0596                    'replace "kidletime" with "${KDE4_KIDLETIME_LIBS}"');
0597 
0598     }
0599 
0600     # kdepimlibs variables
0601     if (! $in_kdelibs && ! $in_kdepimlibs) {
0602       $issues +=
0603         &checkLine($line,$linecnt,
0604                    'target_link_libraries.*[[:space:]]akonadi-kde[\s/)]',
0605                    'replace "akonadi-kde" with "${KDEPIMLIBS_AKONADI_LIBS}"');
0606 
0607       $issues +=
0608         &checkLine($line,$linecnt,
0609                    'target_link_libraries.*[[:space:]]akonadi-calendar[\s/)]',
0610                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_CALENDAR_LIBS}"');
0611 
0612       $issues +=
0613         &checkLine($line,$linecnt,
0614                    'target_link_libraries.*[[:space:]]akonadi-contact[\s/)]',
0615                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_CONTACT_LIBS}"');
0616 
0617       $issues +=
0618         &checkLine($line,$linecnt,
0619                    'target_link_libraries.*[[:space:]]akonadi-kabc[\s/)]',
0620                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_KABC_LIBS}"');
0621 
0622       $issues +=
0623         &checkLine($line,$linecnt,
0624                    'target_link_libraries.*[[:space:]]akonadi-kcal[\s/)]',
0625                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_KCAL_LIBS}"');
0626 
0627       $issues +=
0628         &checkLine($line,$linecnt,
0629                    'target_link_libraries.*[[:space:]]akonadi-kmime[\s/)]',
0630                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_KMIME_LIBS}"');
0631 
0632       $issues +=
0633         &checkLine($line,$linecnt,
0634                    'target_link_libraries.*[[:space:]]akonadi-notes[\s/)]',
0635                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_NOTES_LIBS}"');
0636 
0637       $issues +=
0638         &checkLine($line,$linecnt,
0639                    'target_link_libraries.*[[:space:]]akonadi-socialutils[\s/)]',
0640                    'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_SOCIALUTILS_LIBS}"');
0641 
0642       $issues +=
0643         &checkLine($line,$linecnt,
0644                    'target_link_libraries.*[[:space:]]gpgmepp[\s/)]',
0645                    'replace "gpgmepp" with "${KDEPIMLIBS_GPGMEPP_LIBS}"');
0646 
0647       $issues +=
0648         &checkLine($line,$linecnt,
0649                    'target_link_libraries.*[[:space:]]kabc[\s/)]',
0650                    'replace "kabc" with "${KDEPIMLIBS_KABC_LIBS}"');
0651 
0652       $issues +=
0653         &checkLine($line,$linecnt,
0654                    'target_link_libraries.*[[:space:]]kalarmcal[\s/)]',
0655                    'replace "kcalutils" with "${KDEPIMLIBS_KALARMCAL_LIBS}"');
0656 
0657       $issues +=
0658         &checkLine($line,$linecnt,
0659                    'target_link_libraries.*[[:space:]]kblog[\s/)]',
0660                    'replace "kblog" with "${KDEPIMLIBS_KBLOG_LIBS}"');
0661 
0662       $issues +=
0663         &checkLine($line,$linecnt,
0664                    'target_link_libraries.*[[:space:]]kcal[\s/)]',
0665                    'replace "kcal" with "${KDEPIMLIBS_KCAL_LIBS}"');
0666 
0667       $issues +=
0668         &checkLine($line,$linecnt,
0669                    'target_link_libraries.*[[:space:]]kcalcore[\s/)]',
0670                    'replace "kcalcore" with "${KDEPIMLIBS_KCALCORE_LIBS}"');
0671 
0672       $issues +=
0673         &checkLine($line,$linecnt,
0674                    'target_link_libraries.*[[:space:]]kcalutils[\s/)]',
0675                    'replace "kcalutils" with "${KDEPIMLIBS_KCALUTILS_LIBS}"');
0676 
0677       $issues +=
0678         &checkLine($line,$linecnt,
0679                    'target_link_libraries.*[[:space:]]kholidays[\s/)]',
0680                    'replace "kholidays" with "${KDEPIMLIBS_KHOLIDAYS_LIBS}"');
0681 
0682       $issues +=
0683         &checkLine($line,$linecnt,
0684                    'target_link_libraries.*[[:space:]]kimap[\s/)]',
0685                    'replace "kimap" with "${KDEPIMLIBS_KIMAP_LIBS}"');
0686 
0687       $issues +=
0688         &checkLine($line,$linecnt,
0689                    'target_link_libraries.*[[:space:]]kldap[\s/)]',
0690                    'replace "kldap" with "${KDEPIMLIBS_KLDAP_LIBS}"');
0691 
0692       $issues +=
0693         &checkLine($line,$linecnt,
0694                    'target_link_libraries.*[[:space:]]kmbox[\s/)]',
0695                    'replace "kmbox" with "${KDEPIMLIBS_KMBOX_LIBS}"');
0696 
0697       $issues +=
0698         &checkLine($line,$linecnt,
0699                    'target_link_libraries.*[[:space:]]kmime[\s/)]',
0700                    'replace "kmime" with "${KDEPIMLIBS_KMIME_LIBS}"');
0701 
0702       $issues +=
0703         &checkLine($line,$linecnt,
0704                    'target_link_libraries.*[[:space:]]kontactinterface[\s/)]',
0705                    'replace "kontactinterface" with "${KDEPIMLIBS_KONTACTINTERFACE_LIBS}"');
0706 
0707       $issues +=
0708         &checkLine($line,$linecnt,
0709                    'target_link_libraries.*[[:space:]]kpimidentities[\s/)]',
0710                    'replace "kpimidentities" with "${KDEPIMLIBS_KPIMIDENTITIES_LIBS}"');
0711 
0712       $issues +=
0713         &checkLine($line,$linecnt,
0714                    'target_link_libraries.*[[:space:]]kpimtextedit[\s/)]',
0715                    'replace "kpimtextedit" with "${KDEPIMLIBS_KPIMTEXTEDIT_LIBS}"');
0716 
0717       $issues +=
0718         &checkLine($line,$linecnt,
0719                    'target_link_libraries.*[[:space:]]kpimutils[\s/)]',
0720                    'replace "kpimutils" with "${KDEPIMLIBS_KPIMUTILS_LIBS}"');
0721 
0722       $issues +=
0723         &checkLine($line,$linecnt,
0724                    'target_link_libraries.*[[:space:]]kresources[\s/)]',
0725                    'replace "kresources" with "${KDEPIMLIBS_KRESOURCES_LIBS}"');
0726 
0727       $issues +=
0728         &checkLine($line,$linecnt,
0729                    'target_link_libraries.*[[:space:]]ktnef[\s/)]',
0730                    'replace "ktnef" with "${KDEPIMLIBS_KTNEF_LIBS}"');
0731 
0732       $issues +=
0733         &checkLine($line,$linecnt,
0734                    'target_link_libraries.*[[:space:]]kxmlrpcclient[\s/)]',
0735                    'replace "kxmlrpcclient" with "${KDEPIMLIBS_KXMLRPCCLIENT_LIBS}"');
0736 
0737       $issues +=
0738         &checkLine($line,$linecnt,
0739                    'target_link_libraries.*[[:space:]]mailtransport[\s/)]',
0740                    'replace "mailtransport" with "${KDEPIMLIBS_MAILTRANSPORT_LIBS}"');
0741 
0742       $issues +=
0743         &checkLine($line,$linecnt,
0744                    'target_link_libraries.*[[:space:]]microblog[\s/)]',
0745                    'replace "microblog" with "${KDEPIMLIBS_MICROBLOG_LIBS}"');
0746 
0747       $issues +=
0748         &checkLine($line,$linecnt,
0749                    'target_link_libraries.*[[:space:]]qgpgme[\s/)]',
0750                    'replace "qgpgme" with "${KDEPIMLIBS_QGPGME_LIBS}"');
0751 
0752       $issues +=
0753         &checkLine($line,$linecnt,
0754                    'target_link_libraries.*[[:space:]]syndication[\s/)]',
0755                    'replace "syndication" with "${KDEPIMLIBS_SYNDICATION_LIBS}"');
0756     }
0757 
0758     if ($line !~ m+(Qt4|IOKit|KdeSubversion|KDE4|KDE4Internal|KDEWIN32|KdepimLibs|kdevplatform|Carbon|Gpgme|Perl|Wcecompat)+ && $in !~ m+/(examples|qtonly)/+) {
0759       $issues +=
0760        &checkLine($line,$linecnt,
0761                    '^\s*[Ff][Ii][Nn][Dd]_[Pp][Aa][Cc][Kk][Aa][Gg][Ee]\s*\(\s*[A-Za-z0-9_]*\sREQUIRED\s*\)',
0762                   'Do not use the REQUIRED keyword with find_package()');
0763     }
0764 
0765     my($subdir);
0766     if ($line =~ m+macro_optional_add_subdirectory\s*\(\s*(\S*)\s*\)+) {
0767       $subdir = $1;
0768       if (!&canBeOptional($subdir) || ($top_of_module && ($in_kdelibs || $in_kdepimlibs))) {
0769         if (!&mustBeOptional($subdir)) {
0770           $issues++;
0771           &printIssue($line,$linecnt,"Replace macro_optional_add_subdirectory($subdir) with add_subdirectory($subdir)");
0772         }
0773       }
0774     }
0775     if ($line =~ m+^\s*add_subdirectory\s*\(\s*(\S*)\s*\)+) {
0776       $subdir = $1;
0777       if (&mustBeOptional($subdir)) {
0778         $issues++;
0779         &printIssue($line,$linecnt,"Replace add_subdirectory($subdir) with macro_optional_add_subdirectory($subdir)");
0780       }
0781     }
0782     $prevline = $line;
0783   }
0784 
0785   #look for "missing" stuff
0786   my($in_exec)=0;
0787   my($has_project)=0;
0788   my($mlf)=0;
0789   my($has_display_log)=0;
0790   foreach $line (@lines) {
0791     chomp($line);
0792     $line =~ s/#.*$//; #remove comments
0793     next if ($line =~ m/^[[:space:]]$/); #skip blank lines
0794     $in_exec = 1
0795       if ($line =~ m/add_(|kdeinit_)executable[[:space:]]*\(/i);
0796     if ($line =~ m/[Pp][Rr][Oo][Jj][Ee][Cc][Tt]/) {
0797       $has_project=1;
0798     }
0799     if ($line =~ m/macro_log_feature\(\s*([A-Z0-9_]*).*\)/i) {
0800       $mlf++;
0801     }
0802     if ($line =~ m/macro_display_feature_log/i) {
0803       $has_display_log=1;
0804     }
0805   }
0806   if (! $has_project && $top_of_project && $in_exec) {
0807     $issues++;
0808     &printIssue("",-1,"Missing a PROJECT() command");
0809   }
0810   if ($top_of_module && $mlf > 0 && $has_display_log == 0) {
0811     $issues++;
0812     &printIssue("",-1,"Missing macro_display_feature_log() command");
0813   }
0814   #if (!$top_of_module && $has_display_log == 1 && $in !~ m+/qtonly/+) {
0815   #  $issues++;
0816   #  &printIssue("",-1,"Do not put macro_display_feature_log() in a subdir CMakeLists.txt");
0817   #}
0818   if ($nop > $ncp) {
0819     $issues++;
0820     &printIssue("",-1,"Mismatched parens (too many open parens $nop to $ncp)");
0821   }
0822   if ($nop < $ncp) {
0823     $issues++;
0824     &printIssue("",-1,"Mismatched parens (too many close parens $nop to $ncp)");
0825   }
0826   if ($nob > $ncb) {
0827     $issues++;
0828     &printIssue("",-1,"Mismatched braces (too many open braces $nob to $ncb)");
0829   }
0830   if ($nob < $ncb) {
0831     $issues++;
0832     &printIssue("",-1,"Mismatched braces (too many close braces $nob to $ncb)");
0833   }
0834 
0835   #missing macro_log_feature()
0836   foreach $pack ( keys %optpacks ) {
0837     if ($optpacks{$pack}{'log'} == 0) {
0838       $issues++;
0839       &printIssue("",-1,"Missing macro_log_feature($pack)");
0840     }
0841   }
0842 
0843   close(IN);
0844   return $issues;
0845 }
0846 
0847 sub checkLine {
0848   my($line,$cnt,$regex,$explain) = @_;
0849   if ($line =~ m/$regex/i) {
0850     &printIssue($line,$cnt,$explain);
0851     return 1;
0852   }
0853   return 0;
0854 }
0855 
0856 sub printIssue {
0857   my($line,$cnt,$explain) = @_;
0858   if ($line) {
0859     print "\tline#$cnt: $explain\n";
0860     print "\t=>$line\n" if ($verbose);
0861   } else {
0862     print "\t$explain\n";
0863   }
0864 }
0865 
0866 sub canBeOptional {
0867   my($guy) = @_;
0868 
0869   my($ret) = 1;
0870   $ret = 0
0871     if ($guy =~ m/^lib/ ||
0872         $guy =~ m/lib$/ ||
0873         $guy =~ m/^cmake$/
0874        );
0875   return $ret;
0876 }
0877 
0878 sub mustBeOptional {
0879   my($guy) = @_;
0880 
0881   my($ret) = 0;
0882   $ret = 1
0883     if ($guy =~ m/^doc$/);
0884   return $ret;
0885 }
0886 
0887 #==============================================================================
0888 # Help function: print help message and exit.
0889 sub Help {
0890   &Version();
0891   print "Check KDE CMakeLists.txt files for common errors.\n\n";
0892   print "Usage: $Prog [OPTIONS] FILES\n";
0893   print "  --help             display help message and exit\n";
0894   print "  --version          display version information and exit\n";
0895   print "\n";
0896   exit 0 if $help;
0897 }
0898 
0899 # Version function: print the version number and exit.
0900 sub Version {
0901   print "$Prog, version $Version\n";
0902   exit 0 if $version;
0903 }
0904 
0905 __END__