File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / mkdep.pl
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:23:02 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: #!/usr/bin/env perl
    2: 
    3: use File::Temp qw/ :mktemp  /;
    4: use Fcntl;
    5: use warnings;
    6: 
    7: die "usage: $0 Makefile ...\n" unless $#ARGV >= 0;
    8: 
    9: my @incpaths;
   10: my %dir_vars;
   11: my %implicit;
   12: 
   13: # Read in MANIFEST fail if present
   14: my %manifest;
   15: if (open(MANIFEST, "<MANIFEST")) {
   16:     while (<MANIFEST>) {
   17: 	chomp;
   18: 	next unless /([^\/]+\.[cly])$/;
   19: 	$manifest{$1} = $_;
   20:     }
   21: }
   22: 
   23: foreach (@ARGV) {
   24:     mkdep($_);
   25: }
   26: 
   27: sub mkdep {
   28:     my $file = $_[0];
   29:     $file =~ s:^\./+::;		# strip off leading ./
   30: 
   31:     my $makefile;
   32:     if (open(MF, "<$file")) {
   33: 	local $/;		# enable "slurp" mode
   34: 	$makefile = <MF>;
   35:     } else {
   36: 	warn "$0: $file: $!\n";
   37: 	return undef;
   38:     }
   39:     close(MF);
   40: 
   41:     # New makefile, minus the autogenerated dependencies
   42:     my $separator = "# Autogenerated dependencies, do not modify";
   43:     my $new_makefile = $makefile;
   44:     $new_makefile =~ s/${separator}.*$//s;
   45:     $new_makefile .= "$separator\n";
   46: 
   47:     # Old makefile, join lines with continuation characters
   48:     $makefile =~ s/\\\n//mg;
   49: 
   50:     # Expand some configure bits
   51:     $makefile =~ s:\@COMMON_OBJS\@:aix.lo:;
   52:     $makefile =~ s:\@SUDO_OBJS\@:preload.o selinux.o sesh.o sudo_noexec.lo:;
   53:     $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo plugin_error.lo:;
   54:     # XXX - fill in AUTH_OBJS from contents of the auth dir instead
   55:     $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb4.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid.lo securid5.lo sia.lo:;
   56:     $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo dlopen.lo fnmatch.lo getcwd.lo getgrouplist.lo getline.lo getprogname.lo glob.lo isblank.lo memrchr.lo mksiglist.lo mktemp.lo nanosleep.lo setenv.lo siglist.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo unsetenv.lo utimes.lo globtest.o fnm_test.o:;
   57: 
   58:     # Parse OBJS lines
   59:     my %objs;
   60:     while ($makefile =~ /^[A-Z0-9_]*OBJS\s*=\s*(.*)/mg) {
   61: 	foreach (split/\s+/, $1) {
   62: 	    next if /^\$[\(\{].*[\)\}]$/; # skip included vars for now
   63: 	    $objs{$_} = 1;
   64: 	}
   65:     }
   66: 
   67:     # Find include paths
   68:     @incpaths = ();
   69:     while ($makefile =~ /-I(\S+)/mg) {
   70: 	push(@incpaths, $1) unless $1 eq ".";
   71:     }
   72: 
   73:     # Values of srcdir, top_srcdir, top_builddir, incdir
   74:     %dir_vars = ();
   75:     $file =~ m:^(.*)/+[^/]+:;
   76:     $dir_vars{'srcdir'} = $1 || '.';
   77:     $dir_vars{'devdir'} = $dir_vars{'srcdir'};
   78:     $dir_vars{'authdir'} = $dir_vars{'srcdir'} . "/auth";
   79:     $dir_vars{'top_srcdir'} = '.';
   80:     #$dir_vars{'top_builddir'} = '.';
   81:     $dir_vars{'incdir'} = 'include';
   82: 
   83:     # Find implicit rules for generate .o and .lo files
   84:     %implicit = ();
   85:     while ($makefile =~ /^\.c\.(l?o):\s*\n\t+(.*)$/mg) {
   86: 	$implicit{$1} = $2;
   87:     }
   88: 
   89:     # Find existing .o and .lo dependencies
   90:     my %old_deps;
   91:     while ($makefile =~ /^(\w+\.l?o):\s*(\S+\.c)/mg) {
   92: 	$old_deps{$1} = $2;
   93:     }
   94: 
   95:     # Sort files so we do .lo files first
   96:     foreach my $obj (sort keys %objs) {
   97: 	next unless $obj =~ /(\S+)\.(l?o)$/;
   98: 	if ($2 eq "o" && exists($objs{"$1.lo"})) {
   99: 	    # If we have both .lo and .o files, make the .o depend on the .lo
  100: 	    $new_makefile .= sprintf("%s: %s.lo\n", $obj, $1);
  101: 	} else {
  102: 	    # Use old depenencies when mapping objects to their source.
  103: 	    # If no old depenency, use the MANIFEST file to find the source.
  104: 	    my $src = $1 . '.c';
  105: 	    my $ext = $2;
  106: 	    if (exists $old_deps{$obj}) {
  107: 		$src = $old_deps{$obj};
  108: 	    } elsif (exists $manifest{$src}) {
  109: 		$src = $manifest{$src};
  110: 		foreach (sort { length($b) <=> length($a) } keys %dir_vars) {
  111: 		    last if $src =~ s:^\Q$dir_vars{$_}/\E:\$\($_\)/:;
  112: 		}
  113: 	    } else {
  114: 		warn "$file: unable to find source for $obj\n";
  115: 	    }
  116: 	    my $imp = $implicit{$ext};
  117: 	    $imp =~ s/\$</$src/g;
  118: 
  119: 	    my $deps = sprintf("%s: %s %s", $obj, $src,
  120: 		join(' ', find_depends($src)));
  121: 	    if (length($deps) > 80) {
  122: 		my $off = 0;
  123: 		my $indent = length($obj) + 2;
  124: 		while (length($deps) - $off > 80 - $indent) {
  125: 		    my $pos;
  126: 		    if ($off != 0) {
  127: 			$new_makefile .= ' ' x $indent;
  128: 			$pos = rindex($deps, ' ', $off + 80 - $indent - 2);
  129: 		    } else {
  130: 			$pos = rindex($deps, ' ', $off + 78);
  131: 		    }
  132: 		    $new_makefile .= substr($deps, $off, $pos - $off) . " \\\n";
  133: 		    $off = $pos + 1;
  134: 		}
  135: 		$new_makefile .= ' ' x $indent;
  136: 		$new_makefile .= substr($deps, $off) . "\n";
  137: 	    } else {
  138: 		$new_makefile .= "$deps\n";
  139: 	    }
  140: 	    $new_makefile .= "\t$imp\n";
  141: 	}
  142:     }
  143: 
  144:     rename($file, $file . ".old");
  145:     if (!open(MF, ">$file")) {
  146: 	warn("cannot open $file: $!\n");
  147: 	rename($file . ".old", $file);
  148:     } else {
  149: 	print MF $new_makefile || warn("cannot write $file: $!\n");
  150: 	close(MF);
  151:     }
  152: }
  153: 
  154: exit(0);
  155: 
  156: sub find_depends {
  157:     my $src = $_[0];
  158:     my ($deps, $code, @headers);
  159: 
  160:     if ($src !~ /\//) {
  161: 	# XXX - want build dir not src dir
  162: 	$src = "$dir_vars{'srcdir'}/$src";
  163:     }
  164: 
  165:     # resolve $(srcdir) etc.
  166:     foreach (keys %dir_vars) {
  167: 	$src =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
  168:     }
  169: 
  170:     # find open source file and find headers used by it
  171:     if (!open(FILE, "<$src")) {
  172: 	warn "unable to open $src\n";
  173: 	return "";
  174:     }
  175:     local $/;		# enable "slurp" mode
  176:     $code = <FILE>;
  177:     close(FILE);
  178: 
  179:     # find all headers
  180:     while ($code =~ /^#\s*include\s+["<](\S+)[">]/mg) {
  181: 	my ($hdr, $hdr_path) = find_header($1);
  182: 	if (defined($hdr)) {
  183: 	    push(@headers, $hdr);
  184: 	    # Look for other includes in the .h file
  185: 	    push(@headers, find_depends($hdr_path));
  186: 	}
  187:     }
  188: 
  189:     @headers;
  190: }
  191: 
  192: # find the path to a header file
  193: # returns path or undef if not found
  194: sub find_header {
  195:     my $hdr = $_[0];
  196: 
  197:     # Look for .h.in files in top_builddir and build dir
  198:     return ("\$(top_builddir\)/$hdr", "./${hdr}.in") if -r "./${hdr}.in";
  199:     return ("./$hdr", "$dir_vars{'srcdir'}/${hdr}.in") if -r "$dir_vars{'srcdir'}/${hdr}.in";
  200: 
  201:     foreach my $inc (@incpaths) {
  202: 	my $hdr_path = "$inc/$hdr";
  203: 	# resolve variables in include path
  204: 	foreach (keys %dir_vars) {
  205: 	    $hdr_path =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
  206: 	}
  207: 	return ("$inc/$hdr", $hdr_path) if -r $hdr_path;
  208:     }
  209: 
  210:     undef;
  211: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>