-### Java classes.
-
-## Java and Scala source files turn into multiple `.class' files with
-## unpredictable names. Rather than try to guess stable outputs for these
-## sources, we make artificial `timestamp' files and uses these in our
-## dependencies.
-CLASSDIR = $(OUTDIR)cls/
-stamps = $(patsubst %,$(OUTDIR)%.stamp,$1)
-
-clean::; rm -rf $(CLASSDIR)
-CLEANFILES += $(OUTDIR)*.stamp
-
-## Compiling actual Java code. Note that this confuses the resident Scala
-## compiler, so we have to reset it here.
-CLSISH += java
-$(OUTDIR)%.stamp: %.java
- $(call v_tag,JAVAC)mkdir -p $(CLASSDIR) && \
- $(JAVAC) -d $(CLASSDIR) -cp $(CLASSDIR) $(JAVAFLAGS) $< && \
- echo built >$@
- $(V_AT)$(SCALAC_RESET)
-
-## Compiling Scala code.
-CLSEXT += scala
-$(OUTDIR)%.stamp: %.scala
- $(call v_tag,SCALAC)mkdir -p $(CLASSDIR) && \
- $(SCALAC) -d $(CLASSDIR) -cp $(CLASSDIR) $(SCALAFLAGS) $< && \
- echo built >$@
+### Our own native programs.
+
+## Fetching package configuration.
+PKG_CONFIG = pkg-config --static
+PKGS = catacomb mLib
+
+PCOPT.CFLAGS = --cflags
+PCOPT.LIBS = --libs
+
+pkg-config = $(shell \
+ env PKG_CONFIG_LIBDIR=$(call ext-prefix,$1)/lib/pkgconfig \
+ $(PKG_CONFIG) $(PCOPT.$3) $2)
+
+## Definitions.
+APKLIBS += libtripe.so
+libtripe.so_SRCS = jni.c
+libtripe.so_EXTS = mLib catacomb tripe
+libtripe.so_CFLAGS = -I$(call ext-prefix,$1)/include \
+ -I$(call ext-srcdir,tripe)/common \
+ -I$(call ext-srcdir,tripe)/priv \
+ -I$(call ext-srcdir,tripe)/server \
+ -I$(call ext-builddir,$1,tripe)/config \
+ $(call pkg-config,$1,mLib,CFLAGS) \
+ $(call pkg-config,$1,catacomb,CFLAGS)
+libtripe.so_LIBS = $(call ext-builddir,$1,tripe)/server/libtripe.a \
+ $(call ext-builddir,$1,tripe)/priv/libpriv.a \
+ $(call ext-builddir,$1,tripe)/common/libcommon.a \
+ -L$(call ext-prefix,$1)/lib \
+ $(call pkg-config,$1,catacomb,LIBS) \
+ $(call pkg-config,$1,mLib,LIBS)
+
+## Machinery for compiling.
+objdir = $(OUTDIR)/obj.$1
+objects = $(patsubst %.c,$(call objdir,$1)/%$3,$2)
+
+apklib-objects = $(call objects,$1,$($2_SRCS),$3)
+obj-base = $(patsubst $(OUTDIR)/obj.%.o,%,$1)
+obj-type = $(patsubst %/,%,$(dir $(call obj-base,$1)))
+obj-name = $(notdir $(call obj-base,$1))
+obj-tool = $(call tool,$(call obj-type,$1),$2)
+
+define obj-rule
+$1_OBJS := $$(foreach f,$$(FLAVOURS),\
+ $$(call objects,$$f,$$($1_SRCS),.o))
+DEPFILES += $$(foreach f,$$(FLAVOURS),\
+ $$(call objects,$$f,$$($1_SRCS),.d))
+$$($1_OBJS): $$(OUTDIR)/obj.%.o: \
+ $$$$(call obj-name,$$$$@).c \
+ $$$$(call stamps,$$$$(call obj-type,$$$$@),$$$$($1_EXTS))
+ $$(V_AT)mkdir -p $$(dir $$@)
+ $$(call v_tag,CC)$$(call obj-tool,$$@,ENV) \
+ $$(call obj-tool,$$@,CC) -c -o$$@ -MD \
+ $$(call obj-tool,$$@,CFLAGS) \
+ $$(call $1_CFLAGS,$$(call obj-type,$$@)) \
+ $$<
+endef
+$(foreach a,$(APKLIBS), $(eval $(call obj-rule,$a)))
+
+CLEANFILES += $(OUTDIR)/obj.*/*.o $(OUTDIR)/obj.*/*.d
+
+## Machinery for linking.
+JNIDIR.host = $(OUTDIR)
+JNIDIR.ndk = $(OUTDIR)/pkg/lib/$1
+
+define apklib-rule
+INSTFILES += $$(call tool,$1,JNIDIR)/$2
+$$(call tool,$1,JNIDIR)/$2: $$(call objects,$$f,$$($2_SRCS),.o)
+ $$(V_AT)mkdir -p $$(dir $$@)
+ $$(call v_tag,LD)$$(call tool,$1,ENV) \
+ $$(call tool,$1,LD) -o$$@ \
+ $$(call tool,$1,LDFLAGS) -shared \
+ $$^ \
+ $$(call $2_LIBS,$1)
+endef
+
+$(foreach f,$(FLAVOURS), \
+$(foreach a,$(APKLIBS), \
+ $(eval $(call apklib-rule,$f,$a))))
+
+CLEANFILES += $(OUTDIR)/pkg/lib/*/lib*.so $(OUTDIR)/lib*.so