# Makefile for Unix Inform 6 Compiler package
# Stable branch
#
#   Inform 6.42
#   Inform 6 Standard Library 6.12.7
#   PunyInform Library 5.5.2
#
# GNU make is required.

# Your C compiler
#CC ?= gcc
#CC ?= clang

#OPTS = -g -Wall -Wextra

PREFIX ?= /usr/local
MAN_PREFIX ?= $(PREFIX)
REAL_PREFIX ?= $(PREFIX)

COMPVERSION = 6.42
PKGVERSION = r4
NAME = inform
LANGUAGE = english
BINNAME = $(NAME)-$(COMPVERSION)
DISTNAME = $(NAME)-$(COMPVERSION)-$(PKGVERSION)
UNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
UNAME_O := $(shell uname -o)

GIT = git
GIT_DIR ?= .git

BINPERM  = 755
DIRPERM  = 755
FILEPERM = 644

ifeq ($(UNAME_O),Android)
LDFLAGS += -lm
endif

###############################################
# Here are where Inform's pieces are installed.
BINDIR         = $(PREFIX)/bin
SHAREDIR       = $(PREFIX)/share/$(NAME)


##########################
# For the Standard Library
STDSRC         = std
STD            = $(SHAREDIR)/$(STDSRC)
STDLIB         = $(STD)/lib
STDLIB_LINKS   = English.h Grammar.h Parser.h Verblib.h VerbLib.h
STDINC         = $(STD)/include
STDDEMO        = $(STD)/demos
STDTUTOR       = $(STD)/tutor

STDLIB_SRC     = $(STDSRC)
STDINC_SRC     = std-include
STDDEMOS_SRC   = std-demos
STDTUTOR_SRC   = std-tutor

STDDEMOS_INF   = $(wildcard ${STDDEMOS_SRC}/*.inf)
STDDEMOS_Z5    = $(patsubst %.inf,%.z5,${STDDEMOS_INF})
STDTUTOR_INF   = $(wildcard ${STDTUTOR_SRC}/*.inf)
STDTUTOR_Z5    = $(patsubst %.inf,%.z5,${STDTUTOR_INF})


############################
# For the PunyInform Library
PUNYSRC         = punyinform
PUNY            = $(SHAREDIR)/$(PUNYSRC)
PUNYLIB         = $(PUNY)/lib
PUNYINCLUDE     = $(PUNY)/include
PUNYHOWTO       = $(PUNY)/howto
PUNYTESTS       = $(PUNY)/tests
PUNYDOCS        = $(PUNY)/documentation

PUNYDOCS1       = $(PUNYDOCS)/guides
PUNYDOCS2       = $(PUNYDOCS)/screenshots
PUNYDOCS3       = $(PUNYDOCS)/technical

PUNYDOCS_SRC     = $(PUNYSRC)/documentation
PUNYDOCS_DIR1    = $(PUNYDOCS_SRC)/guides
PUNYDOCS_DIR2    = $(PUNYDOCS_SRC)/screenshots
PUNYDOCS_DIR3    = $(PUNYDOCS_SRC)/technical

PUNYLIB_SRC      = $(PUNYSRC)/lib
PUNYINC_SRC      = $(PUNYSRC)/include
PUNYHOWTO_SRC    = $(PUNYSRC)/howto
PUNYTESTS_SRC    = $(PUNYSRC)/tests

PUNYHOWTO_INF    = $(wildcard ${PUNYHOWTO_SRC}/*.inf)
PUNYHOWTO_Z3     = $(patsubst %.inf,%.z3,${PUNYHOWTO_INF})

PUNYTESTS_INF    = $(wildcard ${PUNYTESTS_SRC}/*.inf)
PUNYTESTS_Z3     = $(patsubst %.inf,%.z3,${PUNYTESTS_INF})

PUNYINFORM       = punyinform
PUNYINFORMSH     = punyinform.sh
PUNYMISC_FILES   = LICENSE README.md releasenotes.txt


#######################################################
# For the Compiler
# The default include path is for the Standard Library.
# The PunyInform Library sets its own path.
INCLUDEPATH   = ",$(STDLIB),$(STDINC)"

DEFINES= -DDefault_Language=\"$(LANGUAGE)\" \
	-DInclude_Directory=\"$(INCLUDEPATH)\" \
	-DTemporary_Directory=\"$(TEMPDIR)\"

ifeq ($(UNAME_S),darwin)
DEFINES += -DMACOS
else ifeq ($(UNAME_O),Android)
DEFINES += -DUNIX
else ifeq ($(UNAME_S),linux)
DEFINES += -DLINUX
else
DEFINES += -DUNIX
endif

COMPSRC = src
SOURCES = $(wildcard ${COMPSRC}/*.c)
OBJECTS = $(patsubst %.c,%.o,${SOURCES})

MANPAGE       = $(NAME).1
MANDIR        = $(PREFIX)/man/man1
TEMPDIR       = /tmp

.PHONY: all clean distcheck distclean modclean stdlib punylib

all:	$(BINNAME) stddemos stdtutor punyhowto punytests
install: install-compiler install-manual install-contrib install-stdlib-all install-puny


#############################################################
# Submodules must be downloaded before anything else happens.
check-submodules:
ifeq ($(and $(wildcard $(COMPSRC)/*),$(wildcard $(STDSRC)/*),$(wildcard $(PUNYSRC))),)
	$(warning One or more submodules are missing.)
	$(error Please do "$(MAKE) submodules" and try again)
endif


#############################################################
# Check to see if .git/ exists.  If not, stop.
# This stops the builder from doing anything involving git.
distcheck:
ifeq ($(wildcard $(GIT_DIR)),)
	$(warning *** This is a release archive.)
	$(error There is no need to do what you just did)
endif


submodule: submodules
submodules: distcheck
ifneq ($(and $(wildcard $(GIT_DIR)),$(shell which $(GIT))),)
	rm -rf $(COMPSRC) $(STDSRC) $(PUNYSRC)
	@$(GIT) submodule init
	@$(GIT) submodule update
	@$(GIT) submodule update
	@echo " *** Submodules downloaded."
else
	$(warning *** Not in a git repository or git command missing.)
	$(warning *** Don't download this package directly from Gitlab.)
	$(warning *** You need to clone it from Gitlab or download an archive)
	$(warning *** from the Interactive Fiction Archive.)
	$(warning ***)
	$(warning *** If you cloned this package or got an archive from the)
	$(warning *** Interactive Fiction Archive and got this message,)
	$(warning *** you might have deleted something you shouldn't.)
	$(warning *** submodule directories.)
	$(error Read README.md for more information)
endif


########################################################
# Rules for building and installing the Inform6 Compiler
%.o: %.c
	$(CC) $(DEFINES) $(OPTS) -o $@ -c $<

$(BINNAME): $(OBJECTS)
	$(CC) -o $(BINNAME) $(LDFLAGS) $(OBJECTS)
	@echo "** Done building compiler."

strip:	$(BINNAME)
	strip $(BINNAME)

install-compiler: $(BINNAME)
ifeq ($(wildcard $(DESTDIR)$(BINDIR)/$(BINNAME)),)
	install -d -m $(DIRPERM) $(DESTDIR)$(BINDIR)
	install -c -m $(BINPERM) $(BINNAME) $(DESTDIR)$(BINDIR)
	cd $(DESTDIR)$(BINDIR) ; ln -sf $(BINNAME) $(NAME)
	@echo "** Done installing compiler."
else
	$(warning *** It looks like Inform $(COMPVERSION) is already installed.)
	$(warning *** If you want to reinstall, do "$(MAKE) uninstall" as root first.)
	$(warning *** If you want to add this version of the compiler as an)
	$(warning *** an alternative, do "$(MAKE) install-alt" as root instead.)
	$(warning *** If neither of these make sense, manually delete)
	$(error $(DESTDIR)$(BINDIR)/$(BINNAME) and try again)
endif

install-alt:	$(BINNAME)
ifeq ($(wildcard $(DESTDIR)$(BINDIR)/$(BINNAME)),)
	install -d -m $(DIRPERM) $(DESTDIR)$(BINDIR)
	install -c -m $(BINPERM) $(BINNAME) $(DESTDIR)$(BINDIR)
	cd $(DESTDIR)$(BINDIR) ; ln -sf $(PUNYINFORMSH) $(PUNYINFORM)-$(COMPVERSION)
	@echo "** Done installing alternate compiler."
else
	$(warning *** It looks like Version $(COMPVERSION) of the Inform compiler)
	$(warning *** is already installed.)
	$(error Cannot install $(COMPVERSION) as an alternative)
endif


#########################################################
# Rules for building and installing the Standard Library
%.z5: %.inf | $(BINNAME)
	$(PWD)/$(BINNAME) +$(STDSRC) $< $@

stddemos:	$(BINNAME) $(STDDEMOS_Z5)
	@echo "** Done building Standard Library demos."

stdtutor:	$(BINNAME) $(STDTUTOR_Z5)
	@echo "** Done building Standard Library tutorials."

install-stdlib-all: install-stdlib install-stdinc install-stddemos install-stdtutor

install-stdlib:
	install -d -m $(DIRPERM) $(STDLIB)
	install -c -m $(FILEPERM) $(wildcard ${STDSRC}/*) $(STDLIB)
	@./fixlinks.sh $(STDLIB) $(STDLIB_LINKS)
	@echo "** Done installing Standard Library."

install-stdinc:
	install -d -m $(DIRPERM) $(STDINC)
	install -c -m $(FILEPERM) $(wildcard ${STDINC_SRC}/*) $(STDINC)
	@echo "** Done installing Standard Library includes."

install-stddemos: stddemos
	install -d -m $(DIRPERM) $(STDDEMO)
	install -c -m $(FILEPERM) $(wildcard ${STDDEMOS_SRC}/*) $(STDDEMO)
	@echo "** Done installing Standard Library demos."

install-stdtutor: stdtutor
	install -d -m $(DIRPERM) $(STDTUTOR)
	install -c -m $(FILEPERM) $(wildcard ${STDTUTOR_SRC}/*) $(STDTUTOR)
	@echo "** Done installing Standard Library tutorials."


##########################################################
# Rules for building and installing the PunyInform Library
%.z3: %.inf | $(BINNAME)
	$(PWD)/$(BINNAME) -v3 +$(PUNYLIB_SRC) $< $@

punyhowto:	$(BINNAME) $(PUNYHOWTO_Z3)
	@echo "** Done building PunyInform Library howtos."

punytests:	$(BINNAME) $(PUNYTESTS_Z3)
	@echo "** Done building PunyInform Library tests."

install-punywrapper:
	sed 's,^LIBPATH.*,LIBPATH=$(REAL_PREFIX)/share/$(NAME),g' $(PUNYINFORMSH) > $(PUNYINFORMSH)-scratch
	install -c -m $(BINPERM) $(PUNYINFORMSH)-scratch $(DESTDIR)$(BINDIR)/$(PUNYINFORMSH)
	cd $(DESTDIR)$(BINDIR) ; ln -sf $(PUNYINFORMSH) $(PUNYINFORM)
	cd $(DESTDIR)$(BINDIR) ; ln -sf $(PUNYINFORMSH) $(PUNYINFORM)-$(COMPVERSION)
	rm -f $(PUNYINFORMSH)-scratch

install-punylib:
	install -d -m $(DIRPERM) $(PUNYLIB)
	install -c -m $(FILEPERM) $(wildcard ${PUNYLIB_SRC}/*) $(PUNYLIB)
	@echo "** Done installing PunyInform Library."

install-punyhowto:
	install -d -m $(DIRPERM) $(PUNYHOWTO)
	install -c -m $(FILEPERM) $(wildcard ${PUNYHOWTO_SRC}/*) $(PUNYHOWTO)

install-punytests:
	install -d -m $(DIRPERM) $(PUNYTESTS)
	install -c -m $(FILEPERM) $(wildcard ${PUNYTESTS_SRC}/*) $(PUNYTESTS)

install-punydocs:
	install -d -m $(DIRPERM) $(PUNYDOCS)
	install -d -m $(DIRPERM) $(PUNYDOCS1)
	install -d -m $(DIRPERM) $(PUNYDOCS2)
	install -d -m $(DIRPERM) $(PUNYDOCS3)
	install -c -m $(FILEPERM) $(wildcard ${PUNYDOCS_SRC}/*pdf) $(PUNYDOCS)
	install -c -m $(FILEPERM) $(wildcard ${PUNYDOCS_DIR1}/*) $(PUNYDOCS1)
	install -c -m $(FILEPERM) $(wildcard ${PUNYDOCS_DIR2}/*) $(PUNYDOCS2)
	install -c -m $(FILEPERM) $(wildcard ${PUNYDOCS_DIR3}/*) $(PUNYDOCS3)

install-punymisc:
	for file in $(PUNYMISC_FILES); do \
		install -c -m $(FILEPERM) $(PUNYSRC)/$$file $(PUNY); \
	done
	install -c -m $(FILEPERM) $(wildcard ${PUNYSRC}/*.inf) $(PUNY)

install-puny:	install-punylib install-punywrapper install-punymisc install-punyhowto install-punytests install-punydocs


#############################
# Installing everything else
install-manual:
	install -d -m $(DIRPERM) $(MANDIR)
	install -c -m $(FILEPERM) $(MANPAGE) $(MANDIR)

install-contrib:
	install -c -m $(BINPERM) contrib/pblorb.pl $(DESTDIR)$(BINDIR)
	install -c -m $(BINPERM) contrib/scanblorb.pl $(DESTDIR)$(BINDIR)
	cd $(DESTDIR)$(BINDIR) ; ln -sf pblorb.pl pblorb
	cd $(DESTDIR)$(BINDIR) ; ln -sf scanblorb.pl scanblorb

install-strip: strip install

uninstall:
	rm -f $(DESTDIR)$(BINDIR)/$(NAME)*
	rm -f $(DESTDIR)$(BINDIR)/pblorb*
	rm -f $(DESTDIR)$(BINDIR)/scanblorb*
	rm -f $(DESTDIR)$(BINDIR)/$(PUNYINFORM)*
	rm -f $(MANDIR)/$(MANPAGE)
	rm -rf $(SHAREDIR)

dist: distcheck distclean submodules
ifneq ($(and $(wildcard $(GIT_DIR)),$(shell which $(GIT))),)
ifeq ($(shell which git-archive-all),)
	$(warning *** Install this:)
	$(warning *** https://gitlab.com/DavidGriffith/git-archive-all/)
	$(error git-archive-all command missing)
endif
	@git archive-all -v --format tar.gz -t HEAD --prefix $(DISTNAME)/ $(DISTNAME).tar.gz
	@echo "Here are hashes of $(DISTNAME).tar.gz:"
	@echo -n "MD5:    "
	@md5sum $(DISTNAME).tar.gz | cut -n -d" " -f1
	@echo -n "SHA1:   "
	@sha1sum $(DISTNAME).tar.gz | cut -n -d" " -f1
	@echo -n "SHA256: "
	@sha256sum $(DISTNAME).tar.gz | cut -n -d" " -f1

else
	$(warning *** Not in a git repository or git command not found.)
	$(error Cannot make a .tar.gz file)
endif

clean:
	rm -f $(BINNAME)
	rm -f ${COMPSRC}/*.o
	find . -name '*.z?' -exec rm -f {} \;
	find . -name '*.scr' -exec rm -f {} \;
	find . -name '*.output' -exec rm -f {} \;

gitclean: distcheck
ifneq ($(and $(wildcard $(GIT_DIR)),$(shell which $(GIT))),)
	$(GIT) clean -fdx
else
	$(error Not in a git repository or git command missing)
endif

distclean: clean
	find . -name *core -exec rm -f {} \;
	-rm -f punyinform.sh-scratch
	-rm -rf $(DISTNAME)*

modclean:
ifneq ($(and $(wildcard $(GIT_DIR)),$(shell which $(GIT))),)
	rm -rf $(COMPSRC) $(STDSRC) $(PUNYSRC)
else
	$(error That would be bad)
endif
