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