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

0001 #!/usr/bin/perl -w
0002 
0003 # Modifies CMakeLists.txt in the current directory, to install forwarding headers
0004 # using ecm_generate_headers() instead of a manual list of lowercase headers.
0005 #
0006 # Remember to adjust things manually when using namespaced headers: 
0007 #  - add PREFIX to the ecm_generate_headers call
0008 #  - add that "/Prefix" to the directory in target_include_directories(... INTERFACE ...)
0009 #  - add that lowercase prefix to the install dir for lowercase headers
0010 
0011 use strict;
0012 my %foundclasses = ();
0013 my $name;
0014 my $basename;
0015 my $file = "CMakeLists.txt";
0016 my $tid_done;
0017 my $in_install_files;
0018 my $devel_done;
0019 my $install_dir_done;
0020 my $modified = 0;
0021 open(my $FILE, "<", $file) || die;
0022 
0023 my @l = map {
0024   my $orig = $_;
0025 
0026   if (!/ALIAS/ && /add_library\s*\(\s*(\w+)/) {
0027     $name = $1;
0028     $basename = $1 if ($name =~ m/^KF5(\w+)/);
0029   }
0030   if (/BASE_NAME (\w+)/) {
0031     $basename = $1;
0032   }
0033 
0034   if (/target_link_libraries/ && !defined $tid_done) {
0035     $tid_done = 1;
0036     die "didn't find a add_library line before target_link_libraries!" unless defined $name;
0037     $_ = "target_include_directories($name INTERFACE \"\$<INSTALL_INTERFACE:\${INCLUDE_INSTALL_DIR}/$basename>\")\n\n$_";
0038   }
0039 
0040   if (/install.\s*FILES\s*$/ || defined $in_install_files) {
0041     s/install\( FILES/install\(FILES/;
0042     $in_install_files = 1;
0043     if (/^\s*(\w+\/)?(\w+\.h)/ && !/export\.h/ && !/_p\.h/) {
0044       my $origline = $_;
0045       my $subdir = defined($1) ? $1 : "";
0046       my $header = $2;
0047       $subdir =~ s,/$,,;
0048       my $foundclass;
0049       my $multipleclasses = "";
0050       my $path = $subdir eq "" ? $header : "$subdir/$header";
0051       open(F, "$path") || print STDERR "ERROR: $path not found\n";
0052       while (<F>) {
0053         if (/^class .*(?:EXPORT|EXPORT_NOISE) \s*(\w+)/) {
0054           if (lc($1).".h" eq lc($header)) {
0055             $foundclass = $1;
0056           }
0057           $multipleclasses .= $1 . " ";
0058         }
0059         if (/^\s*namespace \s*(\w+)/ || /^typedef \w+ (\w+)/) {
0060           if (lc($1).".h" eq lc($header)) {
0061             $foundclass = $1;
0062             $multipleclasses .= $foundclass . " ";
0063           }
0064         }
0065       }
0066       close(F);
0067       if (defined $foundclass) {
0068         $foundclasses{$subdir} = "" unless defined $foundclasses{$subdir};
0069         $foundclasses{$subdir} .= "  " . $foundclass . "\n";
0070         #print STDERR "inserting into foundclasses{$subdir} : " . $foundclasses{$subdir} . "\n";
0071         $_ = "";
0072       } else {
0073         $multipleclasses =~ s/ $//; # remove trailing slash
0074         if ($multipleclasses =~ / /) {
0075           print STDERR "WARNING: multiple exported classes found in $path: $multipleclasses\n";
0076         } else {
0077           print STDERR "WARNING: No exported class or namespace found in $path, check for a template maybe?\n";
0078         }
0079         $_ = $origline;
0080       }
0081     }
0082   }
0083 
0084   if (/COMPONENT Devel/ && !defined $devel_done) {
0085     $devel_done = 1;
0086     undef $in_install_files;
0087     die unless defined $basename;
0088     $_ = "  \${${basename}_HEADERS}\n" . $_;
0089     s/\${INCLUDE_INSTALL_DIR} /\${INCLUDE_INSTALL_DIR}\/$basename /;
0090   }
0091 
0092   if (defined $devel_done && /\)/) {
0093     my $line = $_;
0094     foreach my $subdir (keys %foundclasses) {
0095       print STDERR "writing out classes for subdir '" . $subdir ."'\n";
0096       my $theclasses = $foundclasses{$subdir};
0097       $line .= "ecm_generate_headers(\n$theclasses\n";
0098       if ($subdir ne "") {
0099         $line .= "  RELATIVE $subdir\n";
0100       }
0101       $line .= "  MODULE_NAME $basename\n  REQUIRED_HEADERS ${basename}_HEADERS\n)\n";
0102     }
0103     $_ = $line;
0104     %foundclasses = ();
0105   }
0106 
0107   # happens earlier in the file, but must be last to avoid matching on "COMPONENT Devel"
0108   if (/install.TARGETS/ && !defined $install_dir_done) {
0109     $install_dir_done = 1;
0110     $_ = "<move ecm_generate_headers calls here>\ninstall(DIRECTORY \${CMAKE_CURRENT_BINARY_DIR}/$basename DESTINATION \${INCLUDE_INSTALL_DIR} COMPONENT Devel)\n\n" . $_;
0111   }
0112 
0113   $modified ||= $orig ne $_;
0114   $_;
0115 } <$FILE>;
0116 
0117 if ($modified) {
0118     open (my $OUT, ">", $file);
0119     print $OUT @l;
0120     close ($OUT);
0121 }
0122 
0123