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