Cosmeitcs
[llpp.git] / build.sh
blob31a6582592836af95f05ce45693572468f6fe0bd
1 #!/bin/sh
2 set -eu
4 now() { date +$dfmt; }
5 unameN=$(uname)
6 test "$unameN" = Darwin && {
7 darwin=true
8 wsi="wsi/osx"
9 } || {
10 darwin=false
11 wsi="wsi/x11"
14 dfmt="%s"
15 if $(expr >/dev/null "$(date --version 2>/dev/null)" : ".*GNU"); then
16 dfmt="%s.%N"
19 tstart=$(now)
20 alias vecho=${vecho-:}
21 command -v md5sum >/dev/null || true && alias sum=md5sum
22 digest() {
23 ah=
24 sum "$@" 2>/dev/null | while read h _; do ah="$ah$h"; done
25 printf "$ah"
28 partmsg() {
29 test $? -eq 0 && msg="ok" || msg="ko"
30 echo "$msg $(echo "scale=3; ($(now) - $tstart)/1" | bc -l) sec"
33 die() {
34 echo "$*" >&2
35 exit 111
38 trap 'partmsg' EXIT
40 test $(ocamlc -version | { IFS=. read a b _; echo $a$b; } ) -lt 406 && {
41 die OCaml version 4.06+ is required
44 test -n "${1-}" || die "usage: $0 build-directory"
46 outd=$1
47 srcd=$(dirname $0)
48 mudir=$srcd/mupdf
49 muinc="-I $mudir/include -I $mudir/thirdparty/freetype/include"
51 isfresh() {
52 test -e "$1" && test -r "$1.past" && {
53 . "$1.past"
54 test "$k" = "$2"
58 oflags() {
59 case "${1#$outd/}" in
60 main.cmo|utils.cmo|config.cmo|parser.cmo|wsi.cmi|$wsi/wsi.cmo)
61 f="-g -strict-sequence -strict-formats -warn-error a";;
62 *) f="-g";;
63 esac
64 echo "-I lablGL -I $outd/lablGL -I $wsi -I $outd/$wsi -I $outd $f"
67 cflags() {
68 case "${1#$outd/}" in
69 link.o)
70 f="-g -std=c99 -O2 $muinc -Wall -Werror -pedantic-errors"
71 $darwin && echo "$f -D__COCOA__" || echo $f;;
72 */ml_gl.o) echo "-g -Wno-pointer-sign -O2";;
73 *) echo "-g -O2";;
74 esac
77 mflags() { echo "-I $(ocamlc -where) -g -O2"; }
79 bocaml1() {
80 eval ocamlc -depend -bytecode -one-line $incs $s | {
81 read _ _ depl
82 for d in $(eval echo $depl); do
83 bocaml ${d#$srcd/} $((n+1))
84 done
86 cmd="ocamlc $(oflags $o) -c -o $o $s"
87 keycmd="digest $o $s"
88 grep -q "$o" $outd/ordered || {
89 echo "$o" >>"$outd/ordered"
90 isfresh "$o" "$cmd$(eval $keycmd)" || {
91 printf "%*.s%s -> %s\n" $n '' "${s#$srcd/}" "$o"
92 eval "$cmd"
93 echo "k='$cmd$(eval $keycmd)'" >"$o.past"
94 } && vecho "fresh '$o'"
98 bocaml() (
99 o="$1"
100 n="$2"
101 wocmi="${o%.cmi}"
102 test ${wocmi%help.cmo} != $wocmi && {
103 s=$outd/help.ml
104 o=$outd/help.cmo
105 } || {
106 test "$o" = "$wocmi" && s=$srcd/${o%.cmo}.ml || s=$srcd/$wocmi.mli
107 o=$outd/$o
109 incs="-I lablGL -I $outd/lablGL -I $wsi -I $outd/$wsi -I $outd"
110 bocaml1 "$s" "$o"
113 bocamlc() {
114 o=$outd/$1
115 s=$srcd/${1%.o}.c
116 cmd="ocamlc -ccopt \"$(cflags $o) -MMD -MF $o.dep -MT_ -o $o\" $s"
117 test -r $o.dep && read _ d <$o.dep || d=
118 keycmd='digest $o $d'
119 isfresh "$o" "$cmd$(eval $keycmd)" || {
120 printf "%s -> %s\n" "${s#$srcd/}" "$o"
121 eval "$cmd"
122 read _ d <$o.dep
123 echo "k='$cmd$(eval $keycmd)'" >"$o.past"
124 } && vecho "fresh $o"
127 bobjc() {
128 o=$outd/$1
129 s=$srcd/${1%.o}.m
130 cmd="$mcomp $(mflags $o) -MMD -MF $o.dep -MT_ -c -o $o $s"
131 test -r $o.dep && read _ d <$o.dep || d=
132 keycmd='digest $o $d'
133 isfresh "$o" "$cmd$(eval $keycmd)" || {
134 printf "%s -> %s\n" "${s#$srcd/}" "$o"
135 eval "$cmd"
136 read _ d <$o.dep
137 echo "k='$cmd$(eval $keycmd)'" >"$o.past"
138 } && vecho "fresh $o"
141 mkdir -p $outd/$wsi
142 mkdir -p $outd/lablGL
143 :>$outd/ordered
145 mkhelp() {
146 ocaml str.cma -stdin $srcd/KEYS <<EOF
147 let fixup = let open Str in
148 let dash = regexp {|\([^ ]*\) +- +\(.*\)|}
149 and head = regexp {|-----\(.*\)-----|} in fun s ->
150 String.escaped s |> global_replace dash {|\1\t\2|}
151 |> global_replace head {|\xc2\xb7\1|};;
152 let rec iter ic = match input_line ic with
153 | s -> Printf.printf "\"%s\";\\n" @@ fixup s; iter ic
154 | exception End_of_file -> ();;
155 Printf.printf "let keys = [\\n";
156 iter @@ open_in Sys.argv.(1);;
157 Printf.printf "] and version = \"$ver\";;"
161 ver=$(cd $srcd && git describe --tags --dirty) || echo unknown
162 cmd="mkhelp >$outd/help.ml"
163 keycmd="digest $srcd/KEYS; echo $ver"
164 isfresh "$outd/help.ml" '$cmd$(eval $keycmd)$ver' || {
165 eval $cmd
166 echo "k='$cmd$(eval $keycmd)$ver'" >"$outd/help.ml.past"
167 } && vecho "fresh $outd/help.ml"
169 case "${2-}" in
170 man)
171 md=$outd/man
172 mkdir -p $md
173 for m in llpp llppac llpphtml; do
174 man=$srcd/man/$m.man
175 xml=$md/$m.xml
176 out=$md/$m.1
177 keycmd="digest $xml $man"
178 conf="$srcd/man/asciidoc.conf"
179 cmd="asciidoc -d manpage -b docbook -f $conf -o '$xml' '$man'"
180 isfresh "$xml" "$cmd$(eval $keycmd)" || {
181 eval $cmd
182 echo "k='$cmd$(eval $keycmd)'" >"$md/$m.past"
184 keycmd="digest $out $xml"
185 cmd="xmlto man -o $md $xml"
186 isfresh "$out" "$cmd$(eval $keycmd)" || {
187 eval $cmd
188 echo "k='$cmd$(eval $keycmd)'" >"$out.past"
190 done
191 shift;;
192 *) ;;
193 esac
195 # following is disgusting (from "generalize everything" perspective),
196 # but generic method of derviving .ml's location from .mli's is not
197 # immediately obvious
198 for m in lablGL/glMisc.cmo lablGL/glTex.cmo $wsi/wsi.cmo main.cmo; do
199 bocaml $m 0
200 done
201 bocamlc link.o
202 cobjs="$outd/link.o"
204 libs="str.cma unix.cma"
205 clibs="-L$mudir/build/native -lmupdf -lmupdfthird -lpthread"
206 if $darwin; then
207 mcomp=$(ocamlc -config | grep bytecomp_c_co | { read _ c; echo $c; })
208 clibs="$clibs -framework Cocoa -framework OpenGL"
209 bobjc main_osx.o
210 cobjs="$cobjs $outd/main_osx.o"
211 else
212 clibs="$clibs -lGL -lX11"
215 globjs=
216 for f in ml_gl ml_glarray ml_raw; do
217 bocamlc lablGL/$f.o
218 globjs="$globjs $outd/lablGL/$f.o"
219 done
221 ord=$(echo $(grep -v \.cmi $outd/ordered))
222 cmd="ocamlc -custom $libs -o $outd/llpp $cobjs $ord"
223 cmd="$cmd $globjs -cclib \"$clibs\""
224 keycmd="digest $outd/llpp $outd/link.o $ord"
225 isfresh "$outd/llpp" "$cmd$(eval $keycmd)" || {
226 echo linking $outd/llpp
227 eval $cmd || echo "$cmd failed"
228 echo "k='$cmd$(eval $keycmd)'" >"$outd/llpp.past"
229 } && vecho "fresh llpp"
231 if $darwin; then
232 out="$outd/llpp.app/Contents/Info.plist"
233 keycmd="digest $out $srcd/misc/Info.plist.sh"
234 isfresh $out "$(eval $keycmd)" || {
235 shortver=$(echo $ver | { IFS='-' read s _; echo ${s#v}; })
236 d=$(dirname $out)
237 test -d "$d" || mkdir -p "$d"
238 . $srcd/misc/Info.plist.sh >"$out"
239 echo "k=$(eval $keycmd)" >"$out.past"
240 } && vecho "fresh plist"
242 out=$outd/llpp.app/Contents/MacOS/llpp
243 keycmd="digest $out $outd/llpp"
244 isfresh $out "$(eval $keycmd)" || {
245 d=$(dirname $out)
246 mkdir -p "$d"
247 cp $outd/llpp $out
248 echo "k=$(eval $keycmd)" >"$out.past"
249 } && vecho "fresh bundle"