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