#! /bin/sh set -euf ## SYNOPSIS # [debug=true] build compile SRCFILE DSTFILE # [debug=true] build deps SRCFILE... build() { case "$1" in compile) build_compile "$2" "$3";; deps) shift; build_deps "$@";; *) echo "build: $1: bad command" >&2; return 23;; esac } # usage: debug_script VARNAME [DESCRIPTION] debug_script() { if test "${debug-false}" = true; then printf '====== %s%s\n%s\n' \ "$1" \ "${2+" ($2)"}" \ "$(eval echo \"\$$1\" | nl -b a)" >&2 fi } ## build directives build_info_directive='#@info' build_include_directive='#@include \([0-9A-Za-z]\+\)' input_parser="\ s:^ *\([0-9]\+\) "$build_info_directive"$:build_info \1: s:^ *\([0-9]\+\) "$build_include_directive"$:build_include \1 \2: t s:^ *\([0-9]\+\) .*:echo \1p:" debug_script input_parser ## usage: build_include LINENO LIBNAME build_include() { cat< "$2" chmod +x "$2" } ## usage: needs_compilation SHELLSCRIPT # Returns true if SRCFILE contains compilation directives. needs_compilation() { echo "$1" | grep -q "^\\($build_include_directive\\|$build_info_directive\\)$" } ## usage: make_sedscript_maker_shellscript SRCFILE # Print a shellscript that creates a sedscript that resolves all the build # directives in SRCFILE. make_sedscript_maker_shellscript() { sedscript_generator="$(echo "$1" | nl -b a -s ' ' | sed "$input_parser")" debug_script sedscript_generator 'sed input_parser srcfile' sedscript="$(eval "$sedscript_generator")" debug_script sedscript 'eval sedscript_generator' echo "$sedscript" } ## usage: build_deps SRCFILE... # Print all the dependencies of SRCFILE... (in alphabetic order) to stdout. build_deps() { while test $# -gt 0; do deps="$( for f; do for d in $(sed -n 's:^'"$build_include_directive"'$:\1:p' "$f"); do build_resolve $d done done )" set -- $deps if test $# -gt 0; then echo "$deps" fi done | sort | uniq } ## usage: build_resolve LIBNAME build_resolve() { echo "$BUILD_PATH" | tr : \\n | xargs -I: printf '%s/%s\n' : "$1" | xargs -I: ls -d : 2>/dev/null | head -n 1 | grep . || { echo "build resolve: $1: library not found" >&2 return 23 } } build "$@"