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