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