### -*-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)
.SECONDEXPANSION: #sorry
###--------------------------------------------------------------------------
### Build parameters.
abs_builddir := $(shell pwd)
## Where to put the object files.
OUTDIR = out
## Native C compiler.
CC = gcc
CFLAGS = -O2 -g -Wall -pedantic -Werror
## Native linker.
LD = gcc -Wl,-z,defs
LDFLAGS.so = -shared
## External `pkg-config' packages required.
PKGS = mLib catacomb
## Java development kit.
JDKDIR = /usr/lib/jvm/default-java
JDK_PLAT = linux
JNI_INCLUDES = $(JDKDIR)/include $(JDKDIR)/include/$(JDK_PLAT)
## Default arguments for the Java runtime.
JAVADEFS =
## 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)
ifeq ($(explicit-tmpdir-p), t)
JAVADEFS += -Djava.io.tmpdir=$(TMPDIR)
endif
## Java compiler.
JAVAC = javac $(JAVADEFS)
JAVAFLAGS =
## 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)
SCALAC_RESET = $(SCALAC) -reset
else
SCALAC = scalac $(JAVADEFS)
SCALAC_RESET =
endif
SCALAFLAGS = -optimise -feature -deprecation -Xfatal-warnings \
-Xlint -Xlint:-package-object-classes \
-Yinline-warnings:false
SCALA_REPL = $(NOIP) scala $(JAVADEFS)
## 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 = @
###--------------------------------------------------------------------------
### External native packages.
EXTPREFIX = $(abs_builddir)/$(OUTDIR)/inst
join-paths = $(if $(filter /%,$2),$2,$1/$2)
ext-srcdir = $(or $($1_SRCDIR),../$1)
PKG_CONFIG = PKG_CONFIG_LIBDIR=$(OUTDIR)/inst/lib/pkgconfig \
pkg-config --static
PKGS_CFLAGS := $(foreach p,$(PKGS),$(shell $(PKG_CONFIG) --cflags $p))
PKGS_LIBS := $(foreach p,$(PKGS),$(shell $(PKG_CONFIG) --libs $p))
ALL_CFLAGS = $(CFLAGS) -fPIC \
$(addprefix -I,$(JNI_INCLUDES)) \
-I$(OUTDIR)/inst/include \
-I$(call ext-srcdir,tripe)/common \
-I$(call ext-srcdir,tripe)/priv \
-I$(call ext-srcdir,tripe)/server \
-I$(OUTDIR)/build/tripe/config \
$(PKGS_CFLAGS)
LIBS = $(OUTDIR)/build/tripe/server/libtripe.a \
$(OUTDIR)/build/tripe/priv/libpriv.a \
$(OUTDIR)/build/tripe/common/libcommon.a \
-L$(OUTDIR)/inst/lib $(PKGS_LIBS)
###--------------------------------------------------------------------------
### Various other tweaks and overrides.
## Hack around https://issues.scala-lang.org/browse/SI-9689
SCALAFLAGS += -Yno-load-impl-class
###--------------------------------------------------------------------------
### And now we can start building things.
all::
.PHONY: all
CLEANFILES =
clean::
.PHONY: clean
###--------------------------------------------------------------------------
### Native C code.
out/%.o: %.c
$(call v_tag,CC)mkdir -p $(OUTDIR)/ && \
$(CC) -c $(ALL_CFLAGS) -MMD -o$@ $<
ALL_SOURCES =
DISTFILES += $(ALL_SOURCES)
objects = $(patsubst %.c,$(OUTDIR)/%$2,$1)
CLEANFILES += $(OUTDIR)/*.o $(OUTDIR)/*.d
###--------------------------------------------------------------------------
### 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)/%.$1-stamp,$2)
clean::; rm -rf $(CLASSDIR)
CLEANFILES += $(OUTDIR)/*.class-stamp
## Compiling actual Java code. Note that this confuses the resident Scala
## compiler, so we have to reset it here.
CLSISH += java
$(OUTDIR)/%.class-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)/%.class-stamp: %.scala
$(call v_tag,SCALAC)mkdir -p $(CLASSDIR)/ && \
$(SCALAC) -d $(CLASSDIR) -cp $(CLASSDIR) $(SCALAFLAGS) $< && \
echo built >$@
###--------------------------------------------------------------------------
### Native-code libraries.
SHLIBS += tripe
tripe_SOURCES = jni.c
shlibfile = $(patsubst %,$(OUTDIR)/lib%.so,$1)
SHLIBFILES = $(call shlibfile,$(SHLIBS))
TARGETS += $(SHLIBFILES)
ALL_SOURCES += $(foreach l,$(SHLIBS),$($l_SOURCES))
$(call objects,$(tripe_SOURCES),.o): $(call stamps,ext,tripe)
$(SHLIBFILES): $(OUTDIR)/lib%.so: $$(call objects,$$($$*_SOURCES),.o)
$(call v_tag,LD)$(LD) $(LDFLAGS.so) -o$@ $^ $(LIBS)
###--------------------------------------------------------------------------
### Java classes.
## 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.
CLASSES += util
CLASSES += sys:util
CLASSES += admin:sys,util
CLASSES += tar:util
CLASSES += progress:sys,util
CLASSES += keys:progress,tar,sys,util
CLASSES += terminal:progress,sys,util
## Machinery for parsing the `CLASSES' list.
COMMA = ,
class-name = $(firstword $(subst :, ,$1))
class-deps = $(subst $(COMMA), ,$(word 2,$(subst :, ,$1)))
CLASS_NAMES = $(foreach c,$(CLASSES),$(call class-name,$c))
all:: $(call stamps,class,$(CLASS_NAMES))
$(foreach c,$(CLASSES),$(eval $(call stamps,class,$(call class-name,$c)): \
$(call stamps,class,$(call class-deps,$c))))
DISTFILES += $(foreach c,$(CLASSES),\
$(foreach e,$(CLSEXT),\
$(wildcard $(call class-name,$c).$e)))
###--------------------------------------------------------------------------
### External packages.
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
all:: $(call stamps,ext,$(EXTERNALS))
CLEANFILES += $(OUTDIR)/*.ext-stamp
clean::; rm -rf $(OUTDIR)/inst $(OUTDIR)/build
$(call stamps,ext,$(EXTERNALS)): \
$(OUTDIR)/%.ext-stamp: $$(call stamps,ext,$$($$*_DEPS))
$(V_AT)rm -rf $(OUTDIR)/build/$*/
$(V_AT)mkdir -p $(OUTDIR)/build/$*/
cd $(OUTDIR)/build/$*/ && \
$(call join-paths,../../..,$(call ext-srcdir,$*))/configure \
--prefix=$(EXTPREFIX) \
$($*_CONFIG) \
CFLAGS="-O2 -g -fPIC -Wall -I$(EXTPREFIX)/include" \
LDFLAGS="-L$(EXTPREFIX)/lib" \
PKG_CONFIG="pkg-config --static" \
PKG_CONFIG_LIBDIR=$(EXTPREFIX)/lib/pkgconfig
$(MAKE) -C$(OUTDIR)/build/$*/
$(MAKE) -C$(OUTDIR)/build/$*/ -s install
$(V_AT)echo done >$@
###--------------------------------------------------------------------------
### 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
###--------------------------------------------------------------------------
### Finishing touches.
all:: $(TARGETS)
clean::; rm -f $(CLEANFILES) $(TARGETS)
repl: all
$(SCALA_REPL) -cp $(CLASSDIR) -Djava.library.path=$(OUTDIR)
.PHONY: repl
-include $(call objects,$(ALL_SOURCES),.d)
###----- That's all, folks --------------------------------------------------