Mercurial > hg > buildtools
diff autopoop @ 0:d72d5d73b93a
Added Autopoop and mkchangelog.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 22 Apr 2008 14:31:44 +0300 |
parents | |
children | 5665a846d227 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autopoop Tue Apr 22 14:31:44 2008 +0300 @@ -0,0 +1,257 @@ +#!/usr/bin/perl -w +# autopoop v0.57 (C) 2008 Matti 'ccr' Hamalainen +# +# Tries to generate extra.mk.in from known configure.ac and other +# autoconf m4-macros, scanning against Makefiles. Also checks for +# missing / unsubstituted symbols, etc. +# +# Requirements: +# - Recent enough GNU Autoconf (and requirements for that) +# - Perl 5 +# +# TODO: +# - see fixmes +# - document this +# - find bugs +# - ??? +# - profit +# +use strict; +use Cwd qw(getcwd realpath); + +# List of subdirectories to check for additional Autoconf m4 macros +my @m4testdirs = ("m4", "unix"); + +# Misc. settings +my $makefile = "Makefile"; +my $extrasys = "extra.mk"; +my $buildsys = "buildsys.mk"; +my $tmpfile = "autopoop.tmp"; +my $autom4te = "autom4te"; + +# Things that may be set by user +my %bsdefines = ( + "DESTDIR" => 1, +); + +# Special substitutions +my %confdefines = ( +# "VPATH" => "srcdir", +# "SET_MAKE" => "", +); + + +### Function prototypes +sub shortpath($); +sub scanfile($$$$$$$$); + + +### Argument handling +my $pcwd = getcwd(); +my $argc = ($#ARGV + 1); +print "Autopoop v0.57 (C) 2008 Matti 'ccr' Hamalainen\n"; +die("Usage: autopoop <configurefile> <outfile> [autom4te options]\n". +"Example: autopoop configure.ac extra.mk.in\n\n". +"NOTICE! Assumes following files are used:\n". +"$buildsys\[.in\], $extrasys, $makefile\n\n") unless ($argc >= 2); +my $configure = shift; +my $outfile = shift; + + +### Execute Autoconf 'autom4te' ... +my @args = (@ARGV); +foreach my $dir (@m4testdirs) { + if (-d $dir) { push(@args, ("-I", $dir)); } +} + +push(@args, ( + "--force", "--no-cache", "--melt", "--language=autoconf", + "--trace=AC_SUBST", "-o", $tmpfile, $configure)); + +print "- Running $autom4te ".join(" ", @args)." ...\n"; +system($autom4te, @args) == 0 or die("Failed to execute $autom4te: $?\n"); + + +### Paf files +$buildsys = realpath($buildsys); +$extrasys = realpath($extrasys); +$outfile = realpath($outfile); + + +### Process results +open(INFILE,"<".$tmpfile) or die("Could not open '$tmpfile'!\n"); +while (<INFILE>) { + chop; + my @entries = split(/:/); + my $key = $entries[3]; + unless ($key =~ /_(FALSE|TRUE)$/) { $confdefines{$key} = $key; } +} +close INFILE; +unlink($tmpfile); + + +### Scan Makefiles and depencies +my %makesubsts = (); +my %confsubsts = (); +my %makedefines = (); +my %scanned = ($outfile => 1, $extrasys => 1); +scanfile(".", $makefile, \%scanned, \%makesubsts, \%confsubsts, \%makedefines, 1, 1); +scanfile("", $buildsys, \%scanned, \%makesubsts, \%confsubsts, \%makedefines, 1, 0); + + +### Scan buildsys.mk.in +my %bssubsts = (); +scanfile("", $buildsys.".in", \%scanned, \%bssubsts, \%bssubsts, \%bsdefines, 0, 0); + + +my %globdefs = (); +foreach my $file (keys %makedefines) { + foreach my $s (keys %{$makedefines{$file}}) { + $globdefs{$s} = 1; + } +} + + +### Compare results +print "- Checking for used, but possibly undefined Make variables:\n"; +foreach my $file (keys %makesubsts) { + foreach my $s (sort { $a cmp $b } keys %{$makesubsts{$file}}) { + if (!defined($confdefines{$s}) && !defined($makedefines{$file}{$s}) && !defined($bsdefines{$s})) { + my $err = 0; + if (!defined($globdefs{$s})) { + $err = 1; + } elsif ($file ne $buildsys && $file ne $outfile) { + $err = 2; + } + if ($err) { + printf " %-20s", "'$s'"; + print " in ".shortpath($file).":".$makesubsts{$file}{$s}." ($err)\n"; + } + } + } +} +print qq|Legend: + (1) = Not defined anywhere (or misdetected). + (2) = Defined 'somewhere', but unsure if symbol is propagated. + +|; + + +print "- Checking for used, but possibly undefined substitutions:\n"; +foreach my $file (keys %confsubsts) { + foreach my $s (keys %{$confsubsts{$file}}) { + if (!defined($confdefines{$s})) { + printf " %-20s", "'$s'"; + print " in ".shortpath($file).":".$confsubsts{$file}{$s}."\n"; + } + } +} +print "\n"; + + +### Output stuff +print "- Outputting '$outfile'\n"; +open(OUTFILE, ">", $outfile) or die("Could not open '$outfile'!\n"); +foreach my $s (keys %confdefines) { + if ($confdefines{$s} ne "") { + print OUTFILE "$s ?= \@".$confdefines{$s}."\@\n"; + } else { + print OUTFILE "\@".$s."\@\n"; + } +} +close OUTFILE; + +print "- Done.\n"; + + +### +### Functions +### +sub shortpath($) { + if (index($_[0], $pcwd) == 0) { + return substr($_[0], length($pcwd) + 1); + } else { + return $_[0]; + } +} + +sub addhash($$$$$) +{ +# if ($usenames) { $substs->{$filename}{$1} = $line; } else { $substs->{$1} = $line; } + if ($_[0]) { + $_[1]->{$_[2]}{$_[3]} = $_[4]; + } else { + $_[1]->{$_[3]} = $_[4]; + } +} + +sub scanfile($$$$$$$$) { + my $mypath = $_[0]; + my $myfile = $_[1]; + + my $scanned = $_[2]; + my $substs = $_[3]; + my $confsubsts = $_[4]; + my $defines = $_[5]; + + my $usenames = $_[6]; + my $recurse = $_[7]; + + # Form real path and check if we have already scanned the file + my $filename = realpath($mypath."/".$myfile); + if (defined($filename)) { + if (defined($scanned->{$filename})) { + $scanned->{$filename}++; + return; + } + $scanned->{$filename} = 1; + } else { + $filename = $mypath."/".$myfile; + } + +#print "ASDF: $filename\n"; + + # Scan file, if found + if (open(my $SCANFILE, "<", $filename)) { + print "- Scanning ".shortpath($filename)." ...\n"; + my $line = 0; + while (<$SCANFILE>) { + $line++; + chop; + if (/^#/) { + # ignore comment lines + } else { + + while (/[^\$]\$\{([A-Za-z0-9_]+)\}/g) { + addhash($usenames, $substs, $filename, $1, $line); + } + while (/[^\$]\$\(([A-Za-z0-9_]+)\)/g) { + addhash($usenames, $substs, $filename, $1, $line); + } + while (/\@([A-Za-z0-9_]+)\@/g) { + addhash($usenames, $confsubsts, $filename, $1, $line); + } + + if (/^ifdef\s+([A-Za-z0-9_]+)/g) { + addhash($usenames, $substs, $filename, $1, $line); + } elsif (/^([A-Za-z][A-Za-z0-9_]+)\s*[\+]?=/) { + addhash($usenames, $defines, $filename, $1, $line); + } + elsif (/^include (\S+)/) { + scanfile($mypath, "$1", $scanned, $substs, $confsubsts, $defines, $usenames, $recurse); + } + } + } + close $SCANFILE; + } + + # Recurse into subdirectories + if ($recurse) { + opendir(DIR, $mypath) || return; + my @dirs = grep { /^[^\.]/ && -d "$mypath/$_" } readdir(DIR); + closedir(DIR); + foreach my $dir (@dirs) { + scanfile($mypath."/".$dir, $myfile, $scanned, $substs, $confsubsts, $defines, $usenames, $recurse); + } + } +}