• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2#
3# Generate generic POSIX compliant Makefiles.
4#
5# This means that there's a lot of unnecessary text (when using BSD or GNU
6# make, as I'm sure there are in other variants), and a lack of modularity,
7# but as long as you follow the criterion set in locate-test, then the
8# end-result for modifying and/or adding tests can be achieved by merely
9# rerunning this script.
10#
11# This script will remain around until (hopefully someday) POSIX make
12# becomes less braindead.
13#
14# See COPYING for more details.
15#
16# Ngie Cooper, June 2010
17#
18
19readonly buildonly_compiler_args="-c"
20
21generate_locate_test_makefile() {
22
23	local maketype=$1; shift
24
25	echo "Generating $maketype Makefiles"
26
27	locate-test --$maketype | sed -e 's,^./,,g' > make-gen.$maketype
28
29	generate_makefiles make-gen.$maketype $*
30
31	rm -f make-gen.$maketype
32}
33
34generate_makefile() {
35
36	local link_libs=
37	local make_rule_prereq_cache=
38	local make_copy_prereq_cache=
39	local prereq_cache=
40	local tests=
41	local targets=
42
43	local makefile=$1
44	local prereq_dir=$2
45	local compiler_args=$3
46	shift 3
47
48	prereq_cache=$*
49
50	test_prefix=$(basename "$prereq_dir")
51
52	# special case for speculative testcases
53	if [ "$test_prefix" = "speculative" ]; then
54		test_prefix=$(basename $(echo "$prereq_dir" | sed s/speculative//))
55		test_prefix="${test_prefix}_speculative"
56	fi
57
58	# Add all source files to $make_target_prereq_cache.
59	for prereq in $prereq_cache; do
60		# Stuff that needs to be tested.
61		if echo "$prereq" | grep -Eq '\.(run-test|sh)'; then
62			if [ "$tests" != "" ]; then
63				tests="$tests "
64			fi
65
66			tests="$tests${test_prefix}_$prereq"
67		fi
68
69		# Stuff that needs to be compiled.
70		if echo "$prereq" | grep -Eq '\.(run-test|sh|test)'; then
71			if [ "$targets" != "" ]; then
72				targets="$targets "
73			fi
74
75			targets="$targets${test_prefix}_$prereq"
76		fi
77
78		# Cache for generating compile rules.
79		case "$prereq" in
80		*.sh)
81			# Note that the sh scripts are copied later in order to
82			# have the test_prefix as well
83			if [ "$make_copy_prereq_cache" != "" ]; then
84				make_copy_prereq_cache="$make_copy_prereq_cache "
85			fi
86			make_copy_prereq_cache="$make_copy_prereq_cache$prereq"
87			;;
88		*)
89			if [ "$make_rule_prereq_cache" != "" ]; then
90				make_rule_prereq_cache="$make_rule_prereq_cache "
91			fi
92			make_rule_prereq_cache="$make_rule_prereq_cache$prereq"
93			;;
94		esac
95	done
96
97	if [ ! -f "$makefile.1" ]; then
98
99		cat > "$makefile.1" <<EOF
100#
101# Automatically generated by `basename "$0"` -- DO NOT EDIT.
102#
103# Restrictions for `basename "$0"` apply to this file. See COPYING for
104# more details.
105#
106# $AUTHORDATE
107#
108
109# Path variables.
110top_srcdir?=		`echo "$prereq_dir" | awk '{ gsub(/[^\/]+/, "..", $0); print }'`
111subdir=			$prereq_cache_dir
112srcdir=			\$(top_srcdir)/\$(subdir)
113
114prefix?=		$PREFIX
115exec_prefix?=		\$(prefix)
116INSTALL_DIR=		\$(DESTDIR)/\$(exec_prefix)/\$(subdir)
117LOGFILE?=		logfile
118
119# Build variables
120CFLAGS+=		-I\$(top_srcdir)/include
121
122# XXX: for testfrmw.c -- needs to be moved into a library.
123CFLAGS+=		-I\$(srcdir)
124
125EOF
126
127		if [ -f "$GLOBAL_BOILERPLATE" ]; then
128			cat >> "$makefile.1" <<EOF
129# Top-level make definitions
130`cat $GLOBAL_BOILERPLATE`
131EOF
132		fi
133
134		cat >> "$makefile.1" <<EOF
135# Submake make definitions.
136EOF
137
138		for var in CFLAGS LDFLAGS LDLIBS; do
139			if [ -f "${TOP_SRCDIR}/$var" ]; then
140				cat >> "$makefile.1" <<EOF
141${var}+=		`cat "${prereq_cache_dir}/${var}" 2>/dev/null`
142EOF
143			fi
144		done
145
146		# Whitespace
147		echo "" >> "$makefile.1"
148
149	fi
150
151	cat >> "$makefile.2" <<EOF
152INSTALL_TARGETS+=	${tests}
153MAKE_TARGETS+=		${targets}
154
155EOF
156
157	if [ ! -f "$makefile.3" ]; then
158
159		cat > "$makefile.3" <<EOF
160all: \$(MAKE_TARGETS)
161	@if [ -d speculative ]; then \$(MAKE) -C speculative all; fi
162
163clean:
164	rm -f \$(MAKE_TARGETS) logfile* run.sh *.core
165	@if [ -d speculative ]; then \$(MAKE) -C speculative clean; fi
166
167install: \$(INSTALL_DIR) run.sh
168	set -e; for file in \$(INSTALL_TARGETS) run.sh; do	\\
169		if [ -f "\$\$file" ] ; then			\\
170			install -m 00755 \$\$file		\\
171				\$(INSTALL_DIR)/\$\$file;	\\
172		fi;						\\
173	done
174	@if [ -d speculative ]; then \$(MAKE) -C speculative install; fi
175
176test: run.sh
177	@./run.sh
178
179\$(INSTALL_DIR):
180	mkdir -p \$@
181
182EOF
183
184	fi
185
186	if ! grep -q '^run.sh' "$makefile.3"; then
187		cat >> "$makefile.3" <<EOF
188run.sh:
189	@echo '#!/bin/sh' > \$@
190	@echo "\$(top_srcdir)/bin/run-tests.sh \$(subdir) \$(INSTALL_TARGETS)" >> \$@
191	@chmod +x run.sh
192
193EOF
194	fi
195
196	# Only pass along libraries to link if `-c` was not specified in `$compiler_args`.
197	if [ "$compiler_args" = "$buildonly_compiler_args" ]; then
198		link_libs=false
199	else
200		link_libs=true
201	fi
202
203	# Produce _awesome_ target rules for everything that needs it.
204	for prereq in ${make_rule_prereq_cache}; do
205
206		test_name="$prereq"
207		if [ "$suffix" != "" ]; then
208			test_name=`echo "$test_name" | sed -e "s,$suffix,,"`
209		fi
210
211		c_file="$test_name.c"
212		bin_file="${test_prefix}_$prereq"
213
214		case "$suffix" in
215		.run-test)
216			grep -q 'main' "$prereq_dir/$c_file" || echo >&2 "$prereq_dir/$c_file should be test."
217			;;
218		.test)
219			grep -q 'main' "$prereq_dir/$c_file" && echo >&2 "$prereq_dir/$c_file should be run-test."
220			;;
221		esac
222
223		COMPILE_STR="\$(CC) $compiler_args \$(CFLAGS) \$(LDFLAGS) -o \$@ \$(srcdir)/$c_file"
224		if $link_libs; then
225			COMPILE_STR="$COMPILE_STR \$(LDLIBS)"
226		fi
227
228		cat >> "$makefile.3" <<EOF
229$bin_file: \$(srcdir)/$c_file
230	@if $COMPILE_STR > logfile.\$\$\$\$ 2>&1; then \\
231		 cat logfile.\$\$\$\$; \\
232		 echo "\$(subdir)/$test_name compile PASSED"; \\
233		 echo "\$(subdir)/$test_name compile PASSED" >> \$(LOGFILE); \\
234	else \\
235		 cat logfile.\$\$\$\$; \\
236		 echo "\$(subdir)/$test_name compile FAILED; SKIPPING"; \\
237		(echo "\$(subdir)/$test_name compile FAILED; SKIPPING"; cat logfile.\$\$\$\$) >> \$(LOGFILE); \\
238	fi; \\
239	rm -f logfile.\$\$\$\$
240
241EOF
242	done
243
244	# Produce copy rules for .sh scripts.
245	for prereq in ${make_copy_prereq_cache}; do
246		src="$prereq"
247		dst="${test_prefix}_$prereq"
248
249		cat >> "$makefile.3" <<EOF
250$dst: \$(srcdir)/$src
251	@cp \$(srcdir)/$src \$@
252
253EOF
254	done
255}
256
257generate_makefiles() {
258
259	local prereq_cache=
260
261	local make_gen_list=$1
262	local suffix=$2
263	local compiler_args="$3"
264
265	while read filename; do
266
267		prereq_dir=`dirname "$filename"`
268
269		# First run.
270		if [ "$prereq_cache_dir" = "" ] ; then
271			prereq_cache_dir="$prereq_dir"
272		elif [ "$prereq_cache_dir" != "$prereq_dir" ]; then
273
274			generate_makefile "$prereq_cache_dir/Makefile" "$prereq_cache_dir" "$compiler_args" $prereq_cache
275
276			# Prep for the next round..
277			prereq_cache=
278			prereq_cache_dir="$prereq_dir"
279
280		fi
281
282		# Cache the entries to punt out all of the data at
283		# once for a single Makefile.
284		if [ "$prereq_cache" != "" ] ; then
285			prereq_cache="$prereq_cache "
286		fi
287		prereq_cache="$prereq_cache"`basename "$filename" | sed "s,.c\$,$suffix,g"`
288
289	done < $make_gen_list
290
291	# Dump the last Makefile data cached up.
292	generate_makefile "$prereq_cache_dir/Makefile" $prereq_cache_dir "$compiler_args" $prereq_cache
293
294}
295
296export PATH="$PATH:`dirname "$0"`"
297
298AUTHORDATE=`grep "Ngie Cooper" "$0" | head -n 1 | sed 's,# *,,'`
299PREFIX=`print-prefix.sh`
300EXEC_PREFIX="${PREFIX}/bin"
301TOP_SRCDIR=${TOP_SRCDIR:=`dirname "$0"`/..}
302
303GLOBAL_BOILERPLATE="${TOP_SRCDIR}/.global_boilerplate"
304
305CONFIG_MK="../../include/mk/config-openposix.mk"
306
307rm -f "$GLOBAL_BOILERPLATE"
308
309for var in CFLAGS LDFLAGS LDLIBS; do
310	if [ -f "$TOP_SRCDIR/$var" ]; then
311		cat >> "$GLOBAL_BOILERPLATE" <<EOF
312$var+=		`cat "$TOP_SRCDIR/$var"`
313EOF
314	fi
315done
316
317if [ -f "$CONFIG_MK" ]; then
318	cat "$CONFIG_MK" >> "$GLOBAL_BOILERPLATE"
319fi
320
321# For the generic cases.
322generate_locate_test_makefile buildonly '.test' "$buildonly_compiler_args"
323generate_locate_test_makefile runnable '.run-test'
324generate_locate_test_makefile test-tools ''
325
326rm -f "$GLOBAL_BOILERPLATE"
327
328find . -name Makefile.1 -exec dirname {} \; | while read dir; do
329	if [ -f "$dir/Makefile.2" ]; then
330		cat $dir/Makefile.1 $dir/Makefile.2 $dir/Makefile.3 > $dir/Makefile
331	fi
332	rm $dir/Makefile.1 $dir/Makefile.2 $dir/Makefile.3
333done
334