main
  1#!/bin/bash
  2
  3rm -rf ./build/tests/*
  4mkdir -p ./build/tests
  5
  6CFLAGS=(-nostdlib -ffreestanding -static -fno-stack-protector -I. -DNOTLIBC_IMPLEMENT -DNOTLIBC_SILENCE -fno-builtin -g -Wall -Wextra -Wpedantic -Werror -fno-strict-aliasing)
  7pids=()
  8
  9ensure () {
 10	if ! command -v "$1" >/dev/null 2>&1 ; then
 11		echo "Error: '$1' is not a known command on the current system." >&2
 12		exit 1;
 13	fi
 14}
 15
 16build () {
 17	local flags=("${CFLAGS[@]}")
 18
 19	if [ "$2" == "tcc" ]; then
 20		flags+=("-gdwarf")
 21	fi
 22
 23	case "$3" in
 24		dbg) flags+=(-DBUILD_TYPE=1) ;;
 25		rel) flags+=(-DBUILD_TYPE=2) ;;
 26		*)   echo "Invalid build type flag passed to build()." >&2
 27		exit 1 ;;
 28	esac
 29
 30	case "$4" in
 31		o0) flags+=(-O0) ;;
 32		o1) flags+=(-O1) ;;
 33		o2) flags+=(-O2) ;;
 34		o3) flags+=(-O3) ;;
 35		lto) flags+=(-O2 -flto) ;;
 36		*)   echo "Invalid optimization flag passed to build()." >&2
 37		exit 1 ;;
 38	esac
 39
 40	local filename=$(basename "$1" .c)-$2-$3-$4
 41	local out="./build/tests/$filename"
 42
 43
 44	local cmd="$2 ${flags[@]} $1 -o $out"
 45	echo "Building $filename."
 46	echo "	$cmd"
 47
 48	if ! $cmd; then
 49		echo "Build failed for $out."
 50		exit 1
 51	fi
 52}
 53
 54debug () {
 55	echo "Running $1"
 56	gdb -q --return-child-result -ex "set debuginfod enabled on" -ex 'python gdb.events.exited.connect(lambda e: gdb.execute("quit"))' -ex "file $1" -ex run
 57}
 58
 59ensure gcc
 60ensure clang
 61ensure tcc
 62ensure gdb
 63
 64i=0
 65
 66for SRC in ./testing/tests/*.c; do
 67
 68	build $SRC gcc dbg o0 & pids+=($!)
 69	build $SRC gcc dbg o2 & pids+=($!)
 70	build $SRC gcc rel o2 & pids+=($!)
 71	build $SRC gcc rel lto & pids+=($!)
 72
 73	build $SRC clang dbg o0 & pids+=($!)
 74	build $SRC clang dbg o2 & pids+=($!)
 75	build $SRC clang rel o2 & pids+=($!)
 76	build $SRC clang rel lto & pids+=($!)
 77
 78	# tcc doesn't do optimization, so it just ignores it
 79	build $SRC tcc dbg o2 & pids+=($!)
 80	build $SRC tcc rel o2 & pids+=($!)
 81
 82	# Parallelize the builds across 4 tests (aka a *very* primitive way to limit parallelism)
 83	if (( i % 4 == 1 )); then
 84		for pid in "${pids[@]}"; do
 85			if ! wait "$pid"; then
 86				echo "Some compilation failed. Check the other messages, since this is parallelized."
 87				exit 1
 88			fi
 89		done
 90		pids=()
 91	fi
 92
 93	((i++))
 94done
 95
 96for pid in "${pids[@]}"; do
 97	wait "$pid"
 98done
 99
100for BIN in ./build/tests/*; do
101	if ! debug $BIN; then
102		exit 1
103	fi
104done
105
106
107