summaryrefslogtreecommitdiffstats
path: root/ship
diff options
context:
space:
mode:
Diffstat (limited to 'ship')
-rwxr-xr-xship/bin/punani1
-rwxr-xr-xship/build104
2 files changed, 73 insertions, 32 deletions
diff --git a/ship/bin/punani b/ship/bin/punani
index 99a5a813..28bf7d1a 100755
--- a/ship/bin/punani
+++ b/ship/bin/punani
@@ -1,3 +1,4 @@
#!/bin/sh
+#@info
#@include punani
punani "$@"
diff --git a/ship/build b/ship/build
index 6c26e6f3..486f4bed 100755
--- a/ship/build
+++ b/ship/build
@@ -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 '====== %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<<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