diff options
Diffstat (limited to 'dmakegen')
-rwxr-xr-x | dmakegen | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/dmakegen b/dmakegen new file mode 100755 index 0000000..b6b13b3 --- /dev/null +++ b/dmakegen @@ -0,0 +1,156 @@ +#!/usr/bin/perl +# $Id$ +# +# dmakegen - a preprocessor for GNU make to make make directory-aware +# + +undef %Generics, $Default; + + +$err = 0; +$nline = 0; +open(DMAKEROOT, "< Dmakeroot") or die "$0: No Dmakeroot file found\n"; +while ( defined($line = <DMAKEROOT>) ) { + chomp $line; $nline++; + while ( $line =~ /\\$/ ) { + if ( defined($cline = <DMAKEROOT>) ) { + chomp $cline; $nline++; + $line = substr($line, 0, length($line)-1) + $cline; + } else { + die "$0: Dmakeroot:$nline: unterminated continuation line\n"; + $err = 1; + } + } + + $line =~ s/\#.*$//; # Remove comments + $line =~ s/\s*$//; # Remove trailing whitespace + + if ( $line eq '' ) { + # Empty line, do nothing + } elsif ( $line =~ /^GENERIC:\s*/ ) { + foreach $generic ( split(/\s+/, $') ) { + $Generics{$'} = []; + } + push(Generics, split(/\s+/, $')); + } elsif ( $line =~ /^DEFAULT:\s*/ ) { + $Default = $'; + } else { + print "$0: Dmakeroot:$nline: unknown directive\n"; + $err = 1; + } +} +close(DMAKEROOT); +if ( $err ) { + exit(1); +} + +# +# Recurse through various directories and generate Dmakefragment files +# +@dirlist = ('.'); +@dmakefrags = (); + +while ( defined($dir = pop(@dirlist)) ) { + open(DMAKEFILE, "< ${dir}/Dmakefile") or die "$0: ${dir}/Dmakefile not found\n"; + open(DMAKEFRAG, "> ${dir}/Dmakefrag") or die "$0: Cannot create ${dir}/Dmakefrag: $!\n"; + push(@dmakefrags, "${dir}/Dmakefrag"); + + $nline = 0; $err = 0; + while ( defined($line = <DMAKEFILE>) ) { + chomp $line; $nline++; + while ( $line =~ /\\$/ ) { + if ( defined($cline = <DMAKEFILE>) ) { + chomp $cline; $nline++; + $line = substr($line, 0, length($line)-1) + $cline; + } else { + die "$0: ${dir}/Dmakefile:$nline: unterminated continuation line\n"; + $err = 1; + } + } + + ### FIX: THIS IS BUGGY - NEED TO HANDLE ESCAPES ### + $line =~ s/\#.*$//; # Remove comments + $line =~ s/\s*$//; # Remove trailing spaces + + if ( $line eq '' ) { + # Do nothing + } elsif ( $line =~ /^SUBDIRS:\s*/ ) { + push(@dirlist, split(/\s+/, $')); + } elsif ( $line =~ /^\.([^.:]+):\s*(.*)$/ ) { + # Rule of the form .c: + $suffix = $1; + $deps = $2; + print DMAKEFRAG "${dir}/%: ${dir}/%.${suffix}"; + if ( $deps ne '' ) { + foreach $dep ( split(/\s+/, $deps) ) { + print DMAKEFRAG " ${dir}/${dep}"; + } + } + print "\n"; + } elsif ( $line =~ /^\.([^.:])\.([^.:]+):\s*(.*)$/ ) { + # Rule of the form .c.o: + $suff1 = $1; + $suff2 = $2; + $deps = $3; + print DMAKEFRAG "${dir}/%.${suff2}: ${dir}/%.${suff1}"; + if ( $deps ne '' ) { + foreach $dep ( split(/\s+/, $deps) ) { + print DMAKEFRAG " ${dir}/${dep}"; + } + } + print "\n"; + } elsif ( $line =~ /^(\S|\S.*\S)\s*:\s*(\S|\S.*\S)\s*$/ ) { + # Rule of the form foo .. : bar + $lhs = $1; + $rhs = $2; + if ( $lhs ne '' ) { + foreach $targ ( split(/\s+/, $lhs) ) { + if ( defined($Generics{$targ}) ) { + push(@{$Generics{$targ}}, "${dir}/${targ}"); + print DMAKEFRAG ".PHONY: ${dir}/${targ}\n"; + } + print DMAKEFRAG " ${dir}/${targ}"; + } + } + print DMAKEFRAG " : "; + if ( $rhs ne '' ) { + foreach $deps ( split(/\s+/, $rhs) ) { + print DMAKEFRAG " ${dir}/${deps}"; + } + } + print "\n"; + } elsif ( $line =~ /^(\s+)(\S.*)$/ ) { + print DMAKEFRAG "$1cd \"${dir}\" && $2\n"; + } else { + # Handle stuff like local variables here + } + } + close(DMAKEFILE); + close(DMAKEFRAG); +} + +# +# Create the Makefile +# +open(MAKEFILE, "> Makefile") or die "$0: Could not create Makefile\n"; + +print MAKEFILE ".default: ${Default}\n\n"; + +print MAKEFILE "Makefile:\n\tdmakegen\n\n"; + +foreach $gen ( keys(%Generics) ) { + print MAKEFILE ".PHONY: ${gen}\n"; + print MAKEFILE "${gen}: "; + foreach $subtarg ( @{$Generics{$gen}} ) { + print MAKEFILE $subtarg, ' '; + } + print MAKEFILE "\n"; +} + +# Must be done in reverse order (leaf node directories +# before the associated branch node.) +while ( defined($frag = pop(@dmakefrags)) ) { + print "-include ${frag}\n"; +} + +close(MAKEFILE); |