Sigh...
[llpp.git] / build.sh
blob1b3c3040190c4d168f525da73f8db14f785bb862
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 vecho=${vecho-:}
21 command -v md5sum >/dev/null || true && alias sum=md5sum
22 digest() { sum "$@" 2>/dev/null | while read h _; do printf $h; done; }
24 partmsg() {
25 test $? -eq 0 && msg="ok" || msg="ko"
26 echo "$msg $(echo "scale=3; ($(now) - $tstart)/1" | bc -l) sec"
29 die() {
30 echo "$*" >&2
31 exit 111
34 trap 'partmsg' EXIT
36 test -n "$1" || die "usage: $0 build-directory"
38 outd=$1
39 srcd=$(dirname $0)
40 mudir=$srcd/mupdf
41 muinc="-I $mudir/include -I $mudir/thirdparty/freetype/include"
43 isfresh() {
44 test -e "$1" && test -r "$1.past" && {
45 . "$1.past"
46 test "$k" = "$2"
50 oflags() {
51 case "${1#$outd/}" in
52 main.cmo|utils.cmo|config.cmo|parser.cmo|wsi.cmi|$wsi/wsi.cmo)
53 f="-g -strict-sequence -strict-formats -warn-error a";;
54 *) f="-g";;
55 esac
56 echo "-I lablGL -I $outd/lablGL -I $wsi -I $outd/$wsi -I $outd $f"
59 cflags() {
60 case "${1#$outd/}" in
61 link.o)
62 f="-g -std=c99 -O2 $muinc -Wall -Werror -pedantic-errors"
63 $darwin && echo "$f -D__COCOA__" || echo $f;;
64 */ml_gl.o) echo "-g -Wno-pointer-sign -O2";;
65 *) echo "-g -O2";;
66 esac
69 mflags() { echo "-I $(ocamlc -where) -g -O2"; }
71 bocaml1() {
72 eval ocamlc -depend -bytecode -one-line $incs $s | {
73 read _ _ depl
74 for d in $(eval echo $depl); do
75 bocaml ${d#$srcd/} $((n+1))
76 done
78 cmd="ocamlc $(oflags $o) -c -o $o $s"
79 keycmd="digest $o $s"
80 grep -q "$o" $outd/ordered || {
81 echo "$o" >>$outd/ordered
82 isfresh "$o" "$cmd$(eval $keycmd)" || {
83 printf "%*.s%s -> %s\n" $n '' "${s#$srcd/}" "$o"
84 eval "$cmd"
85 echo "k='$cmd$(eval $keycmd)'" >$o.past
86 } && $vecho "fresh '$o'"
90 bocaml() (
91 o="$1"
92 n="$2"
93 wocmi="${o%.cmi}"
94 test ${wocmi%help.cmo} != $wocmi && {
95 s=$outd/help.ml
96 o=$outd/help.cmo
97 } || {
98 test "$o" = "$wocmi" && s=$srcd/${o%.cmo}.ml || s=$srcd/$wocmi.mli
99 o=$outd/$o
101 incs="-I lablGL -I $outd/lablGL -I $wsi -I $outd/$wsi -I $outd"
102 bocaml1 "$s" "$o"
105 bocamlc() {
106 o=$outd/$1
107 s=$srcd/${1%.o}.c
108 cmd="ocamlc -ccopt \"$(cflags $o) -MMD -MF $o.dep -MT_ -o $o\" $s"
109 test -r $o.dep && read _ d <$o.dep || d=
110 keycmd='digest $o $d'
111 isfresh "$o" "$cmd$(eval $keycmd)" || {
112 printf "%s -> %s\n" "${s#$srcd/}" "$o"
113 eval "$cmd"
114 read _ d <$o.dep
115 echo "k='$cmd$(eval $keycmd)'" >$o.past
119 bobjc() {
120 o=$outd/$1
121 s=$srcd/${1%.o}.m
122 cmd="$mcomp $(mflags $o) -MMD -MF $o.dep -MT_ -c -o $o $s"
123 test -r $o.dep && read _ d <$o.dep || d=
124 keycmd='digest $o $d'
125 isfresh "$o" "$cmd$(eval $keycmd)" || {
126 printf "%s -> %s\n" "${s#$srcd/}" "$o"
127 eval "$cmd"
128 read _ d <$o.dep
129 echo "k='$cmd$(eval $keycmd)'" >$o.past
133 mkdir -p $outd/$wsi
134 mkdir -p $outd/lablGL
135 :>$outd/ordered
137 mkhelp() {
138 ocaml str.cma -stdin $srcd/KEYS <<EOF
139 let fixup = let open Str in
140 let dash = regexp {|\([^ ]*\) +- +\(.*\)|}
141 and head = regexp {|-----\(.*\)-----|} in fun s ->
142 String.escaped s |> global_replace dash {|\1\t\2|}
143 |> global_replace head {|\xc2\xb7\1|};;
144 let rec iter ic = match input_line ic with
145 | s -> Printf.printf "\"%s\";\\n" @@ fixup s; iter ic
146 | exception End_of_file -> ();;
147 Printf.printf "let keys = [\\n";
148 iter @@ open_in Sys.argv.(1);;
149 Printf.printf "] and version = \"$ver\";;"
153 ver=$(cd $srcd && git describe --tags --dirty) || echo unknown
154 cmd="mkhelp >$outd/help.ml"
155 keycmd="digest $srcd/KEYS; echo $ver"
156 isfresh "$outd/help.ml" '$cmd$(eval keycmd)$ver' || {
157 eval $cmd
158 echo "k='$cmd$(eval $keycmd)$ver'" >$outd/help.ml.past
161 # following is disgusting (from "generalize everything" perspective),
162 # but generic method of derviving .ml's location from .mli's is not
163 # immediately obvious
164 for m in lablGL/glMisc.cmo lablGL/glTex.cmo $wsi/wsi.cmo main.cmo; do
165 bocaml $m 0
166 done
167 bocamlc link.o
168 cobjs="$outd/link.o"
170 libs="str.cma unix.cma"
171 clibs="-L$mudir/build/native -lmupdf -lmupdfthird -lpthread"
172 if $darwin; then
173 mcomp=$(ocamlc -config | grep bytecomp_c_co | { read _ c; echo $c; })
174 clibs="$clibs -framework Cocoa -framework OpenGL"
175 bobjc main_osx.o
176 cobjs="$cobjs $outd/main_osx.o"
177 else
178 clibs="$clibs -lGL -lX11"
181 globjs=
182 for f in ml_gl ml_glarray ml_raw; do
183 bocamlc lablGL/$f.o
184 globjs="$globjs $outd/lablGL/$f.o"
185 done
187 ord=$(echo $(grep -v \.cmi $outd/ordered))
188 cmd="ocamlc -custom $libs -o $outd/llpp $cobjs $ord"
189 cmd="$cmd $globjs -cclib \"$clibs\""
190 keycmd="digest $outd/llpp $outd/link.o $ord"
191 isfresh "$outd/llpp" "$cmd$(eval $keycmd)" || {
192 echo linking $outd/llpp
193 eval $cmd || echo "$cmd failed"
194 echo "k='$cmd$(eval $keycmd)'" >$outd/llpp.past