• 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' | sort > 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	if [ ! -z "${tests}" ]; then
152		cat >> "$makefile.2" <<EOF
153INSTALL_TARGETS+=	${tests}
154EOF
155	fi
156	cat >> "$makefile.2" <<EOF
157MAKE_TARGETS+=		${targets}
158
159EOF
160
161	if [ ! -f "$makefile.3" ]; then
162
163		cat > "$makefile.3" <<EOF
164all: \$(MAKE_TARGETS)
165	@if [ -d speculative ]; then \$(MAKE) -C speculative all; fi
166
167clean:
168	rm -f \$(MAKE_TARGETS) logfile* run.sh *.core
169	@if [ -d speculative ]; then \$(MAKE) -C speculative clean; fi
170
171install: \$(INSTALL_DIR) run.sh
172	set -e; for file in \$(INSTALL_TARGETS) run.sh; do	\\
173		if [ -f "\$\$file" ] ; then			\\
174			install -m 00755 \$\$file		\\
175				\$(INSTALL_DIR)/\$\$file;	\\
176		fi;						\\
177	done
178	@if [ -d speculative ]; then \$(MAKE) -C speculative install; fi
179
180test: run.sh
181	@./run.sh
182
183\$(INSTALL_DIR):
184	mkdir -p \$@
185
186EOF
187
188	fi
189
190	if ! grep -q '^run.sh' "$makefile.3"; then
191		cat >> "$makefile.3" <<EOF
192run.sh:
193	@echo '#!/bin/sh' > \$@
194	@echo "\$(top_srcdir)/bin/run-tests.sh \$(subdir) \$(INSTALL_TARGETS)" >> \$@
195	@chmod +x run.sh
196
197EOF
198	fi
199
200	# Only pass along libraries to link if `-c` was not specified in `$compiler_args`.
201	if [ "$compiler_args" = "$buildonly_compiler_args" ]; then
202		link_libs=false
203	else
204		link_libs=true
205	fi
206
207	# Produce _awesome_ target rules for everything that needs it.
208	for prereq in ${make_rule_prereq_cache}; do
209
210		test_name="$prereq"
211		if [ "$suffix" != "" ]; then
212			test_name=`echo "$test_name" | sed -e "s,$suffix,,"`
213		fi
214
215		c_file="$test_name.c"
216		bin_file="${test_prefix}_$prereq"
217
218		case "$suffix" in
219		.run-test)
220			grep -q 'main' "$prereq_dir/$c_file" || echo >&2 "$prereq_dir/$c_file should be test."
221			;;
222		.test)
223			grep -q 'main' "$prereq_dir/$c_file" && echo >&2 "$prereq_dir/$c_file should be run-test."
224			;;
225		esac
226
227		COMPILE_STR="\$(CC) $compiler_args \$(CFLAGS) \$(LDFLAGS) -o \$@ \$(srcdir)/$c_file"
228		if $link_libs; then
229			COMPILE_STR="$COMPILE_STR \$(LDLIBS)"
230		fi
231
232		cat >> "$makefile.3" <<EOF
233$bin_file: \$(srcdir)/$c_file
234	@if $COMPILE_STR > logfile.\$\$\$\$ 2>&1; then \\
235		 cat logfile.\$\$\$\$; \\
236		 echo "\$(subdir)/$test_name compile PASSED"; \\
237		 echo "\$(subdir)/$test_name compile PASSED" >> \$(LOGFILE); \\
238	else \\
239		 cat logfile.\$\$\$\$; \\
240		 echo "\$(subdir)/$test_name compile FAILED; SKIPPING"; \\
241		(echo "\$(subdir)/$test_name compile FAILED; SKIPPING"; cat logfile.\$\$\$\$) >> \$(LOGFILE); \\
242	fi; \\
243	rm -f logfile.\$\$\$\$
244
245EOF
246	done
247
248	# Produce copy rules for .sh scripts.
249	for prereq in ${make_copy_prereq_cache}; do
250		src="$prereq"
251		dst="${test_prefix}_$prereq"
252
253		cat >> "$makefile.3" <<EOF
254$dst: \$(srcdir)/$src
255	@cp \$(srcdir)/$src \$@
256
257EOF
258	done
259}
260
261generate_makefiles() {
262
263	local prereq_cache=
264
265	local make_gen_list=$1
266	local suffix=$2
267	local compiler_args="$3"
268
269	while read filename; do
270
271		prereq_dir=`dirname "$filename"`
272
273		# First run.
274		if [ "$prereq_cache_dir" = "" ] ; then
275			prereq_cache_dir="$prereq_dir"
276		elif [ "$prereq_cache_dir" != "$prereq_dir" ]; then
277
278			generate_makefile "$prereq_cache_dir/Makefile" "$prereq_cache_dir" "$compiler_args" $prereq_cache
279
280			# Prep for the next round..
281			prereq_cache=
282			prereq_cache_dir="$prereq_dir"
283
284		fi
285
286		# Cache the entries to punt out all of the data at
287		# once for a single Makefile.
288		if [ "$prereq_cache" != "" ] ; then
289			prereq_cache="$prereq_cache "
290		fi
291		prereq_cache="$prereq_cache"`basename "$filename" | sed "s,.c\$,$suffix,g"`
292
293	done < $make_gen_list
294
295	# Dump the last Makefile data cached up.
296	generate_makefile "$prereq_cache_dir/Makefile" $prereq_cache_dir "$compiler_args" $prereq_cache
297
298}
299
300export PATH="$PATH:`dirname "$0"`"
301
302AUTHORDATE=`grep "Ngie Cooper" "$0" | head -n 1 | sed 's,# *,,'`
303PREFIX=`print-prefix.sh`
304EXEC_PREFIX="${PREFIX}/bin"
305TOP_SRCDIR=${TOP_SRCDIR:=`dirname "$0"`/..}
306
307GLOBAL_BOILERPLATE="${TOP_SRCDIR}/.global_boilerplate"
308
309CONFIG_MK="../../include/mk/config-openposix.mk"
310
311rm -f "$GLOBAL_BOILERPLATE"
312
313for var in CFLAGS LDFLAGS LDLIBS; do
314	if [ -f "$TOP_SRCDIR/$var" ]; then
315		cat >> "$GLOBAL_BOILERPLATE" <<EOF
316$var+=		`cat "$TOP_SRCDIR/$var"`
317EOF
318	fi
319done
320
321if [ -f "$CONFIG_MK" ]; then
322	cat "$CONFIG_MK" >> "$GLOBAL_BOILERPLATE"
323fi
324
325# For the generic cases.
326generate_locate_test_makefile buildonly '.test' "$buildonly_compiler_args"
327generate_locate_test_makefile runnable '.run-test'
328generate_locate_test_makefile test-tools ''
329
330rm -f "$GLOBAL_BOILERPLATE"
331
332find . -name Makefile.1 -exec dirname {} \; | while read dir; do
333	if [ -f "$dir/Makefile.2" ]; then
334		cat $dir/Makefile.1 $dir/Makefile.2 $dir/Makefile.3 > $dir/Makefile
335	fi
336	rm $dir/Makefile.1 $dir/Makefile.2 $dir/Makefile.3
337done
338