chiark / gitweb /
Overhaul the build machinery.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 9 Jun 2018 11:08:30 +0000 (12:08 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 9 Jun 2018 13:00:09 +0000 (14:00 +0100)
.gitignore
.links [new file with mode: 0644]
Makefile

index b82f8dc..cdb06a1 100644 (file)
@@ -4,3 +4,5 @@
 *.so
 *.stamp
 /out/
+/COPYING
+/auto-version
diff --git a/.links b/.links
new file mode 100644 (file)
index 0000000..6c542fe
--- /dev/null
+++ b/.links
@@ -0,0 +1,2 @@
+COPYING=GPL-3
+auto-version
index d99d6bd..1e74713 100644 (file)
--- a/Makefile
+++ b/Makefile
 ### -*-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 <https://www.gnu.org/licenses/>.
+
+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 <https://git.distorted.org.uk/~mdw/preload-hacks/> 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 -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                  = @
 
-JDK                     = /usr/lib/jvm/default-java
-JDK_PLAT                = linux
-INCLUDES                = $(JDK)/include $(JDK)/include/$(JDK_PLAT)
+###--------------------------------------------------------------------------
+### External native packages.
 
-PKGS                    = mLib catacomb
 PKGS_CFLAGS            := $(foreach p,$(PKGS),$(shell pkg-config --cflags $p))
 PKGS_LIBS              := $(foreach p,$(PKGS),$(shell pkg-config --libs $p))
 
-CC                      = gcc
-CFLAGS                  = -O2 -g -Wall -pedantic -Werror \
-                               -fPIC $(addprefix -I,$(INCLUDES))
-CFLAGS                 += $(PKGS_CFLAGS)
+ALL_CFLAGS              = $(CFLAGS) -fPIC \
+                               $(addprefix -I,$(JNI_INCLUDES)) \
+                               $(PKGS_CFLAGS)
 
-LD                      = gcc
 LIBS                    = $(PKGS_LIBS)
-LDFLAGS.so              = -shared
 
-JAVAC                   = javac
-JAVAFLAGS               =
-
-SCALAC                  = fsc
-SCALAFLAGS              = -optimise -Xlint -Xlint:-package-object-classes \
-                               -Yinline-warnings:false
+###--------------------------------------------------------------------------
+### 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
 
-OUTDIR                  = out/
+CLEANFILES              =
+clean::
+.PHONY: clean
+
+###--------------------------------------------------------------------------
+### Native C code.
 
 out/%.o: %.c
-       $(call v_tag,CC)mkdir -p $(OUTDIR) && $(CC) -c $(CFLAGS) -MMD -o$@ $<
+       $(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
 
-stamp                   = $(patsubst %,$(OUTDIR)%.stamp,$1)
+###--------------------------------------------------------------------------
+### 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
+       $(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 >$@
-CLEANFILES             += $(OUTDIR)*.stamp
-clean::; rm -rf $(CLASSDIR)
 
-objects                         = $(patsubst %.c,$(OUTDIR)%$2,$1)
+###--------------------------------------------------------------------------
+### Native-code libraries.
+
+SHLIBS                 += toy
+toy_SOURCES             = jni.c
 
-TARGETS += $(OUTDIR)libtoy.so
-libtoy.so_SOURCES       = jni.c
-$(OUTDIR)libtoy.so: $(call objects,$(libtoy.so_SOURCES),.o)
+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
-sys_DEPS                = util
-CLASSES                        += admin
-admin_DEPS              = sys util
-CLASSES                        += tar
-tar_DEPS                = util
-CLASSES                        += keys
-keys_DEPS               = tar sys util
-CLASSES                        += main
-main_DEPS               = sys
-
-$(foreach c,$(CLASSES),$(eval $(call stamp,$c): $(call stamp,$($c_DEPS))))
-TARGETS                        += $(call stamp,$(CLASSES))
+CLASSES                        += sys:util
+CLASSES                        += admin:sys,util
+CLASSES                        += tar:util
+CLASSES                        += keys:tar,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)
-ALLSOURCES             += $(foreach t,$(TARGETS),$($t_SOURCES))
+
+clean::; rm -f $(CLEANFILES) $(TARGETS)
 
 repl: $(TARGETS)
-       scala -cp $(CLASSDIR) -Djava.library.path=$(OUTDIR)
+       $(SCALA_REPL) -cp $(CLASSDIR) -Djava.library.path=$(OUTDIR)
+.PHONY: repl
 
-clean::; rm -f $(CLEANFILES) $(TARGETS)
-.PHONY: clean
+-include $(call objects,$(ALL_SOURCES),.d)
 
--include $(call objects,$(ALLSOURCES),.d)
+###----- That's all, folks --------------------------------------------------