4 vecho
() { ${vecho-:} "$@"; }
5 executable_p
() { command -v "$1" >/dev
/null
2>&1; }
6 dgst
='cksum "$@" | while read d _; do printf $d; done'
7 ! executable_p b3sum || dgst
='b3sum --no-names "$@"'
8 executable_p realpath || realpath
() (cd "$1" &>/dev
/null
; pwd -P)
9 eval "digest() { $dgst; } 2>/dev/null"
10 die
() { echo "$@" >&2; exit 111; }
11 trap 'test $? -eq 0 || echo "build failed"' EXIT
15 clip
="LC_CTYPE=UTF-8 xclip -i"
16 paste="LC_CTYPE=UTF-8 xclip -o"
17 uopen
="echo 'Open "%s
"' >&2"
18 print
="echo 'Print "%s
"' >&2"
19 mjobs
=$
(getconf _NPROCESSORS_ONLN ||
echo 1)
24 clip
="LC_CTYPE=UTF-8 pbcopy"
25 paste="LC_CTYPE=UTF-8 pbaste"
28 *) die $
(uname
) is not supported
;;
31 test -n "${1-}" || die
"usage: $0 build-directory"
36 muinc
="-I $mudir/include -I $mudir/thirdparty/freetype/include"
38 test -d $mudir || die muPDF wasn
\'t found
in $outd/, consult
$srcd/BUILDING
40 mkdir
-p $outd/{$wsid,lablGL
}
42 # thanks to Sebastian Rasmussen
43 isfresh
() { test "$(cat $1.past)" = "$2"; } 2>/dev
/null
46 test -n "${gmk:-}" && gmk
=false || gmk
=true
48 mulibs
="$mudir/build/$mbt/libmupdf.a $mudir/build/$mbt/libmupdf-third.a"
49 make="make -C "$mudir" build=$mbt -j $mjobs libs"
55 $wsid/wsi.cm
[oi
]|confstruct.cmo|
help.cmo
) incs
="-I $b -I $b/$wsid";;
56 glutils.cmo
) incs
="-I $b -I $b/lablGL";;
57 uiutils.cmo|main.cmo
) incs
="-I $b -I $b/$wsid -I $b/lablGL";;
58 ffi.cmo|
help.cmi|parser.cmo
) incs
="-I $b";;
60 incs
="-I $b -I $b/$wsid"
61 test "$b" = $outd || incs
="$incs -I $outd"
63 lablGL
/*) incs
="-I $b/lablGL";;
64 main.cmo|keys.cmo|utils.cmo|utf8syms.cmo
) incs
="-I $b";;
65 config.cmi
) incs
="-I $outd -I $b -I $b/$wsid";;
66 uiutils.cmi|ffi.cmi
) incs
="-I $b";;
67 glutils.cmi
) incs
="-I $b/lablGL";;
68 main.cmi|keys.cmi|utils.cmi|utf8syms.cmi|parser.cmi
) ;;
69 *) die
"ocaml include paths for '$2' aren't set";;
71 test -z "${incs-}" ||
echo $incs
78 utf8syms.cmo|confstruct.cmo
)
79 f
="-g -strict-sequence -strict-formats -alert @all-missing-mli";;
80 wsi
/x11
/wsi.cm
[io
]) f
="-g -I +unix";;
81 utils.cmi
) f
="-g -I +unix -I +str";;
82 config.cmo|ffi.cmo|main.cmo|utils.cmo|parser.cmo|uiutils.cmo|
help.cmo
)
83 f
="-g -I +unix -I +str -strict-sequence -strict-formats -alert @all-missing-mli";;
84 *) f
="-g -strict-sequence -strict-formats -alert @all -warn-error @A";;
86 echo $
(oincs
$outd $1) $f
91 version.o
) f
=-DLLPP_VERSION=$ver;;
92 lablGL
/*.o
) f
="-g -Wno-pointer-sign -Werror -O2";;
94 f
="-g -std=c11 $muinc -Wall -Werror -Wextra -pedantic "
95 test "${mbt-}" = "debug" || f
+="-O2 "
96 $darwin && f
+="-DMACOS -D_GNU_SOURCE -DGL_H='<OpenGL/gl.h>'" \
97 || f
+="-D_POSIX_C_SOURCE -DGL_H='<GL/gl.h>'"
98 f
+=" -DTEXT_TYPE=GL_TEXTURE_RECTANGLE_ARB"
100 #f+=" -DTEXT_TYPE=GL_TEXTURE_2D"
102 *) f
="-g -O2 -Wall -Werror";;
104 ! $darwin || f
+=" -DGL_SILENCE_DEPRECATION"
109 echo "-I $(ocamlc -where) -g -Wall -Werror -O2 -DGL_SILENCE_DEPRECATION"
112 overs
=$
(ocamlc
-vnum 2>/dev
/null
) || overs
=""
113 if test "$overs" != "5.2.0"; then
114 url
="https://caml.inria.fr/pub/distrib/ocaml-5.2/ocaml-5.2.0.tar.xz"
115 txz
=$outd/$
(basename $url)
116 keycmd
="printf $url; digest $txz;"
117 isfresh
$txz "$(eval $keycmd)" ||
{
118 if executable_p wget
; then dl
() { wget
"$1" -O "$2"; }
119 elif executable_p curl
; then dl
() { curl
-L "$1" -o "$2"; }
120 else die
"no program to fetch remote urls found"
123 eval $keycmd >$txz.past
124 } && vecho
"fresh $txz"
125 absprefix
=$
(realpath
$outd)
126 export PATH
=$absprefix/bin
:$PATH
127 ocamlc
=$absprefix/bin
/ocamlc
128 keycmd
="printf $url; digest $ocamlc;"
129 isfresh
$ocamlc "$(eval $keycmd)" ||
(
130 # This will needlessly re{configure,make} ocaml since "past"
131 # of configure/make is hard to ascertain. "Better safe than
132 # sorry" approach is taken here. The check will work for a
133 # single ocaml url/version, but _will_ redo _everything_
134 # otherwise (even if fully built artifacts are available)
137 cd $outd/${bn%.tar.xz}
138 .
/configure
--disable-ocamldoc --disable-ocamltest \
139 --enable-debugger=no
--prefix=$absprefix
142 eval $keycmd >$absprefix/bin
/ocamlc.past
143 ) && vecho
"fresh ocamlc"
144 overs
=$
(ocamlc
-vnum 2>/dev
/null
)
149 "bytecomp_c_compiler:") ccomp
=${CAML_CC-$v};;
150 "word_size:") ! test "$darwin$v" = "true32" || die
"need 64bit ocaml";;
152 done < <(ocamlc
-config)
154 read cvers
< <($ccomp --version)
158 $gmk ||
:>$outd/Makefile
160 local n
=$1 s
=$2 o
=$3 deps
= cmd d
161 local keycmd
="digest $s $o.depl"
162 cmd
="ocamlc -depend -bytecode -one-line $(oincs $srcd $o) $s"
164 isfresh
"$o.depl" "$overs$cmd$(eval $keycmd)" ||
{
165 read _ _ depl
< <(eval $cmd) || die
"$cmd failed"
167 if test "$d" = "$outd/confstruct.cmo";
168 then d
=confstruct.cmo
; else d
=${d#$srcd/}; fi
171 printf "$deps" >$o.depl
173 echo "$overs$cmd$(eval $keycmd)" >"$o.depl.past"
174 } && vecho
"fresh $o.depl"
176 # this saves time but is overly optimistic as interface (dis)
177 # appearance will result in an invalid (stale) .depl (cache). not
178 # using a cache is correct but slow(er (much)) way to handle this.
184 cmd
="ocamlc $(oflags $o) -c -o $o $s"
185 keycmd
="digest $o $s $deps"
186 isfresh
"$o" "$overs$cmd$(eval $keycmd)" ||
{
187 printf "%*.s%s\n" $n '' "${o#$outd/}"
188 eval "$cmd" || die
"$cmd failed"
189 echo "$overs$cmd$(eval $keycmd)" >"$o.past"
190 } && vecho
"fresh $o"
191 $gmk ||
printf "$o: $deps\n\t%s\n" "$cmd" >>$outd/Makefile
198 [[ ! $seen =~
$1 ]] ||
return 0
199 local s o
=$1 n
=$2 cycle1
=$cycle
201 confstruct.cmo
) s
=$outd/confstruct.ml
;;
202 *.cmo
) s
=$srcd/${o%.cmo}.ml
;;
203 *.cmi
) s
=$srcd/${o%.cmi}.mli
;;
206 [[ "$cycle" =~
"$o" ]] && die cycle
$o || cycle
=$cycle$o
213 read 2>/dev
/null _ d
<$o.dep || d
=
214 local keycmd
='digest $o $d'
215 isfresh
"$o" "$cvers$cmd$(eval $keycmd)" ||
{
217 eval "$cmd" || die
"$cmd failed"
219 echo "$cvers$cmd$(eval $keycmd)" >"$o.past"
220 } && vecho
"fresh $o"
221 $gmk ||
printf "$o: $d\n\t$cmd\n" >>$outd/Makefile
225 local o
=$outd/$1 s
=$srcd/${1%.o}.c cc
=${CAML_CC:+-cc "'$CAML_CC'" }
226 baux
$o "ocamlc $cc-ccopt \"$(cflags $o) -MMD -MF $o.dep -MT_\" -o $o -c $s"
231 baux
$o "$mcomp $(mflags $o) -MD -MF $o.dep -MT_ -c -o $o $srcd/${1%.o}.m"
234 ver
=$
(cd $srcd && git describe
--tags --dirty) || ver
="'built on $(date)'"
236 gen
=$srcd/genconfstruct.sh
237 out
=$outd/confstruct.ml
238 cmd
="(export print paste clip uopen; . $gen >$out)"
239 keycmd
="{ echo '$print $paste $clip $uopen'; digest $gen $out; }"
240 isfresh
"$out" "$cmd$(eval $keycmd)" ||
{
241 echo "generating $out"
242 eval "$cmd" || die
$gen failed
243 echo "$cmd$(eval $keycmd)" > "${out}.past"
244 } && vecho
"fresh $out"
252 for m
in llpp llppac
; do
253 src
=$srcd/adoc
/$m.adoc
255 conf
=$srcd/man
/asciidoc.conf
256 keycmd
="digest $o $src $conf"
257 cmd
="a2x -f manpage -D $md $src"
258 isfresh
"$o" "$cmd$(eval $keycmd)" ||
{
260 eval "$cmd" || die
"$cmd failed"
261 echo "$cmd$(eval $keycmd)" >"$o.past"
262 } && vecho
"fresh $o"
265 *) die
"no such target - '$target'";;
271 [[ ! "$seen" =~
"$1" ]] ||
return 0
274 local wooutd
=${o#$outd/}
276 *.cmi
) flatten
${wooutd%.cmi}.cmo
;;
277 *.cmo
) flatten
$wooutd;;
285 # it might appear that following can be done inside bocaml* but
286 # alas due to the early cmi->cmo descent this ought to be done
287 # here (at least the solution inside bocaml* eludes me)
288 local dep cmo this
=$1
293 test $cmo = $this || collectmodules
$cmo
300 [[ $modules =~
$cmo ]] || modules
+=" $outd/$cmo"
303 collectmodules main.cmo
306 for m
in link cutils version
; do
310 for m
in ml_gl ml_glarray ml_raw
; do
312 cobjs
+=" $outd/lablGL/$m.o"
315 libs
="str.cma unix.cma"
316 clibs
="-L$mudir/build/$mbt -lmupdf -lmupdf-third -lpthread"
319 clibs
+=" -framework Cocoa -framework OpenGL"
320 cobjs
+=" $outd/wsi/cocoa/cocoa.o"
321 bobjc wsi
/cocoa
/cocoa.o
324 cobjs
+=" $outd/wsi/x11/keysym2ucs.o $outd/wsi/x11/xlib.o"
325 bocamlc wsi
/x11
/keysym2ucs.o
326 bocamlc wsi
/x11
/xlib.o
329 cmd
="ocamlc -custom $libs -o $outd/llpp $cobjs $modules -cclib \"$clibs\""
330 cmd
="$cmd -I +unix -I +str"
331 keycmd
="digest $outd/llpp $cobjs $modules $mulibs"
332 isfresh
"$outd/llpp" "$cmd$(eval $keycmd)" ||
{
333 echo linking
$outd/llpp
334 eval "$cmd" || die
"$cmd failed"
335 echo "$cmd$(eval $keycmd)" >"$outd/llpp.past"
336 } && vecho
"fresh llpp"
337 $gmk ||
printf "$outd/llpp: $cobjs $modules $mulibs\n\t$cmd\n" >>$outd/Makefile
340 out
="$outd/llpp.app/Contents/Info.plist"
341 keycmd
="digest $out $srcd/wsi/cocoa/genplist.sh; echo $ver"
342 isfresh
$out "$(eval $keycmd)" ||
{
345 echo "generating $out"
346 (.
$srcd/wsi
/cocoa
/genplist.sh
) >"$out"
347 eval $keycmd>"$out.past"
348 } && vecho
"fresh plist"
350 out
=$outd/llpp.app
/Contents
/MacOS
/llpp
351 keycmd
="digest $out $outd/llpp"
352 isfresh
$out "$(eval $keycmd)" ||
{
354 mkdir
-p "$(dirname $out)"
356 eval $keycmd>"$out.past"
357 } && vecho
"fresh bundle"