#!/usr/bin/perl -w # Expands the specialised KDE tags in Makefile.in to (hopefully) valid # make syntax. # When called without file parameters, we work recursively on all Makefile.in # in and below the current subdirectory. When called with file parameters, # only those Makefile.in are changed. # The currently supported tags are # # {program}_METASOURCES # where you have a choice of two styles # {program}_METASOURCES = name1.moc name2.moc ... [\] # {program}_METASOURCES = AUTO # The second style requires other tags as well. # # To install icons : # KDE_ICON = iconname iconname2 ... # KDE_ICON = AUTO # # For documentation : # http://developer.kde.org/documentation/other/developer-faq.html # # and more new tags TBD! # # The concept (and base code) for this program came from automoc, # supplied by the following # # Matthias Ettrich (The originator) # Kalle Dalheimer (The original implementator) # Harri Porten # Alex Zepeda # David Faure # Stephan Kulow # Dirk Mueller use Cwd; use File::Find; use File::Basename; # Prototype the functions sub initialise (); sub processMakefile ($); sub updateMakefile (); sub restoreMakefile (); sub removeLine ($$); sub appendLines ($); sub substituteLine ($$); sub findMocCandidates (); sub pruneMocCandidates ($); sub checkMocCandidates (); sub addMocRules (); sub findKcfgFile($); sub tag_AUTOMAKE (); sub tag_META_INCLUDES (); sub tag_METASOURCES (); sub tag_POFILES (); sub tag_DOCFILES (); sub tag_LOCALINSTALL(); sub tag_IDLFILES(); sub tag_UIFILES(); sub tag_KCFGFILES(); sub tag_SUBDIRS(); sub tag_ICON(); sub tag_CLOSURE(); sub tag_NO_UNDEFINED(); sub tag_NMCHECK(); sub tag_DIST(); sub tag_TDEINIT(); # Some global globals... $verbose = 0; # a debug flag $thisProg = "$0"; # This programs name $topdir = cwd(); # The current directory @makefiles = (); # Contains all the files we'll process @foreignfiles = (); $start = (times)[0]; # some stats for testing - comment out for release $version = "v0.2"; $errorflag = 0; $cppExt = "(cpp|cc|cxx|C|c\\+\\+)"; $hExt = "(h|H|hh|hxx|hpp|h\\+\\+)"; $progId = "KDE tags expanded automatically by " . basename($thisProg); $automkCall = "\n"; $printname = ""; # used to display the directory the Makefile is in $use_final = 1; # create code for --enable-final $cleantarget = "clean"; $dryrun = 0; $pathoption = 0; $foreign_libtool = 0; while (defined ($ARGV[0])) { $_ = shift; if (/^--version$/) { print STDOUT "\n"; print STDOUT basename($thisProg), " $version\n", "This is really free software, unencumbered by the GPL.\n", "You can do anything you like with it except sueing me.\n", "Copyright 1998 Kalle Dalheimer \n", "Concept, design and unnecessary questions about perl\n", " by Matthias Ettrich \n\n", "Making it useful by Stephan Kulow and\n", "Harri Porten \n", "Updated (Feb-1999), John Birch \n", "Fixes and Improvements by Dirk Mueller \n", "Current Maintainer Stephan Kulow\n\n"; exit 0; } elsif (/^--verbose$|^-v$/) { $verbose = 1; # Oh is there a problem...? } elsif (/^(?:-p|--path=)(.+)$/) { my $p = $1; $thisProg = $p . "/". basename($thisProg); warn ("$thisProg doesn't exist\n") if (!(-f $thisProg)); $thisProg .= " -p".$p; $pathoption=1; } elsif (/^--help$|^-h$/) { print STDOUT "Usage $thisProg [OPTION] ... [dir/Makefile.in]...\n", "\n", "Patches dir/Makefile.in generated by automake\n", "(where dir can be an absolute or relative directory name)\n", "\n", " -v, --verbose verbosely list files processed\n", " -h, --help print this help, then exit\n", " --version print version number, then exit\n", " -p, --path= use the path to am_edit if the path\n", " called from is not the one to be used\n", " --no-final don't patch for --enable-final\n"; exit 0; } elsif (/^--no-final$/) { $use_final = 0; $thisProg .= " --no-final"; } elsif (/^--foreign-libtool$/) { $foreign_libtool = 1; $thisProg .= " --foreign-libtool"; } elsif (/^-n$/) { $dryrun = 1; } else { # user selects what input files to check # add full path if relative path is given $_ = cwd()."/".$_ if (! /^\//); print "User wants $_\n" if ($verbose); push (@makefiles, $_); } } if ($thisProg =~ /^\// && !$pathoption ) { print STDERR "Illegal full pathname call performed...\n", "The call to \"$thisProg\"\nwould be inserted in some Makefile.in.\n", "Please use option --path.\n"; exit 1; } # Only scan for files when the user hasn't entered data if (!@makefiles) { print STDOUT "Scanning for Makefile.in\n" if ($verbose); find (\&add_makefile, cwd()); #chdir('$topdir'); } else { print STDOUT "Using input files specified by user\n" if ($verbose); } foreach $makefile (sort(@makefiles)) { processMakefile ($makefile); last if ($errorflag); } # Just some debug statistics - comment out for release as it uses printf. printf STDOUT "Time %.2f CPU sec\n", (times)[0] - $start if ($verbose); exit $errorflag; # causes make to fail if erroflag is set #----------------------------------------------------------------------------- # In conjunction with the "find" call, this builds the list of input files sub add_makefile () { push (@makefiles, $File::Find::name) if (/Makefile.in$/); } #----------------------------------------------------------------------------- # Processes a single make file # The parameter contains the full path name of the Makefile.in to use sub processMakefile ($) { # some useful globals for the subroutines called here local ($makefile) = @_; local @headerdirs = ('.'); local $haveAutomocTag = 0; local $MakefileData = ""; local $cxxsuffix = "KKK"; local @programs = (); # lists the names of programs and libraries local $program = ""; local @tdeinits = (); # lists the tdeinit targets local %realObjs = (); # lists the objects compiled into $program local %sources = (); # lists the sources used for $program local %finalObjs = (); # lists the objects compiled when final local %realname = (); # the binary name of program variable local %idlfiles = (); # lists the idl files used for $program local %globalmocs = ();# list of all mocfiles (in %mocFiles format) local %important = (); # list of files to be generated asap local %uiFiles = (); local %kcfgFiles = (); local $allidls = ""; local $idl_output = "";# lists all idl generated files for cleantarget local $ui_output = "";# lists all uic generated files for cleantarget local $kcfg_output = "";# lists all kcfg generated files for cleantarget local %dependmocs = (); local $metasourceTags = 0; local $dep_files = ""; local $dep_finals = ""; local %target_adds = (); # the targets to add local %rule_adds = (); local $kdelang = ""; local @cleanfiles = (); local $cleanMoc = ""; local $closure_output = ""; local %varcontent = (); $makefileDir = dirname($makefile); chdir ($makefileDir); $printname = $makefile; $printname =~ s/^\Q$topdir\E\///; $makefile = basename($makefile); print STDOUT "Processing makefile $printname\n" if ($verbose); # Setup and see if we need to do this. return if (!initialise()); tag_AUTOMAKE (); # Allows a "make" to redo the Makefile.in tag_META_INCLUDES (); # Supplies directories for src locations foreach $program (@programs) { $sources_changed{$program} = 0; $dependmocs{$program} = ""; $important{$program} = ""; tag_IDLFILES(); # Sorts out idl rules tag_NO_UNDEFINED(); tag_CLOSURE(); tag_NMCHECK(); tag_UIFILES(); # Sorts out ui rules tag_KCFGFILES(); # Sorts out kcfg rules tag_METASOURCES (); # Sorts out the moc rules if ($sources_changed{$program}) { my $lookup = $program . '_SOURCES\s*=[ \t]*(.*)'; if($program =~ /libtdeinit_(.*)/) { my $prog = $1; substituteLine($prog . '_SOURCES\s*=[ \t]*(.*)', "${prog}_SOURCES = ${prog}_dummy.$cxxsuffix\n" . "libtdeinit_${prog}_SOURCES = " . $sources{$program}); $sources{$prog} = "${prog}_dummy.$cxxsuffix"; } else { substituteLine($lookup, "$program\_SOURCES=" . $sources{$program}); } } if ($important{$program}) { local %source_dict = (); for $source (split(/[\034\s]+/, $sources{$program})) { $source_dict{$source} = 1; } for $source (@cleanfiles) { $source_dict{$source} = 0; } for $source (keys %source_dict) { next if (!$source); if ($source_dict{$source}) { # sanity check if (! -f $source) { print STDERR "Error: $source is listed in a _SOURCE line in $printname, but doesn't exist yet. Put it in DISTCLEANFILES!\n"; } else { $target_adds{"\$(srcdir)/$source"} .= $important{$program}; } } } } } if ($cleanMoc) { # Always add dist clean tag # Add extra *.moc.cpp files created for USE_AUTOMOC because they # aren't included in the normal *.moc clean rules. appendLines ("$cleantarget-metasources:\n\t-rm -f $cleanMoc\n"); $target_adds{"$cleantarget-am"} .= "$cleantarget-metasources "; } tag_DIST() unless ($kdeopts{"noautodist"}); if ($idl_output) { appendLines ("$cleantarget-idl:\n\t-rm -f $idl_output\n"); $target_adds{"$cleantarget-am"} .= "$cleantarget-idl "; } if ($ui_output) { appendLines ("$cleantarget-ui:\n\t-rm -f $ui_output\n"); $target_adds{"$cleantarget-am"} .= "$cleantarget-ui "; } if ($kcfg_output) { appendLines ("$cleantarget-kcfg:\n\t-rm -f $kcfg_output\n"); $target_adds{"$cleantarget-am"} .= "$cleantarget-kcfg "; } if ($closure_output) { appendLines ("$cleantarget-closures:\n\t-rm -f $closure_output\n"); $target_adds{"$cleantarget-am"} .= "$cleantarget-closures "; } if ($MakefileData =~ /\nKDE_LANG\s*=\s*(\S*)\s*\n/) { $kdelang = '$(KDE_LANG)' } else { $kdelang = ''; } tag_POFILES (); # language rules for po directory tag_DOCFILES (); # language rules for doc directories tag_LOCALINSTALL(); # add $(DESTDIR) before all kde_ dirs tag_ICON(); tag_SUBDIRS(); my $tmp = "force-reedit:\n"; $tmp .= "\t$automkCall\n\tcd \$(top_srcdir) && perl $thisProg $printname\n\n"; appendLines($tmp); make_bcheck_target(); make_meta_classes(); tag_COMPILE_FIRST(); tag_FINAL() if (!$kdeopts{"nofinal"}); my $final_lines = "final:\n\t\$(MAKE) "; my $final_install_lines = "final-install:\n\t\$(MAKE) "; my $nofinal_lines = "no-final:\n\t\$(MAKE) "; my $nofinal_install_lines = "no-final-install:\n\t\$(MAKE) "; foreach $program (@programs) { my $lookup = $program . '_OBJECTS\s*=[ \t]*.*'; my $new = ""; my @list = split(/[\034\s]+/, $realObjs{$program}); if (!$kdeopts{"nofinal"} && @list > 1 && $finalObjs{$program}) { $new .= "$program\_final\_OBJECTS = " . $finalObjs{$program}; $new .= "\n$program\_nofinal\_OBJECTS = " . $realObjs{$program}; $new .= "\n\@KDE_USE_FINAL_FALSE\@$program\_OBJECTS = \$($program\_nofinal\_OBJECTS)"; $new .= "\n\@KDE_USE_FINAL_TRUE\@$program\_OBJECTS = \$($program\_final\_OBJECTS)"; $final_lines .= "$program\_OBJECTS=\"\$($program\_final_OBJECTS)\" "; $final_install_lines .= "$program\_OBJECTS=\"\$($program\_final_OBJECTS)\" "; $nofinal_lines .= "$program\_OBJECTS=\"\$($program\_nofinal\_OBJECTS)\" "; $nofinal_install_lines .= "$program\_OBJECTS=\"\$($program\_nofinal_OBJECTS)\" "; } else { $new = "$program\_OBJECTS = " . $realObjs{$program}; } if($MakefileData =~ m/\n$lookup/) { substituteLine ($lookup, $new); } else { appendLines("$new\n"); } } appendLines($final_lines . "all-am\n"); appendLines($final_install_lines . "install-am\n"); appendLines($nofinal_lines . "all-am\n"); appendLines($nofinal_install_lines . "install-am\n"); my $lookup = '(\@\S+\@)?DEP_FILES\s*=[ \t]*(.*)'; if ($MakefileData =~ /\n$lookup/) { my $condition = $1; my $depfiles = $2; my $workfiles; if ($dep_finals) { # Add the conditions on every line, since # there may be line continuations in the list. $workfiles = "$dep_files $dep_finals $depfiles"; $workfiles =~ s/\034/\034$condition\@KDE_USE_FINAL_TRUE\@\t/g; $lines = "$condition\@KDE_USE_FINAL_TRUE\@DEP_FILES = $workfiles\n"; $workfiles = "$dep_files $depfiles"; $workfiles =~ s/\034/\034$condition\@KDE_USE_FINAL_FALSE\@\t/g; $lines .= "$condition\@KDE_USE_FINAL_FALSE\@DEP_FILES = $workfiles"; } else { $workfiles = "$dep_files $depfiles"; $workfiles =~ s/\034/\034$condition\t/g; $lines = $condition . "DEP_FILES = $workfiles"; } substituteLine($lookup, $lines); } # new recursive targets $target_adds{ "nmcheck" } .= ""; # always create nmcheck target $target_adds{ "nmcheck-am" } .= "nmcheck"; $lookup = 'RECURSIVE_TARGETS\s*=[ \t]*(.*)'; if ($MakefileData =~ /\n$lookup/) { substituteLine($lookup, "RECURSIVE_TARGETS = $1 nmcheck-recursive bcheck-recursive"); } $cvs_lines = "kde-rpo-clean:\n"; $cvs_lines .= "\t-rm -f *.rpo\n"; appendLines($cvs_lines); $target_adds{"clean"} .= "kde-rpo-clean "; my %target_dels = ("install-data-am" => ""); # some strange people like to do a install-exec, and expect that also # all modules are installed. automake doesn't know this, so we need to move # this here from install-data to install-exec. if ($MakefileData =~ m/\nkde_module_LTLIBRARIES\s*=/) { # $target_adds{"install-exec-am"} .= "install-kde_moduleLTLIBRARIES "; # don't use $target_adds here because we need to append the dependency, not # prepend it. Fixes #44342 , when a module depends on a lib in the same dir # and libtool needs it during relinking upon install (Simon) my $lookup = "install-exec-am:([^\n]*)"; if($MakefileData =~ /\n$lookup\n/) { substituteLine("$lookup", "install-exec-am: $1 install-kde_moduleLTLIBRARIES"); } $target_dels{"install-data-am"} .= "install-kde_moduleLTLIBRARIES "; $target_adds{"install-data-am"} .= " "; } my $lines = ""; foreach $add (keys %target_adds) { my $lookup = quotemeta($add) . ':([^\n]*)'; if ($MakefileData =~ /\n$lookup\n/) { my $newlines = $1; my $oldlines = $lookup; if (defined $target_dels{$add}) { foreach $del (split(' ', $target_dels{$add})) { $newlines =~ s/\s*$del\s*/ /g; } } substituteLine($oldlines, "$add: " . $target_adds{$add} . $newlines); } else { $lines .= "$add: " . $target_adds{$add} . "\n"; } } appendLines($lines) if ($lines); $lines = join("\n", values %rule_adds); appendLines($lines) if ($lines); my $found = 1; while ($found) { if ($MakefileData =~ m/\n(.*)\$\(CXXFLAGS\)(.*)\n/) { my $stuff_before = $1; my $stuff_after = $2; my $lookup = quotemeta("$1\$(CXXFLAGS)$2"); my $replacement = "$1\$(KCXXFLAGS)$2"; $MakefileData =~ s/$lookup/$replacement/; $lookup =~ s/\\\$\\\(CXXFLAGS\\\)/\\\$\\\(KCXXFLAGS\\\)/; $replacement = "$stuff_before\$(KCXXFLAGS) \$(KDE_CXXFLAGS)$stuff_after"; next if ($stuff_before =~ /\$\(KDE_CXXFLAGS\)/ or $stuff_after =~ /\$\(KDE_CXXFLAGS\)/); substituteLine($lookup, $replacement); } else { $found = 0; } } if($foreign_libtool == 0) { $lookup = '(\n[^#].*\$\(LIBTOOL\) --mode=link) (\$\(CXXLD\).*\$\(KCXXFLAGS\))'; if ($MakefileData =~ m/$lookup/ ) { $MakefileData =~ s/$lookup/$1 --tag=CXX $2/; } $lookup = '(\n[^#].*\$\(LIBTOOL\) --mode=compile)\s+(\$\(CXX\)\s+)'; if ($MakefileData =~ m/$lookup/ ) { $MakefileData =~ s/$lookup/$1 --tag=CXX $2/; } } $MakefileData =~ s/\$\(KCXXFLAGS\)/\$\(CXXFLAGS\)/g; $lookup = '(.*)cp -pr \$\$/\$\$file \$\(distdir\)/\$\$file(.*)'; if ($MakefileData =~ m/\n$lookup\n/) { substituteLine($lookup, "$1cp -pr \$\$d/\$\$file \$(distdir)/\$\$file$2"); } # Always update the Makefile.in updateMakefile (); return; } #----------------------------------------------------------------------------- # Beware: This procedure is not complete. E.g. it also parses lines # containing a '=' in rules (for instance setting shell vars). For our # usage this us enough, though. sub read_variables () { while ($MakefileData =~ /\n\s*(\S+)\s*=([^\n]*)/g) { $varcontent{$1} = $2; } } # Check to see whether we should process this make file. # This is where we look for tags that we need to process. # A small amount of initialising on the tags is also done here. # And of course we open and/or create the needed make files. sub initialise () { if (! -r "Makefile.am") { print STDOUT "found Makefile.in without Makefile.am\n" if ($verbose); return 0; } # Checking for files to process... open (FILEIN, $makefile) || die "Can't open $makefileDir/$makefile: $!\n"; # perl bug in 5.8.0: in utf8 mode it badly screws up binmode(FILEIN, ":bytes") if ($] >= 5.008); # Read the file # stat(FILEIN)[7] might look more elegant, but is slower as it # requires stat'ing the file seek(FILEIN, 0, 2); my $fsize = tell(FILEIN); seek(FILEIN, 0, 0); read FILEIN, $MakefileData, $fsize; close FILEIN; print "DOS CRLF within $makefileDir/$makefile!\n" if($MakefileData =~ y/\r//d); # Remove the line continuations, but keep them marked # Note: we lose the trailing spaces but that's ok. # Don't mangle line-leading spaces (usually tabs) # since they're important. $MakefileData =~ s/\\\s*\n/\034/g; # If we've processed the file before... restoreMakefile () if ($MakefileData =~ /$progId/); foreach $dir (@foreignfiles) { if (substr($makefileDir,0,length($dir)) eq $dir) { return 0; } } %kdeopts = (); $kdeopts{"foreign"} = 0; $kdeopts{"qtonly"} = 0; $kdeopts{"noautodist"} = 0; $kdeopts{"foreign-libtool"} = $foreign_libtool; $kdeopts{"nofinal"} = !$use_final; # default read_variables(); if ($MakefileData =~ /\nKDE_OPTIONS\s*=[ \t]*([^\n]*)\n/) { my $kde_options_str = $1; local @kde_options = split(/[\034\s]+/, $kde_options_str); if (grep(/^foreign$/, @kde_options)) { push(@foreignfiles, $makefileDir . "/"); return 0; # don't touch me } for $opt (@kde_options) { if (!defined $kdeopts{$opt}) { print STDERR "Warning: unknown option $opt in $printname\n"; } else { $kdeopts{$opt} = 1; } } } # Look for the tags that mean we should process this file. $metasourceTags = 0; $metasourceTags++ while ($MakefileData =~ /\n[^=\#]*METASOURCES\s*=/g); my $pofileTag = 0; $pofileTag++ while ($MakefileData =~ /\nPOFILES\s*=/g); if ($pofileTag > 1) { print STDERR "Error: Only one POFILES tag allowed\n"; $errorflag = 1; } while ($MakefileData =~ /\n\.SUFFIXES:([^\n]+)\n/g) { my $suffixes_str = $1; my @list=split(' ', $suffixes_str); foreach $ext (@list) { if ($ext =~ /^\.$cppExt$/) { $cxxsuffix = $ext; $cxxsuffix =~ s/\.//g; print STDOUT "will use suffix $cxxsuffix\n" if ($verbose); last; } } } tag_TDEINIT(); while ($MakefileData =~ /\n(\S*)_OBJECTS\s*=[\034 \t]*([^\n]*)\n/g) { my $program = $1; my $objs = $2; # safe them my $ocv = 0; my @objlist = split(/[\034\s]+/, $objs); foreach $obj (@objlist) { if ($obj =~ /(\S*)\$\((\S+)\)/ ) { my $pre = $1; my $variable = $2; if ($pre eq '' && exists($varcontent{$variable})) { my @addlist = split(/[\034\s]+/, $varcontent{$variable}); push(@objlist, @addlist); } elsif ($variable !~ 'OBJEXT' && $variable !~ /am__objects_\d+/ ) { $ocv = 1; } } } next if ($ocv); next if ($program =~ /^am_libtdeinit_/); $program =~ s/^am_// if ($program =~ /^am_/); my $sourceprogram = $program; $sourceprogram =~ s/\@am_/\@/ if($sourceprogram =~ /^.*\@am_.+/); print STDOUT "found program $program\n" if ($verbose); push(@programs, $program); $realObjs{$program} = $objs; if ($MakefileData =~ /\n$sourceprogram\_SOURCES\s*=[ \t]*(.*)\n/) { $sources{$program} = $1; } else { $sources{$program} = ""; print STDERR "found program with no _SOURCES: $program\n"; } my $realprogram = $program; $realprogram =~ s/_/./g; # unmask to regexp if ($MakefileData =~ /\n($realprogram)(\$\(EXEEXT\)?)?:.*\$\($program\_OBJECTS\)/) { $realname{$program} = $1; } else { # not standard Makefile - nothing to worry about $realname{$program} = ""; } } my $lookup = 'DEPDIR\s*=.*'; if ($MakefileData !~ /\n$lookup/) { $lookup = 'bindir\s*=[ \t]*.*'; substituteLine($lookup, "DEPDIR = .deps\n$1") if ($MakefileData =~ /\n($lookup)/); } my @marks = ('MAINTAINERCLEANFILES', 'CLEANFILES', 'DISTCLEANFILES'); foreach $mark (@marks) { while ($MakefileData =~ /\n($mark)\s*=[ \t]*([^\n]*)/g) { my $clean_str = $2; foreach $file (split('[\034\s]+', $clean_str)) { $file =~ s/\.\///; push(@cleanfiles, $file); } } } my $localTag = 0; $localTag++ if ($MakefileData =~ /\ninstall-\S+-local:/); return (!$errorflag); } #----------------------------------------------------------------------------- # Gets the list of user defined directories - relative to $srcdir - where # header files could be located. sub tag_META_INCLUDES () { my $lookup = '[^=\n]*META_INCLUDES\s*=[ \t]*(.*)'; return 1 if ($MakefileData !~ /($lookup)\n/); print STDOUT "META_INCLUDE processing <$1>\n" if ($verbose); my $headerStr = $2; removeLine ($lookup, $1); my @headerlist = split(/[\034\s]+/, $headerStr); foreach $dir (@headerlist) { $dir =~ s#\$\(srcdir\)#.#; if (! -d $dir) { print STDERR "Warning: $dir can't be found. ", "Must be a relative path to \$(srcdir)\n"; } else { push (@headerdirs, $dir); } } return 0; } #----------------------------------------------------------------------------- sub tag_FINAL() { my @final_names = (); foreach $program (@programs) { if ($sources{$program} =~ /\(/) { print STDOUT "found ( in $program\_SOURCES. skipping\n" if ($verbose); next; } my $mocs = ""; # Moc files (in this program) my $moc_cpp_added = 0; # If we added some .moc.cpp files, due to # no other .cpp file including the .moc one. my @progsources = split(/[\034\s]+/, $sources{$program}); my %shash = (); @shash{@progsources} = 1; # we are only interested in the existence my %sourcelist = (); my %extradeps = (); foreach $source (@progsources) { my $suffix = $source; $suffix =~ s/^.*\.([^\.]+)$/$1/; $sourcelist{$suffix} .= "$source "; } foreach my $mocFile (keys (%globalmocs)) { my ($dir, $hFile, $cppFile) = split ("\035", $globalmocs{$mocFile}, 3); if (defined ($cppFile)) { $mocs .= " $mocFile.moc" if exists $shash{$cppFile}; } else { $sourcelist{$cxxsuffix} .= "$mocFile.moc.$cxxsuffix "; $moc_cpp_added = 1; } } # scan for extra given dependencies and add them to our target while ($MakefileData =~ /\n\s*(\S+)\.(?:lo|o)\s*:([^\n]*)/g) { $extradeps{$1} = $2; } foreach $suffix (keys %sourcelist) { # See if this file contains c++ code. (i.e., just check the file's suffix against c++ extensions) my $suffix_is_cxx = 0; if($suffix =~ /($cppExt)$/) { $cxxsuffix = $1; $suffix_is_cxx = 1; } my $mocfiles_in = ($suffix eq $cxxsuffix) && $moc_cpp_added; my @sourcelist = split(/[\034\s]+/, $sourcelist{$suffix}); if ((@sourcelist == 1 && !$mocfiles_in) || $suffix_is_cxx != 1 ) { # we support IDL on our own if ($suffix eq "skel" || $suffix =~ /^stub/ || $suffix =~ /^signals/ # obsolete, remove in KDE-4 || $suffix eq "h" || $suffix eq "ui" || $suffix eq "kcfgc" ) { next; } foreach $file (@sourcelist) { $file =~ s/\Q$suffix\E$//; $finalObjs{$program} .= $file; if ($program =~ /_la$/) { $finalObjs{$program} .= "lo "; } else { $finalObjs{$program} .= "o "; } } next; # suffix } my $source_deps = ""; foreach $source (@sourcelist) { if (-f $source) { $source_deps .= " \$(srcdir)/$source"; } else { $source_deps .= " $source"; } my $plainsource = $source; $plainsource =~ s/\.$cppExt$//; $source_deps .= " " . $extradeps{$plainsource} if (exists($extradeps{$plainsource})); } $handling = "$program.all_$suffix.$suffix: \$(srcdir)/Makefile.in" . $source_deps . " " . join(' ', $mocs) . "\n"; $handling .= "\t\@echo 'creating $program.all_$suffix.$suffix ...'; \\\n"; $handling .= "\trm -f $program.all_$suffix.files $program.all_$suffix.final; \\\n"; $handling .= "\techo \"#define KDE_USE_FINAL 1\" >> $program.all_$suffix.final; \\\n"; $handling .= "\tfor file in " . $sourcelist{$suffix} . "; do \\\n"; # $handling .= "\t tqt-replace \$\(srcdir\)/\$\$file; \\\n"; $handling .= "\t echo \"#include \\\"\$\$file\\\"\" >> $program.all_$suffix.files; \\\n"; $handling .= "\t test ! -f \$\(srcdir\)/\$\$file || egrep '^#pragma +implementation' \$\(srcdir\)/\$\$file >> $program.all_$suffix.final; \\\n"; $handling .= "\tdone; \\\n"; $handling .= "\tcat $program.all_$suffix.final $program.all_$suffix.files > $program.all_$suffix.$suffix; \\\n"; $handling .= "\trm -f $program.all_$suffix.final $program.all_$suffix.files\n"; appendLines($handling); push(@final_names, "$program.all_$suffix.$suffix"); my $finalObj = "$program.all_$suffix."; if ($program =~ /_la$/) { $finalObj .= "lo"; } else { $finalObj .= "o"; } $finalObjs{$program} .= $finalObj . " "; } } if (!$kdeopts{"nofinal"} && @final_names >= 1) { # add clean-final target my $lines = "$cleantarget-final:\n"; $lines .= "\t-rm -f " . join(' ', @final_names) . "\n" if (@final_names); appendLines($lines); $target_adds{"$cleantarget-am"} .= "$cleantarget-final "; foreach $finalfile (@final_names) { $finalfile =~ s/\.[^.]*$/.P/; $dep_finals .= " \$(DEPDIR)/$finalfile"; } } } sub tag_TDEINIT() { my @progs = (); my $ltlibs = ""; my $lookup = 'tdeinit_LTLIBRARIES\s*=[ \t]*(.*)'; if ($MakefileData =~ m/\n$lookup/) { @tdeinits = split(/[\034\s]+/, $1); my $lines = ""; foreach my $tdeinit (@tdeinits) { if ($tdeinit =~ m/\.la$/) { $tdeinit =~ s/\.la$//; push(@progs, $tdeinit); $lines .= "\n${tdeinit}.la.$cxxsuffix:\n"; $lines .= "\techo 'extern \"C\" int kdemain(int argc, char* argv[]);' > ${tdeinit}.la.$cxxsuffix; \\\n"; $lines .= "\techo 'int main(int argc, char* argv[]) { return kdemain(argc,argv); }' >> ${tdeinit}.la.$cxxsuffix\n"; $lines .= "\n${tdeinit}_dummy.$cxxsuffix:\n"; $lines .= "\techo '#include ' > ${tdeinit}_dummy.$cxxsuffix; \\\n"; $lines .= "\techo 'extern \"C\" int kdemain(int argc, char* argv[]);' >> ${tdeinit}_dummy.$cxxsuffix; \\\n"; $lines .= "\techo 'extern \"C\" KDE_EXPORT int tdeinitmain(int argc, char* argv[]) { return kdemain(argc,argv); }' >> ${tdeinit}_dummy.$cxxsuffix\n"; push(@cleanfiles, "${tdeinit}.la.$cxxsuffix"); push(@cleanfiles, "${tdeinit}_dummy.$cxxsuffix"); # add dependency $dep_files .= " \$(DEPDIR)/${tdeinit}.la.Po" if($dep_files !~/${tdeinit}.la.Po/ ); $dep_files .= " \$(DEPDIR)/${tdeinit}_dummy.Plo" if($dep_files !~/${tdeinit}_dummy.Plo/ ); # make library $lookup = $tdeinit . '_la_LIBADD\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { my $libadd = $1; substituteLine($lookup, "${tdeinit}_la_LIBADD = libtdeinit_${tdeinit}.la"); appendLines("libtdeinit_${tdeinit}_la_LIBADD = $libadd\n"); } appendLines("libtdeinit_${tdeinit}_la_LDFLAGS = -no-undefined -avoid-version \$(all_libraries)\n"); # add library dependencies $lookup = $tdeinit . '_la_DEPENDENCIES\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { my $libdeps = $1; substituteLine($lookup, "${tdeinit}_la_DEPENDENCIES = libtdeinit_${tdeinit}.la"); appendLines("libtdeinit_${tdeinit}_la_DEPENDENCIES = $libdeps\n"); } # make library objects $lookup = "am_${tdeinit}_la_OBJECTS" . '\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { my $libobjects = $1; substituteLine($lookup, "am_${tdeinit}_la_OBJECTS = ${tdeinit}_dummy.lo"); appendLines("am_libtdeinit_${tdeinit}_la_OBJECTS = $libobjects\n"); my $prog = "libtdeinit_${tdeinit}_la"; push(@programs, $prog); $realObjs{$prog} = $libobjects; $realname{$prog} = "libtdeinit_${tdeinit}.la"; } $target_adds{"libtdeinit_${tdeinit}.la"} = "\$(libtdeinit_${tdeinit}_la_OBJECTS) \$(libtdeinit_${tdeinit}_la_DEPENDENCIES)\n" . "\t\$(CXXLINK) -rpath \$(libdir) \$(libtdeinit_${tdeinit}_la_LDFLAGS) ". "\$(libtdeinit_${tdeinit}_la_OBJECTS) " . "\$(libtdeinit_${tdeinit}_la_LIBADD) " . "\$(LIBS)\n"; # make libtdeinit sources $lookup = $tdeinit . '_la_SOURCES\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { my $srces = $1; $sources_changed{"libtdeinit_${tdeinit}_la"} = 1; $sources{"libtdeinit_${tdeinit}_la"} = $srces; } # make libtdeinit metasources $lookup = $tdeinit . '_la_METASOURCES\s*=[ \t]*(.*)'; substituteLine($lookup, "libtdeinit_${tdeinit}_la_METASOURCES = $1") if($MakefileData =~ m/\n$lookup/); =cut # make binary sources $lookup = $tdeinit. '_SOURCES\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { substituteLine($lookup, "${tdeinit}_SOURCES = ${tdeinit}.la.$cxxsuffix"); $lookup = 'SOURCES\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { my $srces = $1; $srces =~ s/\b$tdeinit\.c\b/\$(${tdeinit}_SOURCES)/; $srces =~ s/\$\(${tdeinit}_la_SOURCES\)/\$(libtdeinit_${tdeinit}_la_SOURCES)/; substituteLine($lookup, "SOURCES = $srces"); } $lookup = 'DIST_SOURCES\s*=[ \t](.*)'; if($MakefileData =~ m/\n$lookup/) { my $srces = $1; $srces =~ s/\b$tdeinit\.c\b/\$(${tdeinit}_SOURCES)/; $srces =~ s/\$\(${tdeinit}_la_SOURCES\)/\$(libtdeinit_${tdeinit}_la_SOURCES)/; substituteLine($lookup, "DIST_SOURCES = $srces"); } } # make binary objects / libs $lookup = $tdeinit . '_OBJECTS\s*=[ \t]*.*'; if($MakefileData =~ m/\n$lookup/) { $realObjs{$tdeinit} = "${tdeinit}.la.\$(OBJEXT)"; substituteLine("${tdeinit}_LDFLAGS\\s*=.*", "${tdeinit}_LDFLAGS = \$(all_libraries)"); substituteLine("${tdeinit}_LDADD\\s*=.*", "${tdeinit}_LDADD = libtdeinit_${tdeinit}.la"); substituteLine("${tdeinit}_DEPENDENCIES\\s*=.*", "${tdeinit}_DEPENDENCIES = libtdeinit_${tdeinit}.la"); } =cut # add binary push(@programs, $tdeinit); $realObjs{$tdeinit} = "${tdeinit}.la.\$(OBJEXT)"; $realname{$tdeinit} = $tdeinit; $sources{$tdeinit} = "${tdeinit}.la.$cxxsuffix"; $lines .= "${tdeinit}_LDFLAGS = \$(KDE_RPATH) -no-undefined \$(all_libraries)\n"; $lines .= "${tdeinit}_LDADD = libtdeinit_${tdeinit}.la\n"; $lines .= "${tdeinit}_DEPENDENCIES = libtdeinit_${tdeinit}.la\n"; $target_adds{"${tdeinit}\$(EXEEXT)"} = "\$(${tdeinit}_OBJECTS) \$(${tdeinit}_DEPENDENCIES)\n" . "\t\@rm -f ${tdeinit}\$(EXEEXT)\n" . "\t\$(CXXLINK) \$(${tdeinit}_LDFLAGS) \$(${tdeinit}_OBJECTS) \$(${tdeinit}_LDADD) \$(LIBS)\n"; $ltlibs .= " libtdeinit_${tdeinit}.la"; } } appendLines($lines); # add libtdeinit target $lookup = 'lib_LTLIBRARIES\s*=[ \t]*(.*)'; if($MakefileData =~ m/\n$lookup/) { substituteLine($lookup, "lib_LTLIBRARIES = $1 $ltlibs"); } else { print STDERR "Error: lib_LTLIBRARIES missing in $printname (required for tdeinit_LTLIBRARIES).\n"; $errorflag = 1; } } if($#progs >= 0) { if($MakefileData !~ m/\nbin_PROGRAMS\s*=/) { print STDERR "Error: bin_PROGRAMS missing in $printname (required for tdeinit_LTLIBRARIES).\n"; $errorflag = 1; } else { # add our new progs to SOURCES, DIST_SOURCES and bin_PROGRAMS my $progsources = ""; my $progexes = ""; foreach my $p (@progs) { $progsources .= "\$(${p}_SOURCES) "; $progexes .= "${p}\$(EXEEXT) "; } $lookup = 'SOURCES\s*=[ \t]*(.*)'; if($MakefileData =~ /\n$lookup/) { substituteLine($lookup, "SOURCES = $1 $progsources"); } $lookup = 'DIST_SOURCES\s*=[ \t]*(.*)'; if($MakefileData =~ /\n$lookup/) { substituteLine($lookup, "DIST_SOURCES = $1 $progsources"); } # bin_PROGRAMS is complicated, as it exists twice, so we do a little # magic trick here $lookup = 'PROGRAMS\s*=[ \t]*(.*)'; if ($MakefileData =~ /\n$lookup/) { substituteLine($lookup, "bin_PROGRAMS += $progexes\nPROGRAMS = $1"); } } } } #----------------------------------------------------------------------------- sub tag_COMPILE_FIRST() { foreach $program (@programs) { my $lookup = "$program" . '_COMPILE_FIRST\s*=[ \t]*(.*)'; if ($MakefileData =~ m/\n$lookup\n/) { my $compilefirst_str = $1; my @compilefirst = split(/[\034\s]+/, $compilefirst_str); my @progsources = split(/[\034\s]+/, $sources{$program}); my %donesources = (); foreach $source (@progsources) { my @deps = (); my $sdeps = ""; if (-f $source) { $sdeps = "\$(srcdir)/$source"; } else { $sdeps = "$source"; } foreach $depend (@compilefirst) { next if ($source eq $depend); # avoid cyclic dependencies next if defined($donesources{$depend}); push @deps, $depend; } $target_adds{$sdeps} .= join(' ', @deps) . ' ' if (@deps); $donesources{$source} = 1; } } } } #----------------------------------------------------------------------------- # Organises the list of headers that we'll use to produce moc files # from. sub tag_METASOURCES () { local @newObs = (); # here we add to create object files local @depend = (); # here we add to create moc files local $mocExt = ".moc"; local %mocFiles = (); my $line = ""; my $postEqual = ""; my $lookup; my $found = ""; if ($metasourceTags > 1) { $lookup = $program . '_METASOURCES\s*=\s*(.*)'; return 1 if ($MakefileData !~ /\n($lookup)\n/); $found = $1; } else { $lookup = $program . '_METASOURCES\s*=\s*(.*)'; if ($MakefileData !~ /\n($lookup)\n/) { $lookup = 'METASOURCES\s*=\s*(.*)'; return 1 if ($MakefileData !~ /\n($lookup)\n/); $found = $1; $metasourceTags = 0; # we can use the general target only once } else { $found = $1; } } print STDOUT "METASOURCE processing <$found>)\n" if ($verbose); $postEqual = $found; $postEqual =~ s/[^=]*=//; removeLine ($lookup, $found); # Always find the header files that could be used to "moc" return 1 if (findMocCandidates ()); if ($postEqual =~ /AUTO\s*(\S*)|USE_AUTOMOC\s*(\S*)/) { print STDERR "$printname: the argument for AUTO|USE_AUTOMOC is obsolete" if ($+); $mocExt = ".moc.$cxxsuffix"; $haveAutomocTag = 1; } else { # Not automoc so read the list of files supplied which # should be .moc files. $postEqual =~ tr/\034/ /; # prune out extra headers - This also checks to make sure that # the list is valid. pruneMocCandidates ($postEqual); } checkMocCandidates (); if (@newObs) { my $ext = ($program =~ /_la$/) ? ".moc.lo " : ".moc.o "; $realObjs{$program} .= "\034" . join ($ext, @newObs) . $ext; $dependmocs{$program} = join (".moc.$cxxsuffix " , @newObs) . ".moc.$cxxsuffix"; foreach $file (@newObs) { $dep_files .= " \$(DEPDIR)/$file.moc.P" if($dep_files !~/$file.moc.P/); } } if (@depend) { $dependmocs{$program} .= " "; $dependmocs{$program} .= join('.moc ', @depend) . ".moc"; $dependmocs{$program} .= " "; } addMocRules (); @globalmocs{keys %mocFiles}=values %mocFiles; } #----------------------------------------------------------------------------- # Returns 0 if the line was processed - 1 otherwise. # Errors are logged in the global $errorflags sub tag_AUTOMAKE () { my $lookup = '.*cd \$\(top_srcdir\)\s+&&[\034\s]+\$\(AUTOMAKE\)(.*)'; return 1 if ($MakefileData !~ /\n($lookup)\n/); print STDOUT "AUTOMAKE processing <$1>\n" if ($verbose); my $newLine = $1."\n\tcd \$(top_srcdir) && perl $thisProg $printname"; # automake 1.8.x adds another automake call. *sigh* $newLine =~ s/;([\034\s]+cd\s+\$\(srcdir\)\s+&&[\034\s]+\$\(AUTOMAKE\).*)[\034\s]+\&\&[\034\s]+exit[\034\s]+0;([\034\s]+exit\s+1)/; \034 ( $1 ) || exit 1; echo \' cd \$(top_srcdir) && perl $thisProg \'; cd \$(top_srcdir) && perl $thisProg && exit 0; $2/; substituteLine ($lookup, $newLine); $automkCall = $1; $lookup = '.*cd \$\(srcdir\)\s+&&[\034\s]+\$\(AUTOCONF\)(.*)'; if ($MakefileData =~ /\n($lookup)\n/) { $newLine = "\tcd \$(srcdir) && rm -f configure\n"; $newLine .= "\tcd \$(top_srcdir) && \$(MAKE) -f admin/Makefile.common configure"; substituteLine ($lookup, $newLine); } return 0; } #----------------------------------------------------------------------------- sub handle_TOPLEVEL() { my $pofiles = ""; my @restfiles = (); opendir (THISDIR, "."); foreach $entry (readdir(THISDIR)) { next if (-d $entry); next if ($entry eq "CVS" || $entry =~ /^\./ || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/ || $entry =~ /.gmo$/); if ($entry =~ /\.po$/) { next; } push(@restfiles, $entry); } closedir (THISDIR); if (@restfiles) { $target_adds{"install-data-am"} .= "install-nls-files "; $lines = "install-nls-files:\n"; $lines .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/$kdelang\n"; for $file (@restfiles) { $lines .= "\t\$(INSTALL_DATA) \$\(srcdir\)/$file \$(DESTDIR)\$(kde_locale)/$kdelang/$file\n"; } $target_adds{"uninstall"} .= "uninstall-nls-files "; $lines .= "uninstall-nls-files:\n"; for $file (@restfiles) { $lines .= "\t-rm -f \$(DESTDIR)\$(kde_locale)/$kdelang/$file\n"; } appendLines($lines); } return 0; } #----------------------------------------------------------------------------- sub tag_SUBDIRS () { if ($MakefileData !~ /\nSUBDIRS\s*=\s*\$\(AUTODIRS\)\s*\n/) { return 1; } my $subdirs = "."; opendir (THISDIR, "."); foreach $entry (readdir(THISDIR)) { next if ($entry eq "CVS" || $entry =~ /^\./); if (-d $entry && -f $entry . "/Makefile.am") { $subdirs .= " $entry"; next; } } closedir (THISDIR); substituteLine('SUBDIRS\s*=.*', "SUBDIRS =$subdirs"); return 0; } sub tag_IDLFILES () { my @psources = split(/[\034\s]+/, $sources{$program}); my $dep_lines = ""; my @cppFiles = (); foreach $source (@psources) { my $skel = ($source =~ m/\.skel$/); my $stub = ($source =~ m/\.stub$/); my $signals = ($source =~ m/\.signals$/); # obsolete, remove in KDE-4 if ($stub || $skel || $signals) { my $qs = quotemeta($source); $sources{$program} =~ s/$qs//; $sources_changed{$program} = 1; $source =~ s/\.(stub|skel|signals)$//; my $sourcename; if ($skel) { $sourcename = "$source\_skel"; } elsif ($stub) { $sourcename = "$source\_stub"; } else { $sourcename = "$source\_signals"; } my $sourcedir = ''; if (-f "$makefileDir/$source.h") { $sourcedir = '$(srcdir)/'; } else { if ($MakefileData =~ /\n$source\_DIR\s*=\s*(\S+)\n/) { $sourcedir = $1; $sourcedir .= "/" if ($sourcedir !~ /\/$/); } } if ($allidls !~ /$source\_kidl/) { $use_ng = ($MakefileData =~ /\n$source\_DCOPIDLNG\s*=\s*(\S+)\n/); $dcopidl = $use_ng ? "KDECONFIG=\"\$(KDECONFIG)\" \$(TQTDCOPIDLNG)" : " \$(TQTDCOPIDL)"; $dep_lines .= "$source.kidl: $sourcedir$source.h \$(DCOP_DEPENDENCIES)\n"; $dep_lines .= "\t$dcopidl $sourcedir$source.h > $source.kidl || ( rm -f $source.kidl ; false )\n"; $allidls .= $source . "_kidl "; } if ($allidls !~ /$sourcename/) { $dep_lines_tmp = ""; if ($skel) { $dep_lines .= "$sourcename.$cxxsuffix: $source.kidl\n"; $dep_lines .= "\t\$(TQTDCOPIDL2CPP) --c++-suffix $cxxsuffix --no-signals --no-stub $source.kidl\n"; } elsif ($stub) { $dep_lines_tmp = "\t\$(TQTDCOPIDL2CPP) --c++-suffix $cxxsuffix --no-signals --no-skel $source.kidl\n"; } else { # signals - obsolete, remove in KDE 4 $dep_lines_tmp = "\t\$(TQTDCOPIDL2CPP) --c++-suffix $cxxsuffix --no-stub --no-skel $source.kidl\n"; } if ($stub || $signals) { $target_adds{"$sourcename.$cxxsuffix"} .= "$sourcename.h "; $dep_lines .= "$sourcename.h: $source.kidl\n"; $dep_lines .= $dep_lines_tmp; } $allidls .= $sourcename . " "; } $idlfiles{$program} .= $sourcename . " "; if ($program =~ /_la$/) { $realObjs{$program} .= " $sourcename.lo"; } else { $realObjs{$program} .= " $sourcename.\$(OBJEXT)"; } $sources{$program} .= " $sourcename.$cxxsuffix"; $sources_changed{$program} = 1; $important{$program} .= "$sourcename.h " if (!$skel); $idl_output .= "\\\n\t$sourcename.$cxxsuffix $sourcename.h $source.kidl "; push(@cleanfiles, "$sourcename.$cxxsuffix"); push(@cleanfiles, "$sourcename.h"); push(@cleanfiles, "$sourcename.kidl"); $dep_files .= " \$(DEPDIR)/$sourcename.P" if ($dep_files !~/$sourcename.P/); } } if ($dep_lines) { appendLines($dep_lines); } if (0) { my $lookup = "($program)"; $lookup .= '(|\$\(EXEEXT\))'; $lookup =~ s/\_/./g; $lookup .= ":(.*..$program\_OBJECTS..*)"; # $lookup = quotemeta($lookup); if ($MakefileData =~ /\n$lookup\n/) { my $line = "$1$2: "; foreach $file (split(' ', $idlfiles{$program})) { $line .= "$file.$cxxsuffix "; } $line .= $3; substituteLine($lookup, $line); } else { print STDERR "no built dependency found $lookup\n"; } } } sub tag_UIFILES () { my @psources = split(/[\034\s]+/, $sources{$program}); my @depFiles = (); foreach $source (@psources) { if ($source =~ m/\.ui$/) { print STDERR "adding UI file $source\n" if ($verbose); my $qs = quotemeta($source); $sources{$program} =~ s/$qs//; $sources_changed{$program} = 1; $source =~ s/\.ui$//; my $sourcedir = ''; if (-f "$makefileDir/$source.ui") { $sourcedir = '$(srcdir)/'; } if (!$uiFiles{$source}) { my $dep_lines = "$source.$cxxsuffix: $sourcedir$source.ui $source.h $source.moc\n"; $dep_lines .= "\trm -f $source.$cxxsuffix\n"; if (!$kdeopts{"qtonly"}) { $dep_lines .= "\techo '#include ' > $source.$cxxsuffix\n"; $dep_lines .= "\techo '#include ' >> $source.$cxxsuffix\n"; my ($mangled_source) = $source; $mangled_source =~ s/[^A-Za-z0-9]/_/g; # get rid of garbage $dep_lines .= "\t\$(UIC) -tr \${UIC_TR} -i $source.h $sourcedir$source.ui > $source.$cxxsuffix.temp ; ret=\$\$?; \\\n"; $dep_lines .= "\t\$(PERL) -pe \"s,\${UIC_TR}( \\\"\\\" ),QString::null,g\" $source.$cxxsuffix.temp | \$(PERL) -pe \"s,\${UIC_TR}( \\\"\\\"\\, \\\"\\\" ),QString::null,g\" | \$(PERL) -pe \"s,image([0-9][0-9]*)_data,img\\\$\$1_" . $mangled_source . ",g\" | \$(PERL) -pe \"s,: QWizard\\(,: KWizard(,g\" >> $source.$cxxsuffix ;\\\n"; $dep_lines .= "\trm -f $source.$cxxsuffix.temp ;\\\n"; } else { $dep_lines .= "\t\$(UIC) -i $source.h $sourcedir$source.ui > $source.$cxxsuffix; ret=\$\$?; \\\n"; } $dep_lines .= "\tif test \"\$\$ret\" = 0; then echo '#include \"$source.moc\"' >> $source.$cxxsuffix; else rm -f $source.$cxxsuffix ; exit \$\$ret ; fi\n\n"; $dep_lines .= "$source.h: $sourcedir$source.ui\n"; $dep_lines .= "\trm -rf $source.h;\n"; if (!$kdeopts{"qtonly"}) { $dep_lines .= "\t\$(UIC) $sourcedir$source.ui | \$(PERL) -pi -e \"s,public TQWizard,public KWizard,g; s,#include ,#include ,g\" >> $source.h ;\n"; } else { $dep_lines .= "\t\$(UIC) -o $source.h $sourcedir$source.ui\n"; } $dep_lines .= "$source.moc: $source.h\n"; $dep_lines .= "\t\$(TQTMOC) $source.h -o $source.moc\n"; $rule_adds{"$source.$cxxsuffix"} = $dep_lines; $uiFiles{$source} = 1; $dependmocs{$program} .= " $source.moc"; $globalmocs{$source} = "\035$source.h\035$source.cpp"; } if ($program =~ /_la$/) { $realObjs{$program} .= " $source.lo"; } else { $realObjs{$program} .= " $source.\$(OBJEXT)"; } $sources{$program} .= " $source.$cxxsuffix"; $sources_changed{$program} = 1; $important{$program} .= "$source.h "; $ui_output .= "\\\n\t$source.$cxxsuffix $source.h $source.moc "; push(@cleanfiles, "$source.$cxxsuffix"); push(@cleanfiles, "$source.h"); push(@cleanfiles, "$source.moc"); $dep_files .= " \$(DEPDIR)/$source.P" if($dep_files !~/$source.P/ ); } } } sub tag_KCFGFILES () { my @psources = split(/[\034\s]+/, $sources{$program}); my @depFiles = (); foreach $source (@psources) { if ($source =~ m/\.kcfgc$/) { print STDERR "adding KCFG file $source\n" if ($verbose); my $qs = quotemeta($source); $sources{$program} =~ s/$qs//; $sources_changed{$program} = 1; $source =~ s/\.kcfgc$//; my $sourcedir = ''; if (-f "$makefileDir/$source.kcfgc") { $sourcedir = '$(srcdir)/'; } if (!$kcfgFiles{$source}) { $kcfg = "$program.kcfg"; findKcfgFile("$source.kcfgc"); my $fixsuffix = ""; $fixsuffix = "else mv $source.cpp $source.$cxxsuffix ; " unless "cpp" eq $cxxsuffix; my $dep_lines = "$source.$cxxsuffix: $source.h\n"; $dep_lines .= "$source.h: $sourcedir$kcfg $sourcedir$source.kcfgc \$(KCFG_DEPENDENCIES)\n"; $dep_lines .= "\t\$(KCONFIG_COMPILER) $sourcedir$kcfg $sourcedir$source.kcfgc; ret=\$\$?; \\\n"; $dep_lines .= "\tif test \"\$\$ret\" != 0; then rm -f $source.h ; exit \$\$ret ; $fixsuffix fi\n\n"; $rule_adds{"$source.$cxxsuffix"} = $dep_lines; $kcfgFiles{$source} = 1; } if ($program =~ /_la$/) { $realObjs{$program} .= " $source.lo"; } else { $realObjs{$program} .= " $source.\$(OBJEXT)"; } $sources{$program} .= " $source.$cxxsuffix"; $sources_changed{$program} = 1; $important{$program} .= "$source.h "; $kcfg_output .= "\\\n\t$source.$cxxsuffix $source.h "; push(@cleanfiles, "$source.$cxxsuffix"); push(@cleanfiles, "$source.h"); $dep_files .= " \$(DEPDIR)/$source.P" if($dep_files !~/$source.P/ ); } } } sub tag_ICON() { my $lookup = '([^\s]*)_ICON\s*=[ \t]*(.*)'; my $install = ""; my $uninstall = ""; while ($MakefileData =~ /\n$lookup/g) { my $destdir; if ($1 eq "KDE") { $destdir = "kde_icondir"; } else { $destdir = $1 . "dir"; } my $iconauto = ($2 =~ /AUTO\s*$/); my @appnames = (); if ( ! $iconauto ) { my $appicon_str = $2; my @_appnames = split(" ", $appicon_str); print STDOUT "KDE_ICON processing <@_appnames>\n" if ($verbose); foreach $appname (@_appnames) { push(@appnames, quotemeta($appname)); } } else { print STDOUT "KDE_ICON processing \n" if ($verbose); } my @files = (); opendir (THISDIR, "."); foreach $entry (readdir(THISDIR)) { next if ($entry eq "CVS" || $entry =~ /^\./ || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/); next if (! -f $entry); if ( $iconauto ) { push(@files, $entry) if ($entry =~ /\.xpm/ || $entry =~ /\.png/ || $entry =~ /\.mng/ || $entry =~ /\.svg/); } else { foreach $appname (@appnames) { push(@files, $entry) if ($entry =~ /-$appname\.xpm/ || $entry =~ /-$appname\.png/ || $entry =~ /-$appname\.mng/ || $entry =~ /-$appname\.svg/); } } } closedir (THISDIR); my %directories = (); foreach $file (@files) { my $newfile = $file; my $prefix = $file; $prefix =~ s/\.(png|xpm|mng|svg|svgz)$//; my $appname = $prefix; $appname =~ s/^[^-]+-// if ($appname =~ /-/) ; $appname =~ s/^[^-]+-// if ($appname =~ /-/) ; $appname = quotemeta($appname); $prefix =~ s/$appname$//; $prefix =~ s/-$//; $prefix = 'lo16-app' if ($prefix eq 'mini'); $prefix = 'lo32-app' if ($prefix eq 'lo'); $prefix = 'hi48-app' if ($prefix eq 'large'); $prefix .= '-app' if ($prefix =~ m/^...$/); my $type = $prefix; $type =~ s/^.*-([^-]+)$/$1/; $prefix =~ s/^(.*)-[^-]+$/$1/; my %type_hash = ( 'action' => 'actions', 'app' => 'apps', 'device' => 'devices', 'filesys' => 'filesystems', 'mime' => 'mimetypes' ); if (! defined $type_hash{$type} ) { print STDERR "unknown icon type $type in $printname ($file)\n"; next; } my %dir_hash = ( 'los' => 'locolor/16x16', 'lom' => 'locolor/32x32', 'him' => 'hicolor/32x32', 'hil' => 'hicolor/48x48', 'lo16' => 'locolor/16x16', 'lo22' => 'locolor/22x22', 'lo32' => 'locolor/32x32', 'hi16' => 'hicolor/16x16', 'hi22' => 'hicolor/22x22', 'hi32' => 'hicolor/32x32', 'hi48' => 'hicolor/48x48', 'hi64' => 'hicolor/64x64', 'hi128' => 'hicolor/128x128', 'hisc' => 'hicolor/scalable', 'cr16' => 'crystalsvg/16x16', 'cr22' => 'crystalsvg/22x22', 'cr32' => 'crystalsvg/32x32', 'cr48' => 'crystalsvg/48x48', 'cr64' => 'crystalsvg/64x64', 'cr128' => 'crystalsvg/128x128', 'crsc' => 'crystalsvg/scalable' ); $newfile =~ s@.*-($appname\.(png|xpm|mng|svgz|svg?))@$1@; if (! defined $dir_hash{$prefix}) { print STDERR "unknown icon prefix $prefix in $printname\n"; next; } my $dir = $dir_hash{$prefix} . "/" . $type_hash{$type}; if ($newfile =~ /-[^\.]/) { my $tmp = $newfile; $tmp =~ s/^([^-]+)-.*$/$1/; $dir = $dir . "/" . $tmp; $newfile =~ s/^[^-]+-//; } if (!defined $directories{$dir}) { $install .= "\t\$(mkinstalldirs) \$(DESTDIR)\$($destdir)/$dir\n"; $directories{$dir} = 1; } $install .= "\t\$(INSTALL_DATA) \$(srcdir)/$file \$(DESTDIR)\$($destdir)/$dir/$newfile\n"; $uninstall .= "\t-rm -f \$(DESTDIR)\$($destdir)/$dir/$newfile\n"; } } if (length($install)) { $target_adds{"install-data-am"} .= "install-kde-icons "; $target_adds{"uninstall-am"} .= "uninstall-kde-icons "; appendLines("install-kde-icons:\n" . $install . "\nuninstall-kde-icons:\n" . $uninstall); } } sub handle_POFILES($$) { my @pofiles = split(" ", $_[0]); my $lang = $_[1]; # Build rules for creating the gmo files my $tmp = ""; my $allgmofiles = ""; my $pofileLine = "POFILES ="; foreach $pofile (@pofiles) { $pofile =~ /(.*)\.[^\.]*$/; # Find name minus extension $tmp .= "$1.gmo: $pofile\n"; $tmp .= "\trm -f $1.gmo; \$(GMSGFMT) -o $1.gmo \$(srcdir)/$pofile\n"; $tmp .= "\ttest ! -f $1.gmo || touch $1.gmo\n"; $allgmofiles .= " $1.gmo"; $pofileLine .= " $1.po"; } appendLines ($tmp); my $lookup = 'POFILES\s*=([^\n]*)'; if ($MakefileData !~ /\n$lookup/) { appendLines("$pofileLine\nGMOFILES =$allgmofiles"); } else { substituteLine ($lookup, "$pofileLine\nGMOFILES =$allgmofiles"); } if ($allgmofiles) { # Add the "clean" rule so that the maintainer-clean does something appendLines ("clean-nls:\n\t-rm -f $allgmofiles\n"); $target_adds{"maintainer-clean"} .= "clean-nls "; $lookup = 'DISTFILES\s*=[ \t]*(.*)'; if ($MakefileData =~ /\n$lookup/) { $tmp = "DISTFILES = \$(GMOFILES) \$(POFILES) $1"; substituteLine ($lookup, $tmp); } } $target_adds{"install-data-am"} .= "install-nls "; $tmp = "install-nls:\n"; if ($lang) { $tmp .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES\n"; } $tmp .= "\t\@for base in "; foreach $pofile (@pofiles) { $pofile =~ /(.*)\.[^\.]*$/; # Find name minus extension $tmp .= "$1 "; } $tmp .= "; do \\\n"; if ($lang) { $tmp .= "\t echo \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n"; $tmp .= "\t if test -f \$\$base.gmo; then \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n"; $tmp .= "\t elif test -f \$(srcdir)/\$\$base.gmo; then \$(INSTALL_DATA) \$(srcdir)/\$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n"; $tmp .= "\t fi ;\\\n"; } else { $tmp .= "\t echo \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n"; $tmp .= "\t \$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES ; \\\n"; $tmp .= "\t if test -f \$\$base.gmo; then \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n"; $tmp .= "\t elif test -f \$(srcdir)/\$\$base.gmo; then \$(INSTALL_DATA) \$(srcdir)/\$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n"; $tmp .= "\t fi ;\\\n"; } $tmp .= "\tdone\n\n"; appendLines ($tmp); $target_adds{"uninstall"} .= "uninstall-nls "; $tmp = "uninstall-nls:\n"; foreach $pofile (@pofiles) { $pofile =~ /(.*)\.[^\.]*$/; # Find name minus extension if ($lang) { $tmp .= "\trm -f \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/$1.mo\n"; } else { $tmp .= "\trm -f \$(DESTDIR)\$(kde_locale)/$1/LC_MESSAGES/\$(PACKAGE).mo\n"; } } appendLines($tmp); $target_adds{"all"} .= "all-nls "; $tmp = "all-nls: \$(GMOFILES)\n"; appendLines($tmp); $target_adds{"distdir"} .= "distdir-nls "; $tmp = "distdir-nls:\$(GMOFILES)\n"; $tmp .= "\tfor file in \$(POFILES); do \\\n"; $tmp .= "\t cp \$(srcdir)/\$\$file \$(distdir); \\\n"; $tmp .= "\tdone\n"; $tmp .= "\tfor file in \$(GMOFILES); do \\\n"; $tmp .= "\t cp \$(srcdir)/\$\$file \$(distdir); \\\n"; $tmp .= "\tdone\n"; appendLines ($tmp); if (!$lang) { appendLines("merge:\n\t\$(MAKE) -f \$(top_srcdir)/admin/Makefile.common package-merge POFILES=\"\${POFILES}\" PACKAGE=\${PACKAGE}\n\n"); } } #----------------------------------------------------------------------------- # Returns 0 if the line was processed - 1 otherwise. # Errors are logged in the global $errorflags sub tag_POFILES () { my $lookup = 'POFILES\s*=([^\n]*)'; return 1 if ($MakefileData !~ /\n$lookup/); print STDOUT "POFILES processing <$1>\n" if ($verbose); my $tmp = $1; # make sure these are all gone. if ($MakefileData =~ /\n\.po\.gmo:\n/) { print STDERR "Warning: Found old .po.gmo rules in $printname. New po rules not added\n"; return 1; } # Either find the pofiles in the directory (AUTO) or use # only the specified po files. my $pofiles = ""; if ($tmp =~ /^\s*AUTO\s*$/) { opendir (THISDIR, "."); $pofiles = join(" ", grep(/\.po$/, readdir(THISDIR))); closedir (THISDIR); print STDOUT "pofiles found = $pofiles\n" if ($verbose); if (-f "charset" && -f "tdelibs/tdelibs.po") { handle_TOPLEVEL(); } } else { $tmp =~ s/\034/ /g; $pofiles = $tmp; } return 1 if (!$pofiles); # Nothing to do handle_POFILES($pofiles, $kdelang); return 0; } sub helper_LOCALINSTALL($) { my $lookup = "\035" . $_[0] . " *:[^\035]*\035\t"; my $copy = $MakefileData; $copy =~ s/\n/\035/g; if ($copy =~ /($lookup.*)$/) { $install = $1; $install =~ s/\035$_[0] *:[^\035]*\035//; my $emptyline = 0; while (! $emptyline ) { if ($install =~ /([^\035]*)\035(.*)/) { local $line = $1; $install = $2; if ($line !~ /^\s*$/ && $line !~ /^(\@.*\@)*\t/) { $emptyline = 1; } else { replaceDestDir($line); } } else { $emptyline = 1; } } } } sub tag_LOCALINSTALL () { helper_LOCALINSTALL('install-exec-local'); helper_LOCALINSTALL('install-data-local'); helper_LOCALINSTALL('uninstall-local'); return 0; } sub replaceDestDir($) { local $line = $_[0]; if ( $line =~ /^\s*(\@.*\@)*\s*\$\(mkinstalldirs\)/ || $line =~ /^\s*(\@.*\@)*\s*\$\(INSTALL\S*\)/ || $line =~ /^\s*(\@.*\@)*\s*(-?rm.*) \S*$/) { $line =~ s/^(.*) ([^\s]+)\s*$/$1 \$(DESTDIR)$2/ if ($line !~ /\$\(DESTDIR\)/); } if ($line ne $_[0]) { $_[0] = quotemeta $_[0]; substituteLine($_[0], $line); } } #--------------------------------------------------------------------------- # libtool is very hard to persuade it could use -Wl,--no-undefined for making # -no-undefined actually work # append $(KDE_NO_UNFINED) after every -no-undefined in LDFLAGS # this may go away if libtool ever does this on its own sub tag_NO_UNDEFINED () { return if ($program !~ /_la$/); my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n"; $MakefileData =~ m/$lookup/; return if (!defined($1)); return if ($1 !~ /CXXLINK/); if ($MakefileData !~ /\n$program\_LDFLAGS\s*=.*-no-undefined/ ) { return; } $lookup = $program . '\_LDFLAGS(\s*)=(.*)-no-undefined(.*)'; if ($MakefileData =~ /\n$lookup\n/) { my $replace = $program . "\_LDFLAGS$1=$2-no-undefined \$(KDE_NO_UNDEFINED)$3"; substituteLine($lookup, $replace); } } sub tag_CLOSURE () { return if ($program !~ /_la$/); my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n"; $MakefileData =~ m/$lookup/; return if (!defined($1)); return if ($1 !~ /CXXLINK/); if ($MakefileData !~ /\n$program\_LDFLAGS\s*=.*-no-undefined/ && $MakefileData !~ /\n$program\_LDFLAGS\s*=.*KDE_PLUGIN/ ) { print STDERR "Report: $program contains undefined in $printname\n" if ($program =~ /^lib/ && $dryrun); return; } my $closure = $realname{$program} . ".closure"; my $lines = "$closure: \$($program\_OBJECTS) \$($program\_DEPENDENCIES)\n"; $lines .= "\t\@echo \"int main() {return 0;}\" > $program\_closure.$cxxsuffix\n"; $lines .= "\t\@\$\(LTCXXCOMPILE\) -c $program\_closure.$cxxsuffix\n"; $lines .= "\t\$\(CXXLINK\) $program\_closure.lo \$($program\_LDFLAGS) \$($program\_OBJECTS) \$($program\_LIBADD) \$(LIBS)\n"; $lines .= "\t\@rm -f $program\_closure.* $closure\n"; $lines .= "\t\@echo \"timestamp\" > $closure\n"; $lines .= "\n"; appendLines($lines); $lookup = $realname{$program} . ": (.*)"; if ($MakefileData =~ /\n$lookup\n/) { $lines = "\@KDE_USE_CLOSURE_TRUE@". $realname{$program} . ": $closure $1"; $lines .= "\n\@KDE_USE_CLOSURE_FALSE@" . $realname{$program} . ": $1"; substituteLine($lookup, $lines); } $closure_output .= " $closure"; } sub tag_NMCHECK () { return if ($program !~ /_la$/); my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n"; $MakefileData =~ m/$lookup/; my $linkcmd = $1; return if (!defined($1)); return if ($linkcmd !~ /CXXLINK/ && $linkcmd !~ /LINK/); $lookup = $program . '_NMCHECK\s*=([^\n]*)'; if( $MakefileData !~ m/\n$lookup\n/ ) { return; } my $allowed = $1; $allowed =~ s/^ *//; $lookup = $program . '_NMCHECKWEAK\s*=([^\n]*)'; my $weak = ""; my $is_weak = 0; if( $MakefileData =~ m/\n$lookup\n/ ) { $weak = $1; $is_weak = 1; } $weak =~ s/^ *//; if( $is_weak ) { $weak = '--allowweak=\'' . $weak . '\' '; } my $nmline = "\@KDE_USE_NMCHECK_TRUE@\t\@\$(MAKE) \$(AM_MAKEFLAGS) nmcheck_$realname{$program} || ( rm -f $realname{$program}; exit 1 )"; $lookup = '(\t\$\(CXXLINK\)[^\n]*' . $program . '_OBJECTS[^\n]*)'; if( $MakefileData =~ /\n$lookup\n/ ) { my $oldstuff = $1; substituteLine( $lookup, $oldstuff . "\n" . $nmline ); } $lookup = '(\t\$\(LINK\)[^\n]*' . $program . '_OBJECTS[^\n]*)'; if( $MakefileData =~ /\n$lookup\n/ ) { my $oldstuff = $1; substituteLine( $lookup, $oldstuff . "\n" . $nmline ); } $nmline = "\@\$(top_srcdir)/admin/nmcheck $realname{$program} \'$allowed\' $weak"; appendLines( "\nnmcheck_$realname{$program}: $realname{$program} \n\t$nmline\n" ); $target_adds{ "nmcheck" } .= "nmcheck_$realname{$program} "; } sub tag_DIST () { my %foundfiles = (); opendir (THISDIR, "."); foreach $entry (readdir(THISDIR)) { next if ($entry eq "CVS" || $entry =~ /^\./ || $entry eq "Makefile" || $entry =~ /~$/ || $entry =~ /^\#.*\#$/); next if (! -f $entry); next if ($entry =~ /\.moc/ || $entry =~ /\.moc.$cppExt$/ || $entry =~ /\.lo$/ || $entry =~ /\.la$/ || $entry =~ /\.o/); next if ($entry =~ /\.all_$cppExt\.$cppExt$/); $foundfiles{$entry} = 1; } closedir (THISDIR); # doing this for MAINTAINERCLEANFILES would be wrong my @marks = ("EXTRA_DIST", "DIST_COMMON", '\S*_SOURCES', '\S*_HEADERS', 'CLEANFILES', 'DISTCLEANFILES', '\S*_OBJECTS'); foreach $mark (@marks) { while ($MakefileData =~ /\n($mark)\s*=[ \t]*([^\n]*)/g) { my $cleanfiles_str = $2; foreach $file (split('[\034\s]+', $cleanfiles_str)) { $file =~ s/\.\///; $foundfiles{$file} = 0 if (defined $foundfiles{$file}); } } } my @files = ("Makefile", "config.cache", "config.log", "stamp-h", "stamp-h1", "stamp-h1", "config.h", "Makefile", "config.status", "config.h", "libtool", "core" ); foreach $file (@files) { $foundfiles{$file} = 0 if (defined $foundfiles{$file}); } my $KDE_DIST = ""; foreach $file (keys %foundfiles) { if ($foundfiles{$file} == 1) { $KDE_DIST .= "$file "; } } if ($KDE_DIST) { print "KDE_DIST $printname $KDE_DIST\n" if ($verbose); my $lookup = 'DISTFILES\s*=[ \t]*(.*)'; if ($MakefileData =~ /\n$lookup/) { substituteLine($lookup, "DISTFILES = $1 \$(KDE_DIST)"); appendLines("KDE_DIST=$KDE_DIST\n"); } } } #----------------------------------------------------------------------------- # Returns 0 if the line was processed - 1 otherwise. # Errors are logged in the global $errorflags sub tag_DOCFILES () { $target_adds{"all"} .= "docs-am "; my $lookup = 'KDE_DOCS\s*=[ \t]*([^\n]*)'; goto nodocs if ($MakefileData !~ /\n$lookup/); print STDOUT "KDE_DOCS processing <$1>\n" if ($verbose); my $tmp = $1; # Either find the files in the directory (AUTO) or use # only the specified po files. my $files = ""; my $appname = $tmp; $appname =~ s/^(\S*)\s*.*$/$1/; if ($appname =~ /AUTO/) { $appname = basename($makefileDir); if ("$appname" eq "en") { print STDERR "Error: KDE_DOCS = AUTO relies on the directory name. Yours is 'en' - you most likely want something else, e.g. KDE_DOCS = myapp\n"; exit(1); } } if ($tmp !~ / - /) { opendir (THISDIR, "."); foreach $entry (readdir(THISDIR)) { next if ($entry eq "CVS" || $entry =~ /^\./ || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/ || $entry eq "core" || $entry eq "index.cache.bz2"); next if (! -f $entry); $files .= "$entry "; } closedir (THISDIR); print STDOUT "docfiles found = $files\n" if ($verbose); } else { $tmp =~ s/\034/ /g; $tmp =~ s/^\S*\s*-\s*//; $files = $tmp; } goto nodocs if (!$files); # Nothing to do if ($files =~ /(^| )index\.docbook($| )/) { my $lines = ""; my $lookup = 'MEINPROC\s*='; if ($MakefileData !~ /\n($lookup)/) { $lines = "MEINPROC=/\$(kde_bindir)/meinproc\n"; } $lookup = 'KDE_XSL_STYLESHEET\s*='; if ($MakefileData !~ /\n($lookup)/) { $lines .= "KDE_XSL_STYLESHEET=/\$(kde_datadir)/ksgmltools2/customization/kde-chunk.xsl\n"; } $lookup = '\nindex.cache.bz2:'; if ($MakefileData !~ /\n($lookup)/) { $lines .= "index.cache.bz2: \$(srcdir)/index.docbook \$(KDE_XSL_STYLESHEET) $files\n"; $lines .= "\t\@if test -n \"\$(MEINPROC)\"; then echo \$(MEINPROC) --check --cache index.cache.bz2 \$(srcdir)/index.docbook; \$(MEINPROC) --check --cache index.cache.bz2 \$(srcdir)/index.docbook; fi\n"; $lines .= "\n"; } $lines .= "docs-am: index.cache.bz2\n"; $lines .= "\n"; $lines .= "install-docs: docs-am install-nls\n"; $lines .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n"; $lines .= "\t\@if test -f index.cache.bz2; then \\\n"; $lines .= "\techo \$(INSTALL_DATA) index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n"; $lines .= "\t\$(INSTALL_DATA) index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n"; $lines .= "\telif test -f \$(srcdir)/index.cache.bz2; then \\\n"; $lines .= "\techo \$(INSTALL_DATA) \$(srcdir)/index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n"; $lines .= "\t\$(INSTALL_DATA) \$(srcdir)/index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n"; $lines .= "\tfi\n"; $lines .= "\t-rm -f \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/common\n"; $lines .= "\t\$(LN_S) \$(kde_libs_htmldir)/$kdelang/common \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/common\n"; $lines .= "\n"; $lines .= "uninstall-docs:\n"; $lines .= "\t-rm -rf \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n"; $lines .= "\n"; $lines .= "clean-docs:\n"; $lines .= "\t-rm -f index.cache.bz2\n"; $lines .= "\n"; $target_adds{"install-data-am"} .= "install-docs "; $target_adds{"uninstall"} .= "uninstall-docs "; $target_adds{"clean-am"} .= "clean-docs "; appendLines ($lines); } else { appendLines("docs-am: $files\n"); } $target_adds{"install-data-am"} .= "install-nls "; $target_adds{"uninstall"} .= "uninstall-nls "; $tmp = "install-nls:\n"; $tmp .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n"; $tmp .= "\t\@for base in $files; do \\\n"; $tmp .= "\t echo \$(INSTALL_DATA) \$\$base \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n"; $tmp .= "\t \$(INSTALL_DATA) \$(srcdir)/\$\$base \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n"; $tmp .= "\tdone\n"; if ($appname eq 'common') { $tmp .= "\t\@echo \"merging common and language specific dir\" ;\\\n"; $tmp .= "\tif test ! -f \$(kde_htmldir)/en/common/kde-common.css; then echo 'no english docs found in \$(kde_htmldir)/en/common/'; exit 1; fi \n"; $tmp .= "\t\@com_files=`cd \$(kde_htmldir)/en/common && echo *` ;\\\n"; $tmp .= "\tcd \$(DESTDIR)\$(kde_htmldir)/$kdelang/common ;\\\n"; $tmp .= "\tif test -n \"\$\$com_files\"; then for p in \$\$com_files ; do \\\n"; $tmp .= "\t case \" $files \" in \\\n"; $tmp .= "\t *\" \$\$p \"*) ;; \\\n"; $tmp .= "\t *) test ! -f \$\$p && echo \$(LN_S) ../../en/common/\$\$p \$(DESTDIR)\$(kde_htmldir)/$kdelang/common/\$\$p && \$(LN_S) ../../en/common/\$\$p \$\$p ;; \\\n"; $tmp .= "\t esac ; \\\n"; $tmp .= "\tdone ; fi ; true\n"; } $tmp .= "\n"; $tmp .= "uninstall-nls:\n"; $tmp .= "\tfor base in $files; do \\\n"; $tmp .= "\t rm -f \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n"; $tmp .= "\tdone\n\n"; appendLines ($tmp); $target_adds{"distdir"} .= "distdir-nls "; $tmp = "distdir-nls:\n"; $tmp .= "\tfor file in $files; do \\\n"; $tmp .= "\t cp \$(srcdir)/\$\$file \$(distdir); \\\n"; $tmp .= "\tdone\n"; appendLines ($tmp); return 0; nodocs: appendLines("docs-am:\n"); return 1; } #----------------------------------------------------------------------------- # Find headers in any of the source directories specified previously, that # are candidates for "moc-ing". sub findMocCandidates () { foreach $dir (@headerdirs) { my @list = (); opendir (SRCDIR, "$dir"); @hFiles = grep { /.+\.$hExt$/o && !/^\./ } readdir(SRCDIR); closedir SRCDIR; foreach $hf (@hFiles) { next if ($hf =~ /^\.\#/); $hf =~ /(.*)\.[^\.]*$/; # Find name minus extension next if ($uiFiles{$1}); open (HFIN, "$dir/$hf") || die "Could not open $dir/$hf: $!\n"; my $hfsize = 0; seek(HFIN, 0, 2); $hfsize = tell(HFIN); seek(HFIN, 0, 0); read HFIN, $hfData, $hfsize; close HFIN; # push (@list, $hf) if(index($hfData, "Q_OBJECT") >= 0); ### fast but doesn't handle //Q_OBJECT # handle " { friend class blah; Q_OBJECT ", but don't match antlarr_Q_OBJECT (\b). if ( $hfData =~ /{([^}]*)\bQ_OBJECT/s ) { push (@list, $hf) unless $1 =~ m://[^\n]*Q_OBJECT[^\n]*$:s; ## reject "// Q_OBJECT" } } # The assoc array of root of headerfile and header filename foreach $hFile (@list) { $hFile =~ /(.*)\.[^\.]*$/; # Find name minus extension if ($mocFiles{$1}) { print STDERR "Warning: Multiple header files found for $1\n"; next; # Use the first one } $mocFiles{$1} = "$dir\035$hFile"; # Add relative dir } } return 0; } #----------------------------------------------------------------------------- # The programmer has specified a moc list. Prune out the moc candidates # list that we found based on looking at the header files. This generates # a warning if the programmer gets the list wrong, but this doesn't have # to be fatal here. sub pruneMocCandidates ($) { my %prunedMoc = (); local @mocList = split(' ', $_[0]); foreach $mocname (@mocList) { $mocname =~ s/\.moc$//; if ($mocFiles{$mocname}) { $prunedMoc{$mocname} = $mocFiles{$mocname}; } else { my $print = $makefileDir; $print =~ s/^\Q$topdir\E\\//; # They specified a moc file but we can't find a header that # will generate this moc file. That's possible fatal! print STDERR "Warning: No moc-able header file for $print/$mocname\n"; } } undef %mocFiles; %mocFiles = %prunedMoc; } #----------------------------------------------------------------------------- # Finds the cpp files (If they exist). # The cpp files get appended to the header file separated by \035 sub checkMocCandidates () { my @cppFiles; my $cpp2moc; # which c++ file includes which .moc files my $moc2cpp; # which moc file is included by which c++ files return unless (keys %mocFiles); opendir(THISDIR, ".") || return; @cppFiles = grep { /.+\.$cppExt$/o && !/.+\.moc\.$cppExt$/o && !/.+\.all_$cppExt\.$cppExt$/o && !/^\./ } readdir(THISDIR); closedir THISDIR; return unless (@cppFiles); my $files = join (" ", @cppFiles); $cpp2moc = {}; $moc2cpp = {}; foreach $cxxf (@cppFiles) { open (CXXFIN, $cxxf) || die "Could not open $cxxf: $!\n"; seek(CXXFIN, 0, 2); my $cxxfsize = tell(CXXFIN); seek(CXXFIN, 0, 0); read CXXFIN, $cxxfData, $cxxfsize; close CXXFIN; while(($cxxfData =~ m/^[ \t]*\#include\s*[<\"](.*\.moc)[>\"]/gm)) { $cpp2moc->{$cxxf}->{$1} = 1; $moc2cpp->{$1}->{$cxxf} = 1; } } foreach my $mocFile (keys (%mocFiles)) { @cppFiles = keys %{$moc2cpp->{"$mocFile.moc"}}; if (@cppFiles == 1) { $mocFiles{$mocFile} .= "\035" . $cppFiles[0]; push(@depend, $mocFile); } elsif (@cppFiles == 0) { push (@newObs, $mocFile); # Produce new object file next if ($haveAutomocTag); # This is expected... # But this is an error we can deal with - let them know print STDERR "Warning: No c++ file that includes $mocFile.moc\n"; } else { # We can't decide which file to use, so it's fatal. Although as a # guess we could use the mocFile.cpp file if it's in the list??? print STDERR "Error: Multiple c++ files that include $mocFile.moc\n"; print STDERR "\t",join ("\t", @cppFiles),"\n"; $errorflag = 1; delete $mocFiles{$mocFile}; # Let's continue and see what happens - They have been told! } } } #----------------------------------------------------------------------------- # Add the rules for generating moc source from header files # For Automoc output *.moc.cpp but normally we'll output *.moc # (We must compile *.moc.cpp separately. *.moc files are included # in the appropriate *.cpp file by the programmer) sub addMocRules () { my $cppFile; my $hFile; foreach $mocFile (keys (%mocFiles)) { undef $cppFile; ($dir, $hFile, $cppFile) = split ("\035", $mocFiles{$mocFile}, 3); $dir =~ s#^\.#\$(srcdir)#; if (defined ($cppFile)) { $cppFile =~ s,\.[^.]*$,,; $target_adds{"$cppFile.o"} .= "$mocFile.moc "; $target_adds{"$cppFile.lo"} .= "$mocFile.moc "; appendLines ("$mocFile.moc: $dir/$hFile\n\t\$(TQTMOC) $dir/$hFile -o $mocFile.moc\n"); $cleanMoc .= " $mocFile.moc"; appendLines ("mocs: $mocFile.moc\n"); } else { appendLines ("$mocFile$mocExt: $dir/$hFile\n\t\$(TQTMOC) $dir/$hFile -o $mocFile$mocExt\n"); $cleanMoc .= " $mocFile$mocExt"; appendLines ("mocs: $mocFile$mocExt\n"); } } } sub make_bcheck_target() { my $lookup = 'RECURSIVE_TARGETS\s*=[ \t]*(.*)'; my $bcheckdep = "bcheck-am"; $bcheckdep = "bcheck-recursive" if ($MakefileData =~ /\n$lookup/); my $headers= ""; $headers = $1 if($MakefileData =~ /\nHEADERS\s*=[ \t]*(.+)/); $headers =~ s/\$\((?:noinst|EXTRA)_HEADERS\)//g; $target_adds{"clean-am"} .= "clean-bcheck "; my $t = "clean-bcheck: \n" . "\trm -f *.bchecktest.cc *.bchecktest.cc.class a.out\n\n" . "bcheck: $bcheckdep\n\n" . "bcheck-am:\n" . "\t\@for i in $headers; do \\\n" . "\t if test \$(srcdir)/\$\$i -nt \$\$i.bchecktest.cc; then \\\n" . "\t echo \"int main() {return 0;}\" > \$\$i.bchecktest.cc ; \\\n" . "\t echo \"#include \\\"\$\$i\\\"\" >> \$\$i.bchecktest.cc ; \\\n" . "\t echo \"\$\$i\"; \\\n" . "\t if ! "; $t .= $cxxsuffix eq "KKK" ? "\$(CXX) \$(DEFS) -I. -I\$(srcdir) -I\$(top_builddir) \$(INCLUDES) \$(AM_CPPFLAGS) \$(CPPFLAGS) \$(CXXFLAGS) \$(KDE_CXXFLAGS) " : "\$(CXXCOMPILE) "; $t .= " --dump-class-hierarchy -c \$\$i.bchecktest.cc; then \\\n" . "\t rm -f \$\$i.bchecktest.cc; exit 1; \\\n" . "\t fi ; \\\n" . "\t echo \"\" >> \$\$i.bchecktest.cc.class; \\\n" . "\t perl \$(top_srcdir)/admin/bcheck.pl \$\$i.bchecktest.cc.class || { rm -f \$\$i.bchecktest.cc; exit 1; }; \\\n" . "\t rm -f a.out; \\\n" . "\t fi ; \\\n" . "\tdone\n"; appendLines("$t\n"); } sub make_meta_classes () { return if ($kdeopts{"qtonly"}); my $cppFile; my $hFile; my $moc_class_headers = ""; foreach $program (@programs) { my $mocs = ""; my @progsources = split(/[\034\s]+/, $sources{$program}); my @depmocs = split(' ', $dependmocs{$program}); my %shash = (), %mhash = (); @shash{@progsources} = 1; # we are only interested in the existence @mhash{@depmocs} = 1; print STDOUT "program=$program\n" if ($verbose); print STDOUT "psources=[".join(' ', keys %shash)."]\n" if ($verbose); print STDOUT "depmocs=[".join(' ', keys %mhash)."]\n" if ($verbose); print STDOUT "globalmocs=[".join(' ', keys(%globalmocs))."]\n" if ($verbose); foreach my $mocFile (keys (%globalmocs)) { my ($dir, $hFile, $cppFile) = split ("\035", $globalmocs{$mocFile}, 3); if (defined ($cppFile)) { $mocs .= " $mocFile.moc" if exists $shash{$cppFile}; } else { # Bah. This is the case, if no C++ file includes the .moc # file. We make a .moc.cpp file for that. Unfortunately this # is not included in the %sources hash, but rather is mentioned # in %dependmocs. If the user wants to use AUTO he can't just # use an unspecific METAINCLUDES. Instead he must use # program_METAINCLUDES. Anyway, it's not working real nicely. # E.g. Its not clear what happens if user specifies two # METAINCLUDES=AUTO in the same Makefile.am. $mocs .= " $mocFile.moc.$cxxsuffix" if exists $mhash{$mocFile.".moc.$cxxsuffix"}; } } if ($mocs) { print STDOUT "==> mocs=[".$mocs."]\n" if ($verbose); } print STDOUT "\n" if $verbose; } if ($moc_class_headers) { appendLines ("$cleantarget-moc-classes:\n\t-rm -f $moc_class_headers\n"); $target_adds{"$cleantarget-am"} .= "$cleantarget-moc-classes "; } } #----------------------------------------------------------------------------- sub updateMakefile () { return if ($dryrun); open (FILEOUT, "> $makefile") || die "Could not create $makefile: $!\n"; $MakefileData =~ s/\034/\\\n/g; # Restore continuation lines # Append our $progId line, _below_ the "generated by automake" line # because automake-1.6 relies on the first line to be his own. my $progIdLine = "\# $progId - " . '$Revision$ '."\n"; if ( !( $MakefileData =~ s/^(.*generated .*by automake.*\n)/$1$progIdLine/ ) ) { warn "automake line not found in $makefile\n"; # Fallback: first line print FILEOUT $progIdLine; }; print FILEOUT $MakefileData; close FILEOUT; } #----------------------------------------------------------------------------- # The given line needs to be removed from the makefile # Do this by adding the special "removed line" comment at the line start. sub removeLine ($$) { my ($lookup, $old) = @_; $old =~ s/\034/\\\n#>- /g; # Fix continuation lines $MakefileData =~ s/\n$lookup/\n#>\- $old/; } #----------------------------------------------------------------------------- # Replaces the old line with the new line # old line(s) are retained but tagged as removed. The new line(s) have the # "added" tag placed before it. sub substituteLine ($$) { my ($lookup, $new) = @_; if ($MakefileData =~ /\n($lookup)/) { $old = $1; $old =~ s/\034/\\\n#>\- /g; # Fix continuation lines my $newCount = ($new =~ tr/\034//) + ($new =~ tr/\n//) + 1; $new =~ s/\\\n/\034/g; $MakefileData =~ s/\n$lookup/\n#>- $old\n#>\+ $newCount\n$new/; } else { warn "Warning: substitution of \"$lookup\" in $printname failed\n"; } } #----------------------------------------------------------------------------- # Slap new lines on the back of the file. sub appendLines ($) { my ($new) = @_; my $copynew = $new; my $newCount = ($new =~ tr/\034//) + ($new =~ tr/\n//) + 1; $new =~ s/\\\n/\034/g; # Fix continuation lines $MakefileData .= "\n#>\+ $newCount\n$new"; } #----------------------------------------------------------------------------- # Restore the Makefile.in to the state it was before we fiddled with it sub restoreMakefile () { $MakefileData =~ s/# $progId[^\n\034]*[\n\034]*//g; # Restore removed lines $MakefileData =~ s/([\n\034])#>\- /$1/g; # Remove added lines while ($MakefileData =~ /[\n\034]#>\+ ([^\n\034]*)/) { my $newCount = $1; my $removeLines = ""; while ($newCount--) { $removeLines .= "[^\n\034]*([\n\034]|)"; } $MakefileData =~ s/[\n\034]#>\+.*[\n\034]$removeLines/\n/; } } #----------------------------------------------------------------------------- # find the .kcfg file listed in the .kcfgc file sub findKcfgFile($) { my ($kcfgf) = @_; open (KCFGFIN, $kcfgf) || die "Could not open $kcfgf: $!\n"; seek(KCFGFIN, 0, 2); my $kcfgfsize = tell(KCFGFIN); seek(KCFGFIN, 0, 0); read KCFGFIN, $kcfgfData, $kcfgfsize; close KCFGFIN; if(($kcfgfData =~ m/^File=(.*\.kcfg)/gm)) { $kcfg = $1; } }