### -*-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.
## Where to put the object files.
OUTDIR = out/
## Native C compiler.
CC = gcc
CFLAGS = -O2 -g -Wall -pedantic -Werror
## Native linker.
LD = gcc
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.
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)) \
$(PKGS_CFLAGS)
LIBS = $(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)%.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 >$@
###--------------------------------------------------------------------------
### Native-code libraries.
SHLIBS += toy
toy_SOURCES = jni.c
shlibfile = $(patsubst %,$(OUTDIR)lib%.so,$1)
SHLIBFILES = $(call shlibfile,$(SHLIBS))
TARGETS += $(SHLIBFILES)
ALL_SOURCES += $(foreach l,$(SHLIBS),$($l_SOURCES))
$(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
CLASSES += main:sys
## 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_NAMES))
$(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)))
###--------------------------------------------------------------------------
### 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 --------------------------------------------------