3 use File::Temp qw/ :mktemp /;
7 die "usage: $0 Makefile ...\n" unless $#ARGV >= 0;
13 # Read in MANIFEST fail if present
15 if (open(MANIFEST, "<MANIFEST")) {
18 next unless /([^\/]+\.[cly])$/;
29 $file =~ s:^\./+::; # strip off leading ./
32 if (open(MF, "<$file")) {
33 local $/; # enable "slurp" mode
36 warn "$0: $file: $!\n";
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";
47 # Old makefile, join lines with continuation characters
48 $makefile =~ s/\\\n//mg;
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 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:;
60 while ($makefile =~ /^[A-Z0-9_]*OBJS\s*=\s*(.*)/mg) {
61 foreach (split/\s+/, $1) {
62 next if /^\$[\(\{].*[\)\}]$/; # skip included vars for now
69 while ($makefile =~ /-I(\S+)/mg) {
70 push(@incpaths, $1) unless $1 eq ".";
73 # Values of srcdir, top_srcdir, top_builddir, incdir
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';
83 # Find implicit rules for generate .o and .lo files
85 while ($makefile =~ /^\.c\.(l?o):\s*\n\t+(.*)$/mg) {
89 # Find existing .o and .lo dependencies
91 while ($makefile =~ /^(\w+\.l?o):\s*(\S+\.c)/mg) {
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);
102 # Use old depenencies when mapping objects to their source.
103 # If no old depenency, use the MANIFEST file to find the source.
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:\$\($_\)/:;
114 warn "$file: unable to find source for $obj\n";
116 my $imp = $implicit{$ext};
117 $imp =~ s/\$</$src/g;
119 my $deps = sprintf("%s: %s %s", $obj, $src,
120 join(' ', find_depends($src)));
121 if (length($deps) > 80) {
123 my $indent = length($obj) + 2;
124 while (length($deps) - $off > 80 - $indent) {
127 $new_makefile .= ' ' x $indent;
128 $pos = rindex($deps, ' ', $off + 80 - $indent - 2);
130 $pos = rindex($deps, ' ', $off + 78);
132 $new_makefile .= substr($deps, $off, $pos - $off) . " \\\n";
135 $new_makefile .= ' ' x $indent;
136 $new_makefile .= substr($deps, $off) . "\n";
138 $new_makefile .= "$deps\n";
140 $new_makefile .= "\t$imp\n";
144 rename($file, $file . ".old");
145 if (!open(MF, ">$file")) {
146 warn("cannot open $file: $!\n");
147 rename($file . ".old", $file);
149 print MF $new_makefile || warn("cannot write $file: $!\n");
158 my ($deps, $code, @headers);
161 # XXX - want build dir not src dir
162 $src = "$dir_vars{'srcdir'}/$src";
165 # resolve $(srcdir) etc.
166 foreach (keys %dir_vars) {
167 $src =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
170 # find open source file and find headers used by it
171 if (!open(FILE, "<$src")) {
172 warn "unable to open $src\n";
175 local $/; # enable "slurp" mode
180 while ($code =~ /^#\s*include\s+["<](\S+)[">]/mg) {
181 my ($hdr, $hdr_path) = find_header($1);
183 push(@headers, $hdr);
184 # Look for other includes in the .h file
185 push(@headers, find_depends($hdr_path));
192 # find the path to a header file
193 # returns path or undef if not found
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";
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;
207 return ("$inc/$hdr", $hdr_path) if -r $hdr_path;