summaryrefslogtreecommitdiffstats
path: root/ship/build
diff options
context:
space:
mode:
Diffstat (limited to 'ship/build')
-rwxr-xr-xship/build93
1 files changed, 93 insertions, 0 deletions
diff --git a/ship/build b/ship/build
new file mode 100755
index 00000000..916953cc
--- /dev/null
+++ b/ship/build
@@ -0,0 +1,93 @@
+#! /bin/sh
+set -euf
+
+## SYNOPSIS
+# build compile SRCFILE DSTFILE
+# build deps SRCFILE
+build() {
+ case "$1" in
+ compile) build_compile "$2" "$3";;
+ deps) build_deps "$2";;
+ *) echo "build: $1: bad command" >&2; return 23;;
+ esac
+}
+
+## 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:"
+
+## 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() {
+ srcfile="$(cat "$1")"
+
+ while needs_compilation "$srcfile"; do
+ script="$(make_sedscript_maker_shellscript "$srcfile")"
+ srcfile="$(echo "$srcfile" | sed -n "$script")"
+ done
+
+ echo "$srcfile" > "$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")"
+ sedscript="$(eval "$sedscript_generator")"
+ echo "$sedscript"
+}
+
+## usage: build_deps SRCFILE
+build_deps() {
+ for libname in $(sed -n 's:^'"$build_include_directive"'$:\1:p' "$1"); do
+ build_resolve "$libname"
+ done
+}
+
+## 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 "$@"