#! /usr/local/bin/perl # Changes Makefile.in to work correctly with moc files. When called # without parameters, automoc works recursively on all Makefile.in in # and below the current subdirectory. When called with parameters, # only these Makefile.in are changed. # The Makefile.in should have an entry with the following syntax: # # {program}_METASOURCES = USE_AUTOMOC [{suffix}] # # Moc files will have a 'cpp' suffix unless overriden by the optional # {suffix} parameter. # Be careful not to use a suffix that isn't used by at least one # of the main source files in {program}_SOURCES. # # 1998-07-23 Harri Porten # * small bugfixes for MOCSOURCES # 1998-11-08 Alex Zepeda # * tweak it so it will run from a "common" directory. # 1998-11-11 Harri Porten & David Faure # * bug fix for invocation with arguments # 1998-11-16 Harri Porten # * take care of "ar" object files, too. # (as proposed by Martin Vogt ) # 1999-01-13 Harri Porten # * implemented {suffix} parameter # 1999-01-16 Stephan Kulow # * implemented support for included MOC files and command line # parameters use Cwd; use File::Find; use File::Basename; # TRUE if in verbose mode. $verbose = 0; $direct_arguments = 0; @arglist = @ARGV; @input_files = (); $errorflag = 0; $printname = ''; $lastdirname = ''; @mocnames = (); $callpath = "$0"; @header_suffixes = ("h", "H", "hh", "hxx"); $cxx_suffix = ""; while (@arglist) { if ($arglist[0] eq "--version") { print "\n\n"; print "*********************************************\n"; print "automoc - Software that makes even more sense\n"; print "*********************************************\n\n"; print "Welcome to the wonderful world of automoc!\n"; print "This is really free software, unencumbered by the GPL.\n"; print "You can do anything you like with it except sueing me.\n"; print "Copyright 1998 Kalle Dalheimer \n"; print "Concept, design and unnecessary questions about Perl by Matthias Ettrich \n\n"; print "Making it useful by Stephan Kulow and\n"; print "Harri Porten "; exit 0; } elsif ($arglist[0] eq '--verbose' || $arglist[0] eq '-v') { $verbose = 1; } elsif ($arglist[0] =~ /^-p(.+)$/ || $arglist[0] =~ /^--path=(.+)$/) { $callpath = "$1/" . basename($0); } elsif ($arglist[0] =~ /^--help$/ || $arglist[0] =~ /^-h$/) { print "Usage automoc [OPTION] ... [Makefile.in]...\n"; print "\n"; print "Patches Makefile.in generated from automake\n"; print "\n"; print " -v, --verbose verbosely list files processed\n"; print " -h, --help print this help, then exit\n"; print " --version print version number, then exit\n"; print " -p, --path= use the path to automoc if the path\n"; print " called from is not the one to be used\n"; exit 0; } else { push (@input_files, $arglist[0]); $direct_arguments = 1; } shift @arglist; } if ($direct_arguments == 0) { find( \&add_makefile, cwd() ); } $curdir = cwd(); while( @input_files ) { $filename = $input_files[0]; $errorflag = 0; undef @headersourcedirs; @headersourcedirs = ('$(srcdir)'); process_makefile( $filename ); chdir ( $curdir); shift @input_files; } sub add_makefile() { if( $_ ne "Makefile.in" ) { return; } else { push (@input_files, $File::Find::name ); } } sub process_automoc_makefile { # find the name of the program $search_use_automoc[0] =~ /^([^=]*)_METASOURCES/; $programname = $1; $cxx_suffix = "cpp"; # check whether a suffix is given if( $search_use_automoc[0] =~ /USE_AUTOMOC\s+([^\s]+)/ ) { $cxx_suffix = $1; } $header_list = ""; foreach $suffix (@header_suffixes) { $header_list .= " *.$suffix"; } @mocable_files = `grep -l Q_OBJECT $header_list 2> /dev/null`; foreach $mocable_file (@mocable_files) { chomp $mocable_file; print STDERR "looking for header file $mocable_file\n" if $verbose; $mocable_file =~ s/\.[^\.]*$//; # remove the suffix (.h etc) push @mocnames, $mocable_file; push @mocsources, "$mocable_file\.moc\.$cxx_suffix"; } $objectline = $programname . "_OBJECTS"; LINE: while( ) { if( /^#/ ) { print FILEOUT $_; next LINE; } if( /(.*_METASOURCES\s*=\s*)(USE_AUTOMOC)/ ) { print FILEOUT "$1 "; foreach $mocsource (@mocsources) { print FILEOUT $mocsource . " "; } print FILEOUT "\n"; } elsif( /^$objectline/ ) # look for programs and libraries { chomp $_; $line = $_; $morelines = /\\$/ ? 1 : 0; $line =~ s/\\$//; print FILEOUT "$line "; foreach $mocname (@mocnames) { if ( $objectline !~ /_la_OBJECTS$/ ) { print FILEOUT $mocname . ".moc.o "; } else { print FILEOUT $mocname . ".moc.lo "; } } if($morelines) { print FILEOUT "\\"; } print FILEOUT "\n"; } else { process_generell_rules($_); } } print FILEOUT "\n\n"; foreach $file (@mocnames) { foreach $header_suffix (@header_suffixes) { if (-f $file . ".$header_suffix") { print FILEOUT "$file.moc.$cxx_suffix: \$(srcdir)/$file.$header_suffix\n"; print FILEOUT "\t\$(MOC) \$(srcdir)/$file.$header_suffix -o $file.moc.$cxx_suffix\n\n"; last; } } } } sub process_generell_rules { if ( m+cd \$\(top_srcdir\) \&\& \$\(AUTOMAKE\)+ ) { print FILEOUT $_; print FILEOUT "\tcd \$(top_srcdir) && perl $callpath $printname\n"; return; } if (/^distclean:/) { s/^distclean: //; print FILEOUT "distclean: distclean-metasources "; } if (/^[^=]*META_INCLUDES.*=(.*)/) { chomp $1; @list = split(' ', $1); for $dir (@list) { $realdir = $dir; $realdir =~ s#\$\(srcdir\)#.#; if (! -d $realdir) { print STDERR "$printname: warning $dir can't be found. Must be a relative path to \$(srcdir)\n"; } else { if ($dir !~ /\$\(srcdir\)/) { $dir = "\$(srcdir)/" . $dir; print STDERR "addded $dir\n"; } push @headersourcedirs, $dir; } } } print FILEOUT $_; } sub process_moc_makefile() { local ($saw_bk) = 0; LINE: while( ) { if ( /^#/ ) { print FILEOUT $_; next LINE; } $textline = $_; if ($textline =~ /^[^=]*METASOURCES.*/ || $saw_bk) { $saw_bk = /\\$/; $line=$textline; $line =~ s/\\$//; $line =~ s/.*METASOURCES.*=[ ]*//; @list = split(' ', $line); foreach $mocname (@list) { if ($mocname !~ /\.moc$/) { print STDERR "error: filename $lastdirname/$mocname doesn't end with .moc\n"; $errorflag = 1; } else { $mocname =~ s/\.moc$//; push(@mocnames, $mocname); } } } else { $saw_bk = 0; } process_generell_rules($textline); } if (@mocnames) { print FILEOUT "\n\n"; } foreach $mocfile (@mocnames) { print STDERR "Looking for moc file $mocfile.moc\n" if $verbose; $found = 0; $header_suffix = ""; foreach $dir (@headersourcedirs) { $realdir = $dir; $realdir =~ s/\$\(srcdir\)/./; foreach $suffix (@header_suffixes) { if (-f $realdir . '/' . $mocfile . ".$suffix") { $header_suffix = $suffix; $sourcedir = $dir; $found = 1; last; } } } if ($found == 0) { print STDERR "error: no header file found for mocfile $lastdirname/$mocfile.moc\n"; $errorflag = 1; } @sourcenames=`grep -l "^#include[ ]*.$mocfile\.moc." *.cpp *.cc *.cxx *.C 2> /dev/null`; if (@sourcenames == 1) { $sourcename = $sourcenames[0]; $sourcename =~ s/\n$//; } else { if (@sourcenames == 0) { print STDERR "error: no source file found for mocfile $lastdirname/$mocfile.moc\n"; } else { print STDERR "error: Multiple source files found for mocfile $lastdirname/$mocfile.moc\n"; print STDERR "\t",join ("\t", @sourcenames),"\n"; } $errorflag = 1; } print FILEOUT "\$(srcdir)/$sourcename: $mocfile.moc\n"; print FILEOUT "$mocfile.moc: $sourcedir/$mocfile.$header_suffix\n"; print FILEOUT "\t\$(MOC) $sourcedir/$mocfile.$header_suffix -o $mocfile.moc\n"; print FILEOUT "\n"; } } sub process_makefile { $printname = $filename; $printname = substr ($printname, length($curdir)+1); $lastdirname = dirname($filename); $lastdirname = substr ($lastdirname, length($curdir)+1); print STDERR "Processing " .$printname . "\n" if $verbose; chdir( dirname( $filename ) ); $filename = basename($filename); $search = `grep '[^=#]*METASOURCES.*=' $filename`; return if ($search eq ''); $search = `grep "DO_NOT_USE_AUTOMOC" $filename`; return if ($search); $newfilename = $filename . ".tmp"; open( FILEIN, "$filename" ) or die "Could not open $filename: $!\n"; open( FILEOUT, ">$newfilename" ) or die "Could not open $filename: $!\n"; # search for USE_AUTOMOC @search_use_automoc = `grep "[^#]*USE_AUTOMOC" $filename`; if( @search_use_automoc == 0 ) { process_moc_makefile(); $cxx_suffix=""; } else { process_automoc_makefile(); $cxx_suffix="." . $cxx_suffix; } print FILEOUT "distclean-metasources:\n"; if (@mocnames) { print FILEOUT "\t-rm -f "; foreach $mocfile (@mocnames) { print FILEOUT $mocfile . ".moc$cxx_suffix "; } } print FILEOUT "\n"; if ($errorflag == 0) { print FILEOUT "\n# DO_NOT_USE_AUTOMOC\n"; rename $newfilename, $filename; } else { system("rm $newfilename"); exit 1; # cause the make to stop. (added 28/01/99 jbb) # (I've a bad feeling about this Stephan!) } undef @mocsources; undef @mocnames; }