summaryrefslogtreecommitdiff
path: root/mcon/pl/makefile.pl
blob: 8437dda7d30cc7643b772cd30c5d57c960c7659e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
;# $Id: makefile.pl 20 2008-01-04 23:14:00Z rmanfredi $
;#
;#  Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi
;#  
;#  You may redistribute only under the terms of the Artistic Licence,
;#  as specified in the README file that comes with the distribution.
;#  You may reuse parts of this distribution only within the terms of
;#  that same Artistic Licence; a copy of which may be found at the root
;#  of the source tree for dist 4.0.
;#
;# $Log: makefile.pl,v $
;# Revision 3.0.1.1  1995/09/25  09:19:42  ram
;# patch59: symbols are now sorted according to the ?Y: layout directive
;#
;# Revision 3.0  1993/08/18  12:10:26  ram
;# Baseline for dist 3.0 netwide release.
;#
;# 
;# Given a list of wanted symbols in the Wanted file, produce a Makefile which
;# will compute the transitive closure of dependencies for us and give the
;# correct layout order in the Configure script. Because some conditional
;# symbols could indeed be truly wanted symbols, we build the makefile in two
;# passes. The first one will give us the complete list of units to be loaded,
;# while the second will determine the correct order.
;#
;# The external $saved_dependencies records the original dependencies we got
;# from the units' ?MAKE: lines while $dependencies is tampered with.
;#
;# Note that when the -w option is supplied, the sources are not parsed.
;# However, the config.h.SH file would be empty, because its building
;# relies on values in cmaster and shmaster arrays. It is okay for values
;# in shmaster, because they are true wanted symbols. The cmaster keys
;# have also been written, but with a leading '>' (because they are
;# not true targets for Makefile). We thus extract all these keys and
;# set the cmaster array accordingly.
;#
;# Obsolete symbols, if any found, are also part of the Wanted file, written on
;# a line starting with a '!', eventually followed by a '>' if the obsolete
;# symbol is a C one.
;#
;# These three data structures record wanted things like commands or symbols.
;#  %symwanted{'sym'} is true when the symbol is wanted (transitive closure)
;#  %condwanted{'sym'} when the default value of a symbol is requested
;#  $wanted records the set of wanted shell symbols (as opposed to C ones)
;#
# Build the private makefile we use to compute the transitive closure of the
# previously determined dependencies.
sub build_makefile {
	print "Computing optimal dependency graph...\n" unless $opt_s;
	chdir('.MT') || die "Can't chdir to .MT\n";
	local($wanted);			# Wanted shell symbols
	&build_private;			# Build a first makefile from dependencies
	&compute_loadable;		# Compute loadable units
	&update_makefile;		# Update makefile using feedback from first pass
	chdir($WD) || die "Can't chdir back to $WD\n";
	# Free memory by removing useless data structures
	undef $dependencies;
	undef $saved_dependencies;
}

# First pass: build a private makefile from the extracted dependency, changing
# conditional units to truly wanted ones if the symbol is used, removing the
# dependency otherwise. The original dependencies are saved.
sub build_private {
	print "    Building private make file...\n" unless $opt_s;
	open(WANTED,"../Wanted") || die "Can't reopen Wanted.\n";
	$wanted = ' ' x 2000;	# Pre-extend string
	$wanted = '';
	while (<WANTED>) {
		chop;
		next if /^!/;		# Skip obsolete symbols
		if (s/^>//) {
			$cmaster{$_}++;
		} else {
			$wanted .= "$_ ";
		}
	}
	close WANTED;

	# The wanted symbols are sorted so that d_* (checking for C library symbol)
	# come first and i_* (checking for includes) comes at the end. Grouping the
	# d_* symbols together has good chances of improving the locality of the
	# other questions and i_* symbols must come last since some depend on h_*
	# values which prevent incompatible headers inclusions.
	$wanted = join(' ', sort symbols split(' ', $wanted));
	
	# Now generate the first makefile, which will be used to determine which
	# symbols we really need, so that conditional dependencies may be solved.
	open(MAKEFILE,">Makefile") || die "Can't create .MT/Makefile.\n";
	print MAKEFILE "SHELL = /bin/sh\n";
	print MAKEFILE "W = $wanted\n";
	$saved_dependencies = $dependencies;
	foreach $sym (@Cond) {
		if ($symwanted{$sym}) {
			$dependencies =~ s/\+($sym\s)/$1/gm;
		} else {
			$dependencies =~ s/\+$sym(\s)/$1/gm;
		}
	}
	print MAKEFILE $dependencies;
	close MAKEFILE;
}

# Ordering for symbols. Give higher priority to d_* ones and lower to i_* ones.
# If any layout priority is defined in %Layout, it is used to order the
# symbols.
sub symbols {
	local($r) = $Layout{$a} <=> $Layout{$b};
	return $r if $r;
	# If we come here, both symbols have the same layout priority.
	if ($a =~ /^d_/) {
		return -1 unless $b =~ /^d_/;
	} elsif ($b =~ /^d_/) {
		return 1;
	} elsif ($a =~ /^i_/) {
		return 1 unless $b =~ /^i_/;
	} elsif ($b =~ /^i_/) {
		return -1;
	}
	$a cmp $b;
}

# Run the makefile produced in the first pass to find the whole set of units we
# have to load, filling in the %symwanted and %condwanted structures.
sub compute_loadable {
	print "    Determining loadable units...\n" unless $opt_s;
	open(MAKE, "make -n |") || die "Can't run make";
	while (<MAKE>) {
		s|^\s+||;				# Some make print tabs before command
		if (/^pick/) {
			print "\t$_" if $opt_v;
			($pick,$cmd,$symbol,$unit) = split(' ');
			$symwanted{$symbol}++;
			$symwanted{$unit}++;
		} elsif (/^cond/) {
			print "\t$_" if $opt_v;
			($pick,@symbol) = split(' ');
			for (@symbol) {
				$condwanted{$_}++;	# Default value is requested
			}
		}
	}
	close MAKE;
}

# Now that we know all the desirable symbols, we have to rebuild
# another makefile, in order to have the units in a more optimal
# way.
# Actually, if we have both ?MAKE:a:+b and ?MAKE:d:b and 'd' is
# wanted; then 'b' will be loaded. However, 'b' is a conditional
# dependency for 'a', and it would be better if 'b' were loaded
# before 'a' is, though this is not necessary.
# It is hard to know that 'b' will be loaded *before* the first make.

# Back to the original dependencies, make loadable units truly wanted ones and
# remove optional ones.
sub update_makefile {
	print "    Updating make file...\n" unless $opt_s;
	open(MAKEFILE,">Makefile") || die "Can't create .MT/Makefile.\n";
	print MAKEFILE "SHELL = /bin/sh\n";
	print MAKEFILE "W = $wanted\n";
	foreach $sym (@Cond) {
		if ($symwanted{$sym}) {
			$saved_dependencies =~ s/\+($sym\s)/$1/gm;
		} else {
			$saved_dependencies =~ s/\+$sym(\s)/$1/gm;
		}
	}
	print MAKEFILE $saved_dependencies;
	close MAKEFILE;
}