diff mupdf-source/Makefile @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/Makefile	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,666 @@
+# GNU Makefile
+
+-include user.make
+
+ifndef build
+  build := release
+endif
+
+default: apps libs
+
+include Makerules
+
+ifndef OUT
+  OUT := build/$(build_prefix)$(build)$(build_suffix)
+endif
+
+include Makethird
+
+# --- Configuration ---
+
+# Do not specify CFLAGS, LDFLAGS, LIB_LDFLAGS, EXE_LDFLAGS or LIBS on the make
+# invocation line - specify XCFLAGS, XLDFLAGS, XLIB_LDFLAGS, XEXE_LDFLAGS or
+# XLIBS instead. Make ignores any lines in the makefile that set a variable
+# that was set on the command line.
+CFLAGS += $(XCFLAGS) -Iinclude
+LIBS += $(XLIBS) -lm
+
+LDFLAGS += $(XLDFLAGS)
+LIB_LDFLAGS += $(XLIB_LDFLAGS)
+EXE_LDFLAGS += $(XEXE_LDFLAGS)
+
+ifneq ($(threading),no)
+  ifeq ($(HAVE_PTHREAD),yes)
+    THREADING_CFLAGS := $(PTHREAD_CFLAGS) -DHAVE_PTHREAD
+    THREADING_LIBS := $(PTHREAD_LIBS)
+  endif
+endif
+
+VERSION_MAJOR = $(shell grep "define FZ_VERSION_MAJOR" include/mupdf/fitz/version.h | cut -d ' ' -f 3)
+VERSION_MINOR = $(shell grep "define FZ_VERSION_MINOR" include/mupdf/fitz/version.h | cut -d ' ' -f 3)
+VERSION_PATCH = $(shell grep "define FZ_VERSION_PATCH" include/mupdf/fitz/version.h | cut -d ' ' -f 3)
+
+ifneq ($(OS),Darwin)
+  ifneq ($(USE_SONAME),no)
+    SO_VERSION_MAJOR = .$(VERSION_MINOR)
+    SO_VERSION = .$(VERSION_MINOR).$(VERSION_PATCH)
+  endif
+endif
+
+# workaround argument list too long errors
+ifeq (4.0,$(firstword $(sort $(MAKE_VERSION) 4.0)))
+  USE_ARGUMENT_FILE=yes
+else
+  USE_ARGUMENT_FILE=no
+endif
+
+# --- Commands ---
+
+ifneq ($(verbose),yes)
+  QUIET_AR = @ echo "    AR $@" ;
+  QUIET_RANLIB = @ echo "    RANLIB $@" ;
+  QUIET_CC = @ echo "    CC $@" ;
+  QUIET_CXX = @ echo "    CXX $@" ;
+  QUIET_GEN = @ echo "    GEN $@" ;
+  QUIET_LINK = @ echo "    LINK $@" ;
+  QUIET_LINK_SO = @ echo "    LINK_SO $@" ;
+  QUIET_RM = @ echo "    RM $@" ;
+  QUIET_TAGS = @ echo "    TAGS $@" ;
+  QUIET_OBJCOPY = @ echo "    OBJCOPY $@" ;
+  QUIET_SYMLINK = @ echo "    SYMLINK $@" ;
+endif
+
+MKTGTDIR = mkdir -p $(dir $@)
+CC_CMD = $(QUIET_CC) $(MKTGTDIR) ; $(CC) $(CFLAGS) -MMD -MP -o $@ -c $<
+CXX_CMD = $(QUIET_CXX) $(MKTGTDIR) ; $(CXX) $(CFLAGS) $(XCXXFLAGS) -MMD -MP -o $@ -c $<
+ifeq ($(USE_ARGUMENT_FILE),yes)
+  AR_CMD = $(QUIET_AR) $(MKTGTDIR) ; $(AR) cr $@ $(file > $@.in,$^) @$@.in
+else
+  AR_CMD = $(QUIET_AR) $(MKTGTDIR) ; $(AR) cr $@ $^
+endif
+ifdef RANLIB
+  RANLIB_CMD = $(QUIET_RANLIB) $(RANLIB) $@
+endif
+LINK_CMD = $(QUIET_LINK) $(MKTGTDIR) ; $(CC) $(EXE_LDFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+TAGS_CMD = $(QUIET_TAGS) ctags
+OBJCOPY_CMD = $(QUIET_OBJCOPY) $(MKTGTDIR) ; $(LD) -r -b binary -z noexecstack -o $@ $<
+SYMLINK_CMD = $(QUIET_SYMLINK) $(MKTGTDIR) ; ln -sf
+
+ifeq ($(shared),yes)
+  ifeq ($(USE_ARGUMENT_FILE),yes)
+    LINK_SO_CMD = $(QUIET_LINK_SO) $(MKTGTDIR) ; $(CC) $(LIB_LDFLAGS) $(LDFLAGS) -o $@ $(file > $@.in,$^) @$@.in
+  else
+    LINK_SO_CMD = $(QUIET_LINK_SO) $(MKTGTDIR) ; $(CC) $(LIB_LDFLAGS) $(LDFLAGS) -o $@ $^
+  endif
+  ifeq ($(OS),OpenBSD)
+    # OpenBSD linker magic doesn't use soname; so fake it by using -L$(OUT) and -lmupdf.
+    LINK_CMD = $(QUIET_LINK) $(MKTGTDIR) ; $(CC) $(EXE_LDFLAGS) $(LDFLAGS) -o $@ -L$(OUT) \
+	$(subst $(OUT)/libmupdf.$(SO)$(SO_VERSION),-lmupdf,$^) \
+	$(LIBS)
+  endif
+endif
+
+# --- Rules ---
+
+$(OUT)/%.a :
+	$(AR_CMD)
+	$(RANLIB_CMD)
+
+$(OUT)/source/helpers/mu-threads/%.o : source/helpers/mu-threads/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(THREADING_CFLAGS)
+
+$(OUT)/source/helpers/pkcs7/%.o : source/helpers/pkcs7/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(LIBCRYPTO_CFLAGS)
+
+$(OUT)/source/tools/%.o : source/tools/%.c
+	$(CC_CMD) $(LIB_CFLAGS) $(WARNING_CFLAGS) $(THIRD_CFLAGS) $(THREADING_CFLAGS)
+
+$(OUT)/generated/%.o : generated/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) -O0
+
+$(OUT)/platform/x11/%.o : platform/x11/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(X11_CFLAGS)
+
+$(OUT)/platform/x11/curl/%.o : platform/x11/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(X11_CFLAGS) $(CURL_CFLAGS)
+
+$(OUT)/platform/gl/%.o : platform/gl/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(THIRD_CFLAGS) $(THIRD_GLUT_CFLAGS)
+
+ifeq ($(HAVE_OBJCOPY),yes)
+  $(OUT)/source/fitz/noto.o : source/fitz/noto.c
+	$(CC_CMD) $(WARNING_CFLAGS) -Wdeclaration-after-statement -DHAVE_OBJCOPY $(LIB_CFLAGS) $(THIRD_CFLAGS)
+endif
+
+$(OUT)/source/fitz/memento.o : source/fitz/memento.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(THIRD_CFLAGS) -DMEMENTO_MUPDF_HACKS
+
+$(OUT)/source/%.o : source/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) -Wdeclaration-after-statement $(LIB_CFLAGS) $(THIRD_CFLAGS)
+
+$(OUT)/thirdparty/so/source/%.o : thirdparty/so/source/%.c
+	$(CC_CMD) $(WARNING_CFLAGS) -Wdeclaration-after-statement $(LIB_CFLAGS) $(THIRD_CFLAGS)
+
+$(OUT)/source/%.o : source/%.cpp
+	$(CXX_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(THIRD_CFLAGS)
+
+ifeq ($(HAVE_TESSERACT),yes)
+$(OUT)/source/fitz/tessocr.o : source/fitz/tessocr.cpp
+	$(CXX_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(THIRD_CFLAGS) $(TESSERACT_CFLAGS) $(TESSERACT_DEFINES) $(TESSERACT_LANGFLAGS) $(LEPTONICA_CFLAGS)
+endif
+
+ifeq ($(HAVE_LEPTONICA),yes)
+$(OUT)/source/fitz/leptonica-wrap.o : source/fitz/leptonica-wrap.c
+	$(CC_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(THIRD_CFLAGS) $(LEPTONICA_CFLAGS) $(LEPTONICA_DEFINES)
+endif
+
+$(OUT)/source/fitz/barcode.o : source/fitz/barcode.cpp
+	$(CXX_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(THIRD_CFLAGS) $(ZXINGCPP_CFLAGS) $(ZXINGCPP_LANGFLAGS)
+
+$(OUT)/platform/%.o : platform/%.c
+	$(CC_CMD) $(WARNING_CFLAGS)
+
+.PRECIOUS : $(OUT)/%.o # Keep intermediates from chained rules
+
+# --- File lists ---
+
+THIRD_OBJ := $(THIRD_SRC:%.c=$(OUT)/%.o)
+THIRD_OBJ := $(THIRD_OBJ:%.cc=$(OUT)/%.o)
+THIRD_OBJ := $(THIRD_OBJ:%.cpp=$(OUT)/%.o)
+
+THIRD_GLUT_OBJ := $(THIRD_GLUT_SRC:%.c=$(OUT)/%.o)
+
+MUPDF_SRC := $(sort $(wildcard source/fitz/*.c))
+MUPDF_SRC += $(sort $(wildcard source/fitz/*.cpp))
+MUPDF_SRC += $(sort $(wildcard source/pdf/*.c))
+ifneq ($(xps),no)
+MUPDF_SRC += $(sort $(wildcard source/xps/*.c))
+endif
+ifneq ($(svg),no)
+MUPDF_SRC += $(sort $(wildcard source/svg/*.c))
+endif
+ifneq ($(html),no)
+MUPDF_SRC += $(sort $(wildcard source/html/*.c))
+endif
+MUPDF_SRC += $(sort $(wildcard source/reflow/*.c))
+MUPDF_SRC += $(sort $(wildcard source/cbz/*.c))
+
+MUPDF_OBJ := $(MUPDF_SRC:%.c=$(OUT)/%.o)
+MUPDF_OBJ := $(MUPDF_OBJ:%.cpp=$(OUT)/%.o)
+
+THREAD_SRC := source/helpers/mu-threads/mu-threads.c
+THREAD_OBJ := $(THREAD_SRC:%.c=$(OUT)/%.o)
+
+PKCS7_SRC += source/helpers/pkcs7/pkcs7-openssl.c
+PKCS7_OBJ := $(PKCS7_SRC:%.c=$(OUT)/%.o)
+
+# --- Generated embedded font files ---
+
+HEXDUMP_SH := scripts/hexdump.sh
+
+FONT_BIN := $(sort $(wildcard resources/fonts/urw/*.cff))
+FONT_BIN += $(sort $(wildcard resources/fonts/han/*.ttc))
+FONT_BIN += $(sort $(wildcard resources/fonts/droid/DroidSansFallbackFull.ttf))
+FONT_BIN += $(sort $(wildcard resources/fonts/droid/DroidSansFallback.ttf))
+FONT_BIN += $(sort $(wildcard resources/fonts/noto/*.otf))
+FONT_BIN += $(sort $(wildcard resources/fonts/noto/*.ttf))
+FONT_BIN += $(sort $(wildcard resources/fonts/sil/*.cff))
+
+# Note: The tests here must match the equivalent tests in noto.c
+
+ifneq ($(filter -DTOFU_CJK,$(CFLAGS)),)
+  FONT_BIN := $(filter-out resources/fonts/han/%.ttc, $(FONT_BIN))
+  FONT_BIN := $(filter-out resources/fonts/droid/DroidSansFallbackFull.ttf, $(FONT_BIN))
+  FONT_BIN := $(filter-out resources/fonts/droid/DroidSansFallback.ttf, $(FONT_BIN))
+endif
+
+ifneq ($(filter -DTOFU_CJK_EXT,$(CFLAGS)),)
+  FONT_BIN := $(filter-out resources/fonts/han/%.ttc, $(FONT_BIN))
+  FONT_BIN := $(filter-out resources/fonts/droid/DroidSansFallbackFull.ttf, $(FONT_BIN))
+endif
+
+ifneq ($(filter -DTOFU_CJK_LANG,$(CFLAGS)),)
+  FONT_BIN := $(filter-out resources/fonts/han/%.ttc, $(FONT_BIN))
+endif
+
+ifneq ($(filter -DTOFU,$(CFLAGS)),)
+  FONT_BIN := $(filter-out resources/fonts/noto/%.otf,$(FONT_BIN))
+  FONT_BIN := $(filter-out resources/fonts/noto/%.ttf,$(FONT_BIN))
+  FONT_BIN := $(filter-out resources/fonts/sil/%.cff,$(FONT_BIN))
+endif
+
+ifneq ($(filter -DTOFU_NOTO,$(CFLAGS)),)
+  FONT_BIN := $(filter-out resources/fonts/noto/%.otf,$(FONT_BIN))
+  FONT_BIN := $(filter-out resources/fonts/noto/%.ttf,$(FONT_BIN))
+endif
+
+ifneq ($(filter -DTOFU_SIL,$(CFLAGS)),)
+  FONT_BIN := $(filter-out resources/fonts/sil/%.cff,$(FONT_BIN))
+endif
+
+FONT_GEN := $(FONT_BIN:%=generated/%.c)
+
+generated/%.cff.c : %.cff $(HEXDUMP_SH) ; $(QUIET_GEN) $(MKTGTDIR) ; bash $(HEXDUMP_SH) > $@ $<
+generated/%.otf.c : %.otf $(HEXDUMP_SH) ; $(QUIET_GEN) $(MKTGTDIR) ; bash $(HEXDUMP_SH) > $@ $<
+generated/%.ttf.c : %.ttf $(HEXDUMP_SH) ; $(QUIET_GEN) $(MKTGTDIR) ; bash $(HEXDUMP_SH) > $@ $<
+generated/%.ttc.c : %.ttc $(HEXDUMP_SH) ; $(QUIET_GEN) $(MKTGTDIR) ; bash $(HEXDUMP_SH) > $@ $<
+
+ifeq ($(HAVE_OBJCOPY),yes)
+  MUPDF_OBJ += $(FONT_BIN:%=$(OUT)/%.o)
+  $(OUT)/%.cff.o : %.cff ; $(OBJCOPY_CMD)
+  $(OUT)/%.otf.o : %.otf ; $(OBJCOPY_CMD)
+  $(OUT)/%.ttf.o : %.ttf ; $(OBJCOPY_CMD)
+  $(OUT)/%.ttc.o : %.ttc ; $(OBJCOPY_CMD)
+else
+  MUPDF_OBJ += $(FONT_GEN:%.c=$(OUT)/%.o)
+endif
+
+generate: $(FONT_GEN)
+
+# --- Generated ICC profiles ---
+
+source/fitz/icc/%.icc.h: resources/icc/%.icc
+	$(QUIET_GEN) xxd -i $< | \
+		sed 's/unsigned/static const unsigned/' | \
+		sed '1i// This is an automatically generated file. Do not edit.' \
+		> $@
+
+generate: source/fitz/icc/gray.icc.h
+generate: source/fitz/icc/rgb.icc.h
+generate: source/fitz/icc/cmyk.icc.h
+generate: source/fitz/icc/lab.icc.h
+
+# --- Generated CMap files ---
+
+CMAP_GEN := $(notdir $(sort $(wildcard resources/cmaps/*)))
+CMAP_GEN := $(CMAP_GEN:%=source/pdf/cmaps/%.h)
+
+source/pdf/cmaps/%.h: resources/cmaps/% scripts/cmapdump.py
+	$(QUIET_GEN) python3 scripts/cmapdump.py > $@ $<
+
+generate: $(CMAP_GEN)
+
+# --- Generated embedded javascript files ---
+
+source/pdf/js/%.js.h: source/pdf/js/%.js scripts/jsdump.sed
+	$(QUIET_GEN) sed -f scripts/jsdump.sed < $< > $@
+
+generate: source/pdf/js/util.js.h
+
+# --- Generated perfect hash source files ---
+
+source/html/css-properties.h: source/html/css-properties.gperf
+	$(QUIET_GEN) gperf > $@ $<
+
+generate: source/html/css-properties.h
+
+# --- Library ---
+
+ifeq ($(shared),yes)
+  $(OUT)/libmupdf.$(SO)$(SO_VERSION): $(MUPDF_OBJ) $(THIRD_OBJ)
+	$(LINK_SO_CMD) $(THIRD_LIBS) $(LIBCRYPTO_LIBS) $(LIBS)
+  ifeq ($(OS),OpenBSD)
+    # should never create symlink
+    MUPDF_LIB = $(OUT)/libmupdf.$(SO)$(SO_VERSION)
+  else
+    MUPDF_LIB = $(OUT)/libmupdf.$(SO)
+    ifneq ($(SO_VERSION),)
+      # create symlink with soname if needed
+      $(OUT)/libmupdf.$(SO): $(OUT)/libmupdf.$(SO)$(SO_VERSION)
+	$(SYMLINK_CMD) $(notdir $<) $@
+    endif
+  endif
+else
+  MUPDF_LIB = $(OUT)/libmupdf.a
+  THIRD_LIB = $(OUT)/libmupdf-third.a
+  $(MUPDF_LIB) : $(MUPDF_OBJ)
+  $(THIRD_LIB) : $(THIRD_OBJ)
+endif
+
+ifneq ($(USE_SYSTEM_GLUT),yes)
+  THIRD_GLUT_LIB = $(OUT)/libmupdf-glut.a
+  $(THIRD_GLUT_LIB) : $(THIRD_GLUT_OBJ)
+endif
+
+THREAD_LIB = $(OUT)/libmupdf-threads.a
+$(THREAD_LIB) : $(THREAD_OBJ)
+
+PKCS7_LIB = $(OUT)/libmupdf-pkcs7.a
+$(PKCS7_LIB) : $(PKCS7_OBJ)
+
+# --- Main tools and viewers ---
+
+MUTOOL_SRC := source/tools/mutool.c
+MUTOOL_SRC += source/tools/muconvert.c
+MUTOOL_SRC += source/tools/mudraw.c
+MUTOOL_SRC += source/tools/murun.c
+MUTOOL_SRC += source/tools/mutrace.c
+MUTOOL_SRC += source/tools/mubar.c
+MUTOOL_SRC += source/tools/cmapdump.c
+MUTOOL_SRC += $(sort $(wildcard source/tools/pdf*.c))
+MUTOOL_OBJ := $(MUTOOL_SRC:%.c=$(OUT)/%.o)
+MUTOOL_EXE := $(OUT)/mutool
+$(MUTOOL_EXE) : $(MUTOOL_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(PKCS7_LIB) $(THREAD_LIB)
+	$(LINK_CMD) $(THIRD_LIBS) $(THREADING_LIBS) $(LIBCRYPTO_LIBS)
+TOOL_APPS += $(MUTOOL_EXE)
+
+MURASTER_OBJ := $(OUT)/source/tools/muraster.o
+MURASTER_EXE := $(OUT)/muraster
+$(MURASTER_EXE) : $(MURASTER_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(PKCS7_LIB) $(THREAD_LIB)
+	$(LINK_CMD) $(THIRD_LIBS) $(THREADING_LIBS) $(LIBCRYPTO_LIBS)
+EXTRA_TOOL_APPS += $(MURASTER_EXE)
+
+ifeq ($(HAVE_GLUT),yes)
+  MUVIEW_GLUT_SRC += $(sort $(wildcard platform/gl/*.c))
+  MUVIEW_GLUT_OBJ := $(MUVIEW_GLUT_SRC:%.c=$(OUT)/%.o)
+  MUVIEW_GLUT_EXE := $(OUT)/mupdf-gl
+  $(MUVIEW_GLUT_EXE) : $(MUVIEW_GLUT_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(THIRD_GLUT_LIB) $(PKCS7_LIB)
+	$(LINK_CMD) $(THIRD_LIBS) $(LIBCRYPTO_LIBS) $(THIRD_GLUT_LIBS)
+  VIEW_APPS += $(MUVIEW_GLUT_EXE)
+endif
+
+ifeq ($(HAVE_X11),yes)
+  MUVIEW_X11_EXE := $(OUT)/mupdf-x11
+  MUVIEW_X11_OBJ += $(OUT)/platform/x11/pdfapp.o
+  MUVIEW_X11_OBJ += $(OUT)/platform/x11/x11_main.o
+  MUVIEW_X11_OBJ += $(OUT)/platform/x11/x11_image.o
+  $(MUVIEW_X11_EXE) : $(MUVIEW_X11_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(PKCS7_LIB)
+	$(LINK_CMD) $(THIRD_LIBS) $(X11_LIBS) $(LIBCRYPTO_LIBS)
+  VIEW_APPS += $(MUVIEW_X11_EXE)
+endif
+
+ifeq ($(HAVE_X11),yes)
+ifeq ($(HAVE_CURL),yes)
+ifeq ($(HAVE_PTHREAD),yes)
+  MUVIEW_X11_CURL_EXE := $(OUT)/mupdf-x11-curl
+  MUVIEW_X11_CURL_OBJ += $(OUT)/platform/x11/curl/pdfapp.o
+  MUVIEW_X11_CURL_OBJ += $(OUT)/platform/x11/curl/x11_main.o
+  MUVIEW_X11_CURL_OBJ += $(OUT)/platform/x11/curl/x11_image.o
+  MUVIEW_X11_CURL_OBJ += $(OUT)/platform/x11/curl/curl_stream.o
+  MUVIEW_X11_CURL_OBJ += $(OUT)/platform/x11/curl/prog_stream.o
+  $(MUVIEW_X11_CURL_EXE) : $(MUVIEW_X11_CURL_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(PKCS7_LIB) $(CURL_LIB)
+	$(LINK_CMD) $(THIRD_LIBS) $(X11_LIBS) $(LIBCRYPTO_LIBS) $(CURL_LIBS) $(PTHREAD_LIBS)
+  EXTRA_VIEW_APPS += $(MUVIEW_X11_CURL_EXE)
+endif
+endif
+endif
+
+# --- Generated dependencies ---
+
+-include $(MUPDF_OBJ:%.o=%.d)
+-include $(PKCS7_OBJ:%.o=%.d)
+-include $(THREAD_OBJ:%.o=%.d)
+-include $(THIRD_OBJ:%.o=%.d)
+-include $(THIRD_GLUT_OBJ:%.o=%.d)
+
+-include $(MUTOOL_OBJ:%.o=%.d)
+-include $(MUVIEW_GLUT_OBJ:%.o=%.d)
+-include $(MUVIEW_X11_OBJ:%.o=%.d)
+
+-include $(MURASTER_OBJ:%.o=%.d)
+-include $(MUVIEW_X11_CURL_OBJ:%.o=%.d)
+
+# --- Examples ---
+
+examples: $(OUT)/example $(OUT)/multi-threaded $(OUT)/storytest
+
+$(OUT)/example: docs/examples/example.c $(MUPDF_LIB) $(THIRD_LIB)
+	$(LINK_CMD) $(CFLAGS) $(THIRD_LIBS)
+$(OUT)/multi-threaded: docs/examples/multi-threaded.c $(MUPDF_LIB) $(THIRD_LIB)
+	$(LINK_CMD) $(CFLAGS) $(THIRD_LIBS) -lpthread
+$(OUT)/storytest: docs/examples/storytest.c $(MUPDF_LIB) $(THIRD_LIB)
+	$(LINK_CMD) $(CFLAGS) $(THIRD_LIBS)
+
+# --- Format man pages ---
+
+%.txt: %.1
+	nroff -man $< | col -b | expand > $@
+
+MAN_FILES := $(sort $(wildcard docs/man/*.1))
+TXT_FILES := $(MAN_FILES:%.1=%.txt)
+
+catman: $(TXT_FILES)
+
+# --- Install ---
+
+prefix ?= /usr/local
+bindir ?= $(prefix)/bin
+libdir ?= $(prefix)/lib
+incdir ?= $(prefix)/include
+mandir ?= $(prefix)/share/man
+docdir ?= $(prefix)/share/doc/mupdf
+pydir ?= $(shell python3 -c "import sysconfig; print(sysconfig.get_path('platlib'))")
+SO_INSTALL_MODE ?= 644
+
+third: $(THIRD_LIB)
+extra-libs: $(THIRD_GLUT_LIB)
+libs: $(MUPDF_LIB) $(THIRD_LIB) $(COMMERCIAL_LIBS)
+commercial-libs: $(COMMERCIAL_LIBS)
+tools: $(TOOL_APPS)
+apps: $(TOOL_APPS) $(VIEW_APPS)
+extra-apps: $(EXTRA_TOOL_APPS) $(EXTRA_VIEW_APPS)
+libmupdf-threads: $(THREAD_LIB)
+
+install-headers:
+	install -d $(DESTDIR)$(incdir)/mupdf
+	install -d $(DESTDIR)$(incdir)/mupdf/fitz
+	install -d $(DESTDIR)$(incdir)/mupdf/pdf
+	install -m 644 include/mupdf/*.h $(DESTDIR)$(incdir)/mupdf
+	install -m 644 include/mupdf/fitz/*.h $(DESTDIR)$(incdir)/mupdf/fitz
+	install -m 644 include/mupdf/pdf/*.h $(DESTDIR)$(incdir)/mupdf/pdf
+
+install-libs: libs install-headers
+	install -d $(DESTDIR)$(libdir)
+ifeq ($(shared),yes)
+	install -m $(SO_INSTALL_MODE) $(OUT)/libmupdf.$(SO)$(SO_VERSION) $(DESTDIR)$(libdir)/libmupdf.$(SO)$(SO_VERSION)
+  ifneq ($(OS),OpenBSD)
+	ln -sf libmupdf.$(SO)$(SO_VERSION) $(DESTDIR)$(libdir)/libmupdf.$(SO)$(SO_VERSION_MAJOR)
+	ln -sf libmupdf.$(SO)$(SO_VERSION) $(DESTDIR)$(libdir)/libmupdf.$(SO)
+  endif
+else
+	install -m 644 $(MUPDF_LIB) $(DESTDIR)$(libdir)
+	install -m 644 $(THIRD_LIB) $(DESTDIR)$(libdir)
+endif
+
+install-tools: tools
+	install -d $(DESTDIR)$(bindir)
+	install -m 755 $(TOOL_APPS) $(DESTDIR)$(bindir)
+
+install-apps: apps
+	install -d $(DESTDIR)$(bindir)
+	install -m 755 $(TOOL_APPS) $(VIEW_APPS) $(DESTDIR)$(bindir)
+
+install-extra-apps: install-apps extra-apps
+	install -d $(DESTDIR)$(bindir)
+	install -m 755 $(EXTRA_TOOL_APPS) $(EXTRA_VIEW_APPS) $(DESTDIR)$(bindir)
+
+install-docs:
+	install -d $(DESTDIR)$(mandir)/man1
+	install -m 644 docs/man/*.1 $(DESTDIR)$(mandir)/man1
+	install -d $(DESTDIR)$(docdir)
+	install -d $(DESTDIR)$(docdir)/examples
+	install -m 644 README CHANGES $(DESTDIR)$(docdir)
+	install -m 644 $(wildcard COPYING LICENSE) $(DESTDIR)$(docdir)
+	install -m 644 docs/examples/* $(DESTDIR)$(docdir)/examples
+
+install: install-libs install-apps install-docs
+
+docs:
+	bash scripts/build-docs.sh
+
+docs-live:
+	bash scripts/build-docs-live.sh
+
+docs-markdown:
+	bash scripts/build-docs-markdown.sh
+
+docs-clean:
+	rm -rf build/docs
+	rm -rf build/venv-docs
+	rm -rf build/.doctrees
+
+install-docs-html: docs
+	mkdir -p $(DESTDIR)$(docdir)
+	cp -r build/docs/* $(DESTDIR)$(docdir)
+
+tarball:
+	bash scripts/archive.sh
+
+# --- Clean and Default ---
+
+WATCH_SRCS = $(shell find include source platform -type f -name '*.[ch]')
+watch:
+	@ inotifywait -q -e modify $(WATCH_SRCS)
+
+watch-recompile:
+	@ while ! inotifywait -q -e modify $(WATCH_SRCS) ; do time -p $(MAKE) ; done
+
+java:
+	$(MAKE) -C platform/java build=$(build)
+
+java-clean:
+	$(MAKE) -C platform/java build=$(build) clean
+
+wasm:
+	$(MAKE) -C platform/wasm
+
+wasm-clean:
+	$(MAKE) -C platform/wasm clean
+
+extract-test:
+	$(MAKE) debug
+	$(MAKE) -C thirdparty/extract mutool=../../build/debug/mutool test-mutool
+
+TAG_HDR_FILES=$(shell git ls-files | grep -v '^\(docs\|scripts\|generated\)' | grep '\.h$$')
+TAG_SRC_FILES=$(shell git ls-files | grep -v '^\(docs\|scripts\|generated\)' | grep -v '\.h$$')
+
+tags:
+	$(TAGS_CMD) --sort=no --c-kinds=+p-t $(TAG_SRC_FILES)
+	$(TAGS_CMD) -a --sort=no --c-kinds=+p-t $(TAG_HDR_FILES)
+	$(TAGS_CMD) -a --sort=no --c-kinds=t $(TAG_SRC_FILES) $(TAG_HDR_FILES)
+
+find-try-return:
+	@ bash scripts/find-try-return.sh
+
+cscope.files: $(shell find include source platform -name '*.[ch]')
+	@ echo $^ | tr ' ' '\n' > $@
+
+cscope.out: cscope.files
+	cscope -b
+
+all: libs apps extra-apps
+
+clean:
+	rm -rf $(OUT)
+nuke:
+	rm -rf build/*
+	rm -rf generated/resources/fonts/droid
+	rm -rf generated/resources/fonts/han
+	rm -rf generated/resources/fonts/noto
+	rm -rf generated/resources/fonts/sil
+
+release:
+	$(MAKE) build=release
+debug:
+	$(MAKE) build=debug
+sanitize:
+	$(MAKE) build=sanitize
+
+shared: shared-$(build)
+
+shared-release:
+	$(MAKE) shared=yes build=release
+shared-debug:
+	$(MAKE) shared=yes build=debug
+shared-clean:
+	rm -rf build/shared-*
+
+android: generate
+	ndk-build -j8 \
+		APP_BUILD_SCRIPT=platform/java/Android.mk \
+		APP_PROJECT_PATH=build/android \
+		APP_PLATFORM=android-16 \
+		APP_OPTIM=$(build)
+
+# --- C++, Python and C#, and system installation ---
+
+c++: c++-$(build)
+python: python-$(build)
+csharp: csharp-$(build)
+
+c++-clean:
+	rm -rf platform/c++
+python-clean:
+	rm -rf platform/python
+csharp-clean:
+	rm -rf platform/csharp
+
+# $(OUT) only contains the `shared-` infix if shared=yes and targets that
+# require shared-libraries only work if shared=yes. So if this is not the case,
+# we re-run ourselves with `$(MAKE) shared=yes $@`.
+
+ifeq ($(shared),yes)
+
+# We can build targets that require shared libraries and use $(OUT).
+
+# Assert that $(OUT) contains `shared`.
+ifeq ($(findstring shared, $(OUT)),)
+  $(error OUT=$(OUT) does not contain shared)
+endif
+
+# C++, Python and C# shared libraries.
+#
+# To disable automatic use of a venv, use `make VENV_FLAG= ...` or `VENV_FLAG=
+# make ...`.
+#
+VENV_FLAG ?= --venv
+c++-%: shared-%
+	./scripts/mupdfwrap.py $(VENV_FLAG) -d $(OUT) -b 01
+python-%: c++-%
+	./scripts/mupdfwrap.py $(VENV_FLAG) -d $(OUT) -b 23
+csharp-%: c++-%
+	./scripts/mupdfwrap.py $(VENV_FLAG) -d $(OUT) -b --csharp 23
+
+# Installs of C, C++, Python and C# shared libraries
+#
+# We only allow install of shared libraries if we are not using any libraries
+# in thirdparty/.
+install-shared-check:
+ifneq ($(shared),yes)
+	@ echo "install-shared-* requires that shared=yes."
+	@ false
+endif
+ifneq ($(USE_SYSTEM_LIBS),yes)
+	@ echo "install-shared-* requires that USE_SYSTEM_LIBS=yes."
+	@ false
+endif
+
+install-shared-c: install-shared-check install-libs install-headers
+
+install-shared-c++: install-shared-c c++
+	install -m 644 platform/c++/include/mupdf/*.h $(DESTDIR)$(incdir)/mupdf
+	install -m $(SO_INSTALL_MODE) $(OUT)/libmupdfcpp.$(SO)$(SO_VERSION) $(DESTDIR)$(libdir)/
+ifneq ($(OS),OpenBSD)
+	ln -sf libmupdfcpp.$(SO)$(SO_VERSION) $(DESTDIR)$(libdir)/libmupdfcpp.$(SO)
+	ln -sf libmupdfcpp.$(SO)$(SO_VERSION) $(DESTDIR)$(libdir)/libmupdfcpp.$(SO)$(SO_VERSION_MAJOR)
+endif
+
+install-shared-python: install-shared-c++ python
+	install -d $(DESTDIR)$(pydir)/mupdf
+	install -m $(SO_INSTALL_MODE) $(OUT)/_mupdf.$(SO) $(DESTDIR)$(pydir)/mupdf
+	install -m 644 $(OUT)/mupdf.py $(DESTDIR)$(pydir)/mupdf/__init__.py
+
+else
+
+# $(shared) != yes. For all targets that require a shared-library build and use
+# $(OUT), we need to re-run ourselves with shared=yes.
+install-% c++-% python-% csharp-%:
+	# Running: $(MAKE) shared=yes $@
+	$(MAKE) shared=yes $@
+
+endif
+
+.PHONY: all clean nuke install third libs apps generate tags docs
+.PHONY: shared shared-debug shared-clean
+.PHONY: c++-% python-% csharp-%
+.PHONY: c++-clean python-clean csharp-clean