blob: 7755253de14e0e258bc2d0b5c671b2b781c13239 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#! /bin/sh
set -euf
## SYNOPSIS
# [debug=true] build compile SRCFILE DSTFILE
# [debug=true] build deps SRCFILE...
build() {
## Load macro definitions.
defmacro_pattern='## usage: \(.*\) -> \([^ ]\+\) \(.*\)'
script='s/^'"$defmacro_pattern"'$/\2_macro='"'"'\1'"'"'/p' \
setf defmacros '$(sed -n "$script" "$%s")' 0
eval "$defmacros"
## Dispatch.
case "$1" in
compile) build_compile "$2" "$3";;
deps) shift; build_deps "$@";;
*) echo "build: $1: bad command" >&2; return 23;;
esac
}
## usage: #@include \([0-9A-Za-z]\+\) -> build_include \1 \2
build_include() { cat<<EOF
$1a\\
# begin $2
$1r$(build_resolve $2)
$1a\\
# end $2
EOF
}
## usage: #@info -> build_info \1
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() {
script='s/^'"$defmacro_pattern"'$/\2_macro/p' \
setf macro_names '$(sed -n "$script" "$%s")' 0
setf unexpanded_macros_pattern \
'$(make_unexpanded_macros_pattern $%s)' macro_names
script='
s/^'"$defmacro_pattern"'$/s:^ *\\([0-9]\\+\\) \1$:\2 \3:/p
$a\
t;s:^ *\\([0-9]\\+\\) .*:echo \\1p:
' \
setf input_parser '$(sed -n "$script" "$%s")' 0
SRCFILE="$1" setf src '$(cat "$%s")' SRCFILE
while echo "$src" | grep -q "$unexpanded_macros_pattern"; do
setf sedgen '$(echo "$%s" | nl -b a -s \ | sed "$%s")' src input_parser
setf sedscript '$(eval "$%s")' sedgen
setf src '$(echo "$%s" | sed -n "$%s")' src sedscript
done
echo "$src" > "$2"
chmod +x "$2"
}
## usage: build_deps SRCFILE...
# Print all the dependencies of SRCFILE... to stdout. (alphabetic order)
build_deps() {
while test $# -gt 0; do
deps="$(
for f; do
for d in $(sed -n 's:^'"$build_include_macro"'$:\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
}
}
## usage: make_unexpanded_macros_pattern BUILD_DIRECTIVES...
make_unexpanded_macros_pattern() {
echo "^\\($(
for macro; do
eval echo \"\$$macro\"
done |
tr \\n \| |
sed 's/|/\\|/'
)\\)$"
}
## usage: setf NAME FMT [ARG...]
setf() {
value_script="$(shift; printf "$@")"
eval "$1=$value_script"
if test "${debug-false}" = true; then
eval 'echo "[35m$1=\"$value_script\"[m"'
eval 'echo "'"\$$1"'"' | nl -b a
fi >&2
}
## main
build "$@"
|