PACKAGE = tripe-android
VERSION := $(shell ./auto-version)
+VSN = 1
.SECONDEXPANSION: #sorry
###--------------------------------------------------------------------------
-### Build parameters.
+### Preliminary magic.
-## Where to put the object files.
-OUTDIR = out/
+empty =
+space = $(empty) $(empty)
+comma = ,
-## Native C compiler.
-CC = gcc
-CFLAGS = -O2 -g -Wall -pedantic -Werror
+definedp = $(filter-out undefined,$(origin $1))
+defaulting = $(if $(call definedp,$1),$($1),$2)
-## Native linker.
-LD = gcc
-LDFLAGS.so = -shared
+all::
-## External `pkg-config' packages required.
-PKGS = mLib catacomb
+###--------------------------------------------------------------------------
+### Build parameters.
-## Java development kit.
-JDKDIR = /usr/lib/jvm/default-java
-JDK_PLAT = linux
-JNI_INCLUDES = $(JDKDIR)/include $(JDKDIR)/include/$(JDK_PLAT)
+abs_srcdir := $(abspath .)
+hostos := $(shell uname -s | tr A-Z a-z)
+hostcpu := $(shell uname -m | tr A-Z a-z)
-## Default arguments for the Java runtime.
-JAVADEFS =
+## Of course we have `ccache'.
+CCACHE := $(shell \
+ if ccache --version >/dev/null 2>&1; then echo ccache; fi)
+
+## Where to put the object files.
+OUTDIR = out
+CONFIGDIR = $(OUTDIR)/config-$(hostcpu)
## The Java runtime, for some reason, hardcodes its default for
## `java.io.tmpdir', inviting security problems. If the user has defined a
## `TMPDIR', then persuade Java to use it.
-explicit-tmpdir-p = $(if $(filter-out undefined,$(origin TMPDIR)),t,nil)
+explicit-tmpdir-p = $(if $(call definedp,TMPDIR),t,nil)
ifeq ($(explicit-tmpdir-p), t)
JAVADEFS += -Djava.io.tmpdir=$(TMPDIR)
endif
## Java compiler.
-JAVAC = javac $(JAVADEFS)
-JAVAFLAGS =
+JAVAC = javac $(addprefix -J,$(JAVADEFS))
+JAVAFLAGS = -source 1.6 -target 1.6
## Scala compiler.
##
NOIP = noip
endif
ifeq "$(explicit-tmpdir-p),$(noip-available-p)" "t,t"
- SCALAC = $(NOIP) fsc $(JAVADEFS)
+ SCALAC = noip fsc $(JAVADEFS)
+ SCALA = noip scala $(JAVADEFS)
SCALAC_RESET = $(SCALAC) -reset
else
SCALAC = scalac $(JAVADEFS)
+ SCALA = scala $(JAVADEFS) -nc
SCALAC_RESET =
endif
SCALAFLAGS = -optimise -feature -deprecation -Xfatal-warnings \
-Xlint -Xlint:-package-object-classes \
- -Yinline-warnings:false
-SCALA_REPL = $(NOIP) scala $(JAVADEFS)
+ -Yinline-warnings:false -target:jvm-1.6 \
+ -Yno-load-impl-class
+
+## Basic C toolchain flags.
+CFLAGS = -O2 -g -Wall
+LDFLAGS = -Wl,-z,defs
+
+## Host toolchain.
+FLAVOURS += host-$(hostcpu)
+ENV.host-$(hostcpu) =
+CC.host-$(hostcpu) = gcc
+CFLAGS.host-$(hostcpu) = $(CFLAGS) -fPIC
+LD.host-$(hostcpu) = $(CC.host-$(hostcpu))
+LDFLAGS.host-$(hostcpu) = $(LDFLAGS)
+CONFIG.host-$(hostcpu) =
+
+## Host JNI machinery.
+$(CONFIGDIR)/jdkdir.mk:
+ $(V_AT)mkdir -p $(dir $@)
+ $(call v_tag,CONFIG)java -XshowSettings:properties 2>&1 | \
+ sed -n 's:^ *java\.home *= *\(.*\)/jre$$:JDKDIR = \1:p' >$@.new
+ $(V_AT)mv $@.new $@
+REALCLEANFILES += $(CONFIGDIR)/jdkdir.mk
+include $(CONFIGDIR)/jdkdir.mk
+
+JDKPLAT := $(shell \
+ case $(hostos) in \
+ (darwin) echo macosx ;; \
+ (*) echo $(hostos) ;; \
+ esac)
+CFLAGS.host-$(hostcpu) += -I$(JDKDIR)/include -I$(JDKDIR)/include/$(JDKPLAT)
+
+## Android SDK location.
+ANDROID_SDKDIR = /usr/local/android/sdk
+MINAPI = 15
+TARGETAPI = 23
+TOOLVERSION = 4.9
+
+## Android ABI definitions. We don't bother with `armeabi-v7a': we'll use
+## fancy CPU features if we detect that they're available at runtime anyway.
+ANDROID_ABIS += armeabi
+GNUARCH.armeabi = arm-linux-androideabi
+PLATARCH.armeabi = arm
+CFLAGS.ndk-armeabi =
+
+ANDROID_ABIS += arm64-v8a
+GNUARCH.arm64-v8a = aarch64-linux-android
+PLATARCH.arm64-v8a = arm64
+MINAPI.arm64-v8a = 21
+
+ANDROID_ABIS += x86
+TOOLCHAINDIR.x86 = x86
+GNUARCH.x86 = i686-linux-android
+PLATARCH.x86 = x86
+
+ANDROID_ABIS += x86_64
+TOOLCHAINDIR.x86_64 = x86_64
+GNUARCH.x86_64 = x86_64-linux-android
+PLATARCH.x86_64 = x86_64
+MINAPI.x86_64 = 21
+
+FLAVOURS += $(ANDROID_ABIS)
+
+## Build variants.
+VARIANTS += debug
+AAPTFLAGS.debug = --debug-mode \
+ --rename-manifest-package uk.org.distorted.tripe.debug
+KEYSTORE.debug = debug.keystore
+JARSIGNERFLAGS.debug = -storepass public -keypass public
+
+VARIANTS += release
+KEYSTORE.release = release.keystore
+JARSIGNERFLAGS.release =
+
+## Android NDK location.
+ANDROID_NDKDIR = $(ANDROID_SDKDIR)/ndk-bundle
+NDK_HOSTARCH = $(hostos)-$(hostcpu)
+
+## Android NDK toolchains.
+ndk-sysroot = \
+ $(ANDROID_NDKDIR)/platforms/android-$(call defaulting,MINAPI.$1,$(MINAPI))/arch-$(PLATARCH.$1)
+ndk-toolchain-bin = \
+ $(ANDROID_NDKDIR)/toolchains/$(call defaulting,TOOLCHAINDIR.$1,$(GNUARCH.$1))-$(TOOLVERSION)/prebuilt/$(NDK_HOSTARCH)/bin
+ENV.ndk = env PATH=$(call ndk-toolchain-bin,$1):$$PATH
+CC.ndk = $(GNUARCH.$1)-gcc
+LD.ndk = $(CC.ndk)
+CFLAGS.ndk = $(CFLAGS) -fPIC $(CFLAGS.ndk-$1) \
+ -D__ANDROID_API__=$(call defaulting,MINAPI.$1,$(MINAPI)) \
+ --sysroot=$(call ndk-sysroot,$1) \
+ -isystem $(ANDROID_NDKDIR)/sysroot/usr/include \
+ -isystem $(ANDROID_NDKDIR)/sysroot/usr/include/$(GNUARCH.$1)
+LDFLAGS.ndk = $(LDFLAGS) -pie \
+ --sysroot=$(call ndk-sysroot,$1)
+CONFIG.ndk = --host=$(GNUARCH.$1)
+
+## Flavour options.
+tool = $(call defaulting,$2.$1,$(call $2.ndk,$1))
+
+## Subject name for debug key.
+DEBUGDN = CN=Straylight/Edgeware, L=Cambridge, C=GB
+
+## Android libraries.
+ANDROID_JAR = \
+ $(ANDROID_SDKDIR)/platforms/android-$(MINAPI)/android.jar
+
+## Scala libraries.
+$(CONFIGDIR)/scaladir.mk:
+ $(V_AT)mkdir -p $(dir $@)
+ $(call v_tag,CONFIG)$(SCALA) -J-XshowSettings:properties -help 2>&1 | \
+ sed -n 's:^ *scala\.home *= *:SCALADIR = :p' >$@.new
+ $(V_AT)mv $@.new $@
+include $(CONFIGDIR)/scaladir.mk
+REALCLEANFILES += $(CONFIGDIR)/scaladir.mk
+SCALA_LIB = $(SCALADIR)/lib/scala-library.jar
## Silent-rules is on by default.
V = 0
V_AT_0 = @
###--------------------------------------------------------------------------
-### External native packages.
-
-PKGS_CFLAGS := $(foreach p,$(PKGS),$(shell pkg-config --cflags $p))
-PKGS_LIBS := $(foreach p,$(PKGS),$(shell pkg-config --libs $p))
+### Other handy functions.
-ALL_CFLAGS = $(CFLAGS) -fPIC \
- $(addprefix -I,$(JNI_INCLUDES)) \
- $(PKGS_CFLAGS)
+join-paths = $(if $(filter /%,$2),$2,$1/$2)
-LIBS = $(PKGS_LIBS)
-
-###--------------------------------------------------------------------------
-### Various other tweaks and overrides.
-
-## Hack around https://issues.scala-lang.org/browse/SI-9689
-SCALAFLAGS += -Yno-load-impl-class
+## Datestamp files.
+STAMPDIR = $(OUTDIR)/stamp
+stamps = $(patsubst %,$(STAMPDIR)/%.$1-stamp,$2)
+stamp-base = $(patsubst $(STAMPDIR)/%-stamp,%,$1)
+stamp-name = $(basename $(call stamp-base,$1))
+stamp-type = $(patsubst .%,%,$(suffix $(call stamp-base,$1)))
###--------------------------------------------------------------------------
### And now we can start building things.
all::
.PHONY: all
-CLEANFILES =
clean::
.PHONY: clean
-###--------------------------------------------------------------------------
-### Native C code.
+realclean:: clean
+.PHONY: realclean
-out/%.o: %.c
- $(call v_tag,CC)mkdir -p $(OUTDIR) && \
- $(CC) -c $(ALL_CFLAGS) -MMD -o$@ $<
+distclean:: realclean
+.PHONY: distclean
-ALL_SOURCES =
-DISTFILES += $(ALL_SOURCES)
+###--------------------------------------------------------------------------
+### External native packages.
-objects = $(patsubst %.c,$(OUTDIR)%$2,$1)
-CLEANFILES += $(OUTDIR)*.o $(OUTDIR)*.d
+## Definitions.
+EXTERNALS += adns
+adns_CONFIG = --disable-dynamic
+
+EXTERNALS += mLib
+mLib_DEPS = adns
+mLib_CONFIG = --enable-static --disable-shared --with-adns
+
+EXTERNALS += catacomb
+catacomb_DEPS = mLib
+catacomb_CONFIG = --enable-static --disable-shared
+
+EXTERNALS += tripe
+tripe_DEPS = mLib catacomb
+tripe_CONFIG = --without-wireshark --with-adns --with-tunnel=slip
+
+## Machinery.
+ext-stamps = $(foreach f,$2,$(call stamps,$f,$1))
+
+ext-srcdir = $(call defaulting,$1_SRCDIR,../$1)
+ext-builddir = $(OUTDIR)/build.$1/$2
+ext-prefix = $(OUTDIR)/inst.$1
+ext-absprefix = $(abs_srcdir)/$(call ext-prefix,$1)
+
+ext-stamp-srcdir = $(call ext-srcdir,$(call stamp-name,$1))
+ext-stamp-builddir = \
+ $(call ext-builddir,$(call stamp-type,$1),$(call stamp-name,$1))
+ext-stamp-absprefix = $(call ext-absprefix,$(call stamp-type,$1))
+ext-stamp-tool = $(call tool,$(call stamp-type,$1),$2)
+
+$(foreach e,$(EXTERNALS),\
+ $(eval $e_VERSION := $$(shell cd $$(call ext-srcdir,$e) && $$(abs_srcdir)/auto-version)))
+
+EXTSTAMPS = $(call ext-stamps,$(EXTERNALS),$(FLAVOURS))
+
+$(EXTSTAMPS): \
+ $(STAMPDIR)/%-stamp: \
+ $$(call ext-stamps, \
+ $$($$(call stamp-name,$$@)_DEPS), \
+ $$(call stamp-type,$$@))
+ $(V_AT)mkdir -p $(STAMPDIR)
+ $(V_AT)rm -rf $(call ext-stamp-builddir,$@)
+ $(V_AT)mkdir -p $(call ext-stamp-builddir,$@)
+ cd $(call ext-stamp-builddir,$@) && \
+ $(call ext-stamp-tool,$@,ENV) \
+ $(call join-paths,../../..,$(call ext-stamp-srcdir,$@))/configure \
+ --prefix=$(call ext-stamp-absprefix,$@) \
+ $(call ext-stamp-tool,$@,CONFIG) \
+ $($(call stamp-name,$@)_CONFIG) \
+ CC="$(CCACHE) $(call ext-stamp-tool,$@,CC)" \
+ CFLAGS="$(call ext-stamp-tool,$@,CFLAGS) -I$(call ext-stamp-absprefix,$@)/include" \
+ LD="$(call ext-stamp-tool,$@,LD)" \
+ LDFLAGS="$(call ext-stamp-tool,$@,LDFLAGS) -L$(call ext-stamp-absprefix,$@)/lib" \
+ PKG_CONFIG="pkg-config --static" \
+ PKG_CONFIG_LIBDIR=$(call ext-stamp-absprefix,$@)/lib/pkgconfig
+ $(call ext-stamp-tool,$@,ENV) \
+ $(MAKE) -C$(call ext-stamp-builddir,$@)
+ $(call ext-stamp-tool,$@,ENV) \
+ $(MAKE) -C$(call ext-stamp-builddir,$@) install
+ $(V_AT)touch $@
+
+$(foreach f,$(FLAVOURS),$(foreach e,$(EXTERNALS),clean-$e.$f)): clean-%:
+ rm -f $(STAMPDIR)/$*-stamp
+ rm -rf $(call ext-stamp-builddir,$*)
+.PHONY: $(foreach f,$(FLAVOURS),$(foreach e,$(EXTERNALS),clean-$e.$f))
+$(foreach e,$(EXTERNALS),clean-$e): clean-%: $(foreach f,$(FLAVOURS),clean-%.$f)
+$(foreach f,$(FLAVOURS),clean-inst.$f): clean-inst.%:
+ rm -rf $(call ext-prefix,$*)
+.PHONY: $(foreach f,$(FLAVOURS),clean-inst.$f)
+
+$(foreach f,$(FLAVOURS),realclean-$f): realclean-%: \
+ $$(foreach e,$$(EXTERNALS),clean-$$e.$$*) \
+ clean-inst.$$*
+realclean:: $(foreach f,$(FLAVOURS),realclean-$f)
###--------------------------------------------------------------------------
-### 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)
+### 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) \
+ -ladns
+
+## 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-$(hostcpu) = $(OUTDIR)/lib.host-$(hostcpu)
+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
+CLEANFILES += $(OUTDIR)/lib.host-$(hostcpu)/lib*.so
-## Compiling Scala code.
-CLSEXT += scala
-$(OUTDIR)%.stamp: %.scala
- $(call v_tag,SCALAC)mkdir -p $(CLASSDIR) && \
- $(SCALAC) -d $(CLASSDIR) -cp $(CLASSDIR) $(SCALAFLAGS) $< && \
- echo built >$@
+###--------------------------------------------------------------------------
+### Android string resource generation.
+
+GENSTRINGS += package=PACKAGE
+GENSTRINGS += version=VERSION
+GENSTRINGS += vsn=VSN
+
+$(foreach e,$(EXTERNALS),\
+ $(eval GENSTRINGS += $e_version=$e_VERSION))
+
+BUILD := $(shell uuid -v4)
+GENSTRINGS += build_uuid=BUILD
+
+genstring-name = $(firstword $(subst =, ,$1))
+genstring-value = $($(word 2,$(subst =, ,$1)))
+
+define gen-strings
+ $(V_AT)mkdir -p $(dir $1)
+ $(call v_tag,GEN)set -e; rm -f $1.new; exec >$1.new; \
+ echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; \
+ echo "<resources>"; \
+ $(foreach g,$(GENSTRINGS), \
+ echo " <string name=\"auto_$(call genstring-name,$g)\">$(call genstring-value,$g)</string>";) \
+ echo "</resources>"
+ $(V_AT)mv $1.new $1
+endef
+$(OUTDIR)/res.dummy/values/auto.xml: Makefile
+ $(call gen-strings,$@)
###--------------------------------------------------------------------------
-### Native-code libraries.
+### Java and Scala building.
-SHLIBS += toy
-toy_SOURCES = jni.c
+JARDIR = $(OUTDIR)/jar
+CLASSDIR = $(OUTDIR)/cls
-shlibfile = $(patsubst %,$(OUTDIR)lib%.so,$1)
-SHLIBFILES = $(call shlibfile,$(SHLIBS))
-TARGETS += $(SHLIBFILES)
-ALL_SOURCES += $(foreach l,$(SHLIBS),$($l_SOURCES))
+## External libraries we need to adopt. Grab them and feed them to `dx'
+## separately, because they take aaaaages and we don't want to have to do
+## this on every incremental build.
+JARS = $(SCALA_LIB)
-$(SHLIBFILES): $(OUTDIR)lib%.so: $$(call objects,$$($$*_SOURCES),.o)
- $(call v_tag,LD)$(LD) $(LDFLAGS.so) -o$@ $^ $(LIBS)
+DEXJARS =
+define jar-rule
+DEXJARS += $$(JARDIR)/$$(notdir $1)
+$$(JARDIR)/$$(notdir $1): $1
+ $$(V_AT)mkdir -p $$(JARDIR)/
+ $$(V_AT)rm -f $$@ $$(basename $$@)-new.jar
+ $$(call v_tag,DX)dx --dex --output=$$(basename $$@)-new.jar $1
+ $$(V_AT)mv $$(basename $$@)-new.jar $$@
+endef
+$(foreach j,$(JARS), $(eval $(call jar-rule,$j)))
-###--------------------------------------------------------------------------
-### Java classes.
+REALCLEANFILES += $(JARDIR)/*.jar
## Writing things out longhand is tedious. `CLASSES' is a list of entries of
## the form `SRC[:DEP,...]', saying that `SRC.ext', being a source file
-## capable of being built into `.class' files and setting `SRC.stamp', should
-## be so built, and that it depends on other similar sources named DEP having
-## been so built.
+## capable of being built into `.class' files and setting `SRC.class-stamp',
+## should be so built, and that it depends on other similar sources named DEP
+## having been so built.
CLASSES += util
CLASSES += sys:util
CLASSES += admin:sys,util
CLASSES += tar:util
+CLASSES += dep:util
CLASSES += progress:sys,util
CLASSES += keys:progress,tar,sys,util
CLASSES += terminal:progress,sys,util
-CLASSES += main:sys
+CLASSES += R
+CLASSES += app:R
+CLASSES += toy-activity:app,R
+
+## Building class files.
+$(STAMPDIR)/%.class-stamp: %.java
+ $(V_AT)mkdir -p $(CLASSDIR)/
+ $(call v_tag,JAVAC)$(JAVAC) $(JAVAFLAGS) \
+ -bootclasspath $(ANDROID_JAR) \
+ -d $(CLASSDIR) -cp $(CLASSDIR) \
+ $<
+ $(V_AT)$(SCALAC_RESET)
+ $(V_AT)touch $@
+$(STAMPDIR)/%.class-stamp: %.scala
+ $(V_AT)mkdir -p $(CLASSDIR)/
+ $(call v_tag,SCALAC)$(SCALAC) $(SCALAFLAGS) \
+ -javabootclasspath $(ANDROID_JAR) \
+ -bootclasspath $(SCALA_LIB) \
+ -d $(CLASSDIR) -cp $(CLASSDIR) \
+ $<
+ $(V_AT)touch $@
## Machinery for parsing the `CLASSES' list.
-COMMA = ,
class-name = $(firstword $(subst :, ,$1))
-class-deps = $(subst $(COMMA), ,$(word 2,$(subst :, ,$1)))
+class-deps = $(subst $(comma), ,$(word 2,$(subst :, ,$1)))
-CLASS_NAMES = $(foreach c,$(CLASSES),$(call class-name,$c))
+CLASSNAMES = $(foreach c,$(CLASSES),$(call class-name,$c))
+CLASSSTAMPS = $(call stamps,class,$(CLASSNAMES))
-all:: $(call stamps,$(CLASS_NAMES))
+$(foreach c,$(CLASSES), \
+$(eval $(call stamps,class,$(call class-name,$c)): \
+ $(call stamps,class,$(call class-deps,$c))))
-$(foreach c,$(CLASSES),$(eval $(call stamps,$(call class-name,$c)): \
- $(call stamps,$(call class-deps,$c))))
-
-DISTFILES += $(foreach c,$(CLASSES),\
- $(foreach e,$(CLSEXT),\
- $(wildcard $(call class-name,$c).$e)))
+CLEANFILES += $(CLASSSTAMPS)
+clean::; rm -rf $(OUTDIR)/cls
###--------------------------------------------------------------------------
-### Distribution arrangements.
-
-DISTFILES += COPYING
-DISTFILES += Makefile
-DISTFILES += auto-version
-
-distdir = $(PACKAGE)-$(VERSION)
-DISTTAR = $(distdir).tar.gz
-
-distdir:
- rm -rf $(OUTDIR)$(distdir)
- mkdir $(OUTDIR)$(distdir)
- echo $(VERSION) >$(OUTDIR)$(distdir)/RELEASE
- set -e; for i in $(DISTFILES); do \
- case $$i in */*) mkdir -p $(OUTDIR)$(distdir)/$${i%/*} ;; esac; \
- cp $$i $(OUTDIR)$(distdir)/; \
- done
-.PHONY: distdir
-
-dist: distdir
- set -e; cd $(OUTDIR); tar chozf ../$(DISTTAR) $(distdir)
- rm -rf $(distdir)
-.PHONY: dist
+### Android building machinery.
+
+VPATH += $(OUTDIR)/src
+CLEANFILES += $(OUTDIR)/*.apk
+
+AAPTFLAGS = \
+ --min-sdk-version $(MINAPI) --target-sdk-version $(TARGETAPI) \
+ --version-name "$(VERSION)" --version-code $(VSN) --auto-add-overlay
+
+$(OUTDIR)/src/R.java: AndroidManifest.xml $(OUTDIR)/res.dummy/values/auto.xml
+ $(V_AT)mkdir -p $(dir $@)
+ $(call v_tag,AAPT)aapt package $(AAPTFLAGS) \
+ -M AndroidManifest.xml -S res/ -S $(OUTDIR)/res.dummy/ \
+ -I $(ANDROID_JAR) \
+ -J $(dir $@) --generate-dependencies
+CLEANFILES += $(OUTDIR)/src/R.java $(OUTDIR)/src/R.java.d
+-include $(OUTDIR)/src/R.java.d
+
+BINS = catsign key pathmtu
+CLEANFILES += $(INSTFILES)
+define bin-rule
+INSTFILES += $$(OUTDIR)/pkg/assets/bin/$1/$2
+$$(OUTDIR)/pkg/assets/bin/$1/$2: $$$$(call ext-stamps,$$$$(EXTERNALS),$1)
+ $$(V_AT)mkdir -p $$(dir $$@)
+ $$(call v_tag,CP)cp $$(call ext-prefix,$1)/bin/$2 $$@
+endef
+$(foreach f,$(ANDROID_ABIS), \
+$(foreach b,$(BINS), \
+ $(eval $(call bin-rule,$f,$b))))
+
+DISTCLEANFILES += debug.keystore
+debug.keystore:
+ $(call v_tag,KEYTOOL)keytool -genkeypair -alias debug \
+ -keyalg RSA -keysize 3072 \
+ -dname "$(DEBUGDN)" -validity 10000 \
+ -keystore $@ -storetype PKCS12 \
+ -storepass public -keypass public
+
+INSTFILES += $(OUTDIR)/pkg/classes.dex
+$(OUTDIR)/pkg/classes.dex: $(CLASSSTAMPS) $(DEXJARS)
+ $(V_AT)mkdir -p $(dir $@)
+ $(call v_tag,DX)dx --dex --output=$@ $(CLASSDIR) $(JARDIR)
+
+$(OUTDIR)/res.volatile/values/auto.xml: $(INSTFILES)
+ $(call gen-strings,$@)
+
+$(foreach v,$(VARIANTS),$(OUTDIR)/tripe-$v.unsigned.apk): \
+$(OUTDIR)/tripe-%.unsigned.apk: $(INSTFILES) $(OUTDIR)/res.volatile/values/auto.xml
+ $(call v_tag,AAPT)aapt package -f $(AAPTFLAGS) $(AAPTFLAGS.$*) \
+ -M AndroidManifest.xml -S res/ -S $(OUTDIR)/res.volatile/ \
+ -I $(ANDROID_JAR) -F $@ $(OUTDIR)/pkg/
+
+$(foreach v,$(VARIANTS),$(OUTDIR)/tripe-$v.signed.apk): \
+$(OUTDIR)/tripe-%.signed.apk: $(OUTDIR)/tripe-%.unsigned.apk $$(KEYSTORE.$$*)
+ $(call v_tag,JARSIGN)jarsigner -keystore $(KEYSTORE.$*) \
+ $(JARSIGNERFLAGS.$*) \
+ -signedjar $@ $< $(call defaulting,KEYALIAS.$*,$*)
+
+$(foreach v,$(VARIANTS),$(OUTDIR)/tripe-$v.apk): \
+$(OUTDIR)/tripe-%.apk: $(OUTDIR)/tripe-%.signed.apk
+ $(call v_tag,ZIPALGN)zipalign $(ZIPALIGNFLAGS.$*) -f 4 $< $@
+
+$(VARIANTS): %: $(OUTDIR)/tripe-%.apk
+.PHONY: $(VARIANTS)
###--------------------------------------------------------------------------
### Finishing touches.
-all:: $(TARGETS)
+all:: debug
+
+clean::; rm -f $(CLEANFILES)
+realclean::; rm -f $(REALCLEANFILES)
-clean::; rm -f $(CLEANFILES) $(TARGETS)
+repl: $(CLASSSTAMPS) $(foreach a,$(APKLIBS),$(JNIDIR.host-$(hostcpu))/$a)
+ $(SCALA) -cp $(CLASSDIR) -Yno-load-impl-class \
+ -Djava.library.path=$(JNIDIR.host-$(hostcpu)) \
-repl: all
- $(SCALA_REPL) -cp $(CLASSDIR) -Djava.library.path=$(OUTDIR)
-.PHONY: repl
+t:; : $(show)
+.PHONY: t
--include $(call objects,$(ALL_SOURCES),.d)
+-include $(DEPFILES)
###----- That's all, folks --------------------------------------------------