### -*-makefile-*- ### ### Build script for the TrIPE Android app ### ### (c) 2018 Straylight/Edgeware ### ###----- Licensing notice --------------------------------------------------- ### ### This file is part of the Trivial IP Encryption (TrIPE) Android app. ### ### TrIPE is free software: you can redistribute it and/or modify it under ### the terms of the GNU General Public License as published by the Free ### Software Foundation; either version 3 of the License, or (at your ### option) any later version. ### ### TrIPE is distributed in the hope that it will be useful, but WITHOUT ### ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ### FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ### for more details. ### ### You should have received a copy of the GNU General Public License ### along with TrIPE. If not, see . PACKAGE = tripe-android VERSION := $(shell ./auto-version) VSN = 1 .SECONDEXPANSION: #sorry ###-------------------------------------------------------------------------- ### Preliminary magic. empty = space = $(empty) $(empty) comma = , definedp = $(filter-out undefined,$(origin $1)) defaulting = $(if $(call definedp,$1),$($1),$2) all:: ###-------------------------------------------------------------------------- ### Build parameters. abs_srcdir := $(abspath .) hostos := $(shell uname -s | tr A-Z a-z) hostcpu := $(shell uname -m | tr A-Z a-z) ## 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 $(call definedp,TMPDIR),t,nil) ifeq ($(explicit-tmpdir-p), t) JAVADEFS += -Djava.io.tmpdir=$(TMPDIR) endif ## Java compiler. JAVAC = javac $(addprefix -J,$(JAVADEFS)) JAVAFLAGS = -source 1.6 -target 1.6 ## Scala compiler. ## ## Unfortunately, `fsc' is a total security disaster. On the other hand, ## `scalac' is rather slow. If we're running with a custom `TMPDIR', and the ## `noip' wrapper is ## available, then we can tame `fsc' enough that it's probably safe to run; ## otherwise, it's too risky to enable by default. noip-available-p := $(shell noip echo t 2>/dev/null || echo nil) ifeq ($(noip-available-p), t) NOIP = noip endif ifeq "$(explicit-tmpdir-p),$(noip-available-p)" "t,t" 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 -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 ## Allow local overrides at this point. -include local.mk ###-------------------------------------------------------------------------- ### Silent-rules machinery. v_tag = $(call v_tag_$V,$1) v_tag_0 = @printf " %-8s %s\n" "$1" "$@"; V_AT = $(V_AT_$V) V_AT_0 = @ ###-------------------------------------------------------------------------- ### Other handy functions. join-paths = $(if $(filter /%,$2),$2,$1/$2) ## 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 clean:: .PHONY: clean realclean:: clean .PHONY: realclean distclean:: realclean .PHONY: distclean ###-------------------------------------------------------------------------- ### External native packages. ## 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) ###-------------------------------------------------------------------------- ### 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 ###-------------------------------------------------------------------------- ### 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 ""; \ echo ""; \ $(foreach g,$(GENSTRINGS), \ echo " $(call genstring-value,$g)";) \ echo "" $(V_AT)mv $1.new $1 endef $(OUTDIR)/res.dummy/values/auto.xml: Makefile $(call gen-strings,$@) ###-------------------------------------------------------------------------- ### Java and Scala building. JARDIR = $(OUTDIR)/jar CLASSDIR = $(OUTDIR)/cls ## 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) 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))) 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.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 += 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. class-name = $(firstword $(subst :, ,$1)) class-deps = $(subst $(comma), ,$(word 2,$(subst :, ,$1))) CLASSNAMES = $(foreach c,$(CLASSES),$(call class-name,$c)) CLASSSTAMPS = $(call stamps,class,$(CLASSNAMES)) $(foreach c,$(CLASSES), \ $(eval $(call stamps,class,$(call class-name,$c)): \ $(call stamps,class,$(call class-deps,$c)))) CLEANFILES += $(CLASSSTAMPS) clean::; rm -rf $(OUTDIR)/cls ###-------------------------------------------------------------------------- ### 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:: debug clean::; rm -f $(CLEANFILES) realclean::; rm -f $(REALCLEANFILES) repl: $(CLASSSTAMPS) $(foreach a,$(APKLIBS),$(JNIDIR.host-$(hostcpu))/$a) $(SCALA) -cp $(CLASSDIR) -Yno-load-impl-class \ -Djava.library.path=$(JNIDIR.host-$(hostcpu)) \ t:; : $(show) .PHONY: t -include $(DEPFILES) ###----- That's all, folks --------------------------------------------------