diff options
Diffstat (limited to 'ship/build')
-rwxr-xr-x | ship/build | 104 |
1 files changed, 72 insertions, 32 deletions
@@ -2,67 +2,107 @@ set -euf ## SYNOPSIS -# build compile SRCFILE DSTFILE -# build deps SRCFILE +# [debug=true] build compile SRCFILE DSTFILE +# [debug=true] build deps SRCFILE... build() { case "$1" in compile) build_compile "$2" "$3";; - deps) build_deps "$2";; + 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 '[35m====== %s%s[m\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<<EOF +$1a\\ +# begin $2 +$1r$(build_resolve $2) +$1a\\ +# end $2 +EOF +} + +## usage: build_info LINENO +build_info() { cat<<EOF +$1a\\ +# this file was generated by //ship/build\\ +# date: $(date -u --rfc-3339=s)\\ +# version: $(git rev-parse HEAD) +EOF +} + ## usage: build_compile SRCFILE DSTFILE build_compile() { - cp "$1" "$2" + srcfile="$(cat "$1")" + debug_script srcfile 'SRCFILE' - while needs_compilation "$2"; do - script="$(make_sedscript_maker_shellscript "$2" | sh)" - sed -n "$script" "$2" >"$2.tmp" - mv "$2.tmp" "$2" + while needs_compilation "$srcfile"; do + script="$(make_sedscript_maker_shellscript "$srcfile")" + srcfile="$(echo "$srcfile" | sed -n "$script")" + debug_script srcfile 'sed sedscript srcfile' done + echo "$srcfile" > "$2" chmod +x "$2" } -## usage: needs_compilation SRCFILE +## usage: needs_compilation SHELLSCRIPT # Returns true if SRCFILE contains compilation directives. needs_compilation() { - grep -q "^$build_include_directive$" "$1" + 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() { - echo 'set -euf' - deps="$(build_deps "$1")" - for lib in $deps; do - echo "_build_include_$(basename $lib)=$lib" - done - nl -b a -s ' ' "$1" | - sed ' - s:^ *:: - s:^\([0-9]\+\) '"$build_include_directive"'$:\1a\\\\\ -# BEGIN \2\ - \1r\$_build_include_\2\ - \1a\\\\\ -# END \2: - s:^\([0-9]\+\) .*:\1p: - - 1s:^:echo ": - $s:$:": - ' + 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 +## usage: build_deps SRCFILE... +# Print all the dependencies of SRCFILE... (in alphabetic order) to stdout. build_deps() { - for libname in $(sed -n 's:^'"$build_include_directive"'$:\1:p' "$1"); do - build_resolve "$libname" - done + 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 |