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