########################################################################
#
# Makefile rules for GAP, to be included from GNUmakefile.
# Partially based on the git and ScummVM build systems.
#
# This requires GNU make!!! You have been warned.
#
# To learn more about the GAP build system, see README.buildsys.md
#
########################################################################


########################################################################
# Default rule: build gap
########################################################################
all: gap$(EXEEXT) gac libgap.la CITATION doc/versiondata
.PHONY: all

# Backwards compatibility: add "default" target as alias for "all"
default: all
.PHONY: default


########################################################################
# Source files
#
# We avoid line continuations, instead use repeatedly "SOURCES+=". This
# makes it trivial to comment out lines, or to insert conditionals.
########################################################################
SOURCES =
SOURCES += src/ariths.c
SOURCES += src/bags.c
SOURCES += src/blister.c
SOURCES += src/bool.c
ifeq ($(HPCGAP),yes)
SOURCES += src/hpc/c_oper1.c
SOURCES += src/hpc/c_type1.c
else
SOURCES += src/c_oper1.c
SOURCES += src/c_type1.c
endif
SOURCES += src/calls.c
SOURCES += src/code.c
SOURCES += src/collectors.cc
SOURCES += src/compiler.c
SOURCES += src/compstat.c
SOURCES += src/costab.c
SOURCES += src/cyclotom.c
SOURCES += src/debug.c
SOURCES += src/dt.c
SOURCES += src/dteval.c
SOURCES += src/error.c
SOURCES += src/exprs.c
SOURCES += src/ffdata.c
SOURCES += src/finfield.c
SOURCES += src/funcs.c
SOURCES += src/gap.c
SOURCES += gen/gap_version.c	# generated source file
SOURCES += src/gvars.c
SOURCES += src/hookintrprtr.c
SOURCES += src/info.c
SOURCES += src/integer.c
SOURCES += src/intfuncs.c
SOURCES += src/intrprtr.c
SOURCES += src/io.c
SOURCES += src/iostream.c
ifeq ($(HPCGAP),no)             # we don't support a kernel API in HPC-GAP atm
SOURCES += src/libgap-api.c
endif
SOURCES += src/listfunc.c
SOURCES += src/listoper.c
SOURCES += src/lists.c
SOURCES += src/macfloat.c
SOURCES += src/modules.c
SOURCES += src/modules_builtin.c
SOURCES += src/objcftl.c
SOURCES += src/objects.c
SOURCES += src/objfgelm.cc
SOURCES += src/objpcgel.cc
SOURCES += src/objset.c
SOURCES += src/opers.c
SOURCES += src/permutat.cc
SOURCES += src/plist.c
SOURCES += src/pperm.cc
SOURCES += src/precord.c
SOURCES += src/profile.c
SOURCES += src/range.c
SOURCES += src/rational.c
SOURCES += src/read.c
SOURCES += src/records.c
SOURCES += src/saveload.c
SOURCES += src/scanner.c
SOURCES += src/sctable.c
SOURCES += src/set.c
SOURCES += src/stats.c
SOURCES += src/streams.c
SOURCES += src/stringobj.c
SOURCES += src/syntaxtree.c
SOURCES += src/sysfiles.c
SOURCES += src/sysmem.c
SOURCES += src/system.c
SOURCES += src/tietze.c
SOURCES += src/trans.cc
SOURCES += src/vars.c
SOURCES += src/vec8bit.c
SOURCES += src/vecffe.c
SOURCES += src/vecgf2.c
SOURCES += src/vector.c
SOURCES += src/weakptr.c

SOURCES += $(GC_SOURCES)

ifeq ($(HPCGAP),yes)
  SOURCES += src/hpc/aobjects.c
  SOURCES += src/hpc/misc.c
  SOURCES += src/hpc/region.c
  SOURCES += src/hpc/serialize.c
  SOURCES += src/hpc/thread.c
  SOURCES += src/hpc/threadapi.c
  SOURCES += src/hpc/tls.c
  SOURCES += src/hpc/traverse.c
endif

########################################################################
# Preprocessor flags
#
# GAP_CPPFLAGS is for the GAP build system, while GAP_PKG_CPPFLAGS is
# for use by gac, and for package build systems. The latter does not
# contain warning flags, and uses absolute include paths.
########################################################################

GAP_CPPFLAGS =
GAP_PKG_CPPFLAGS =

# First add include paths

# The "gen" directory contains generated files and thus is placed into
# the build directory.
GAP_CPPFLAGS += -I$(builddir)/gen
GAP_PKG_CPPFLAGS += -I$(abs_builddir)/gen

# The other source files are relative to the srcdir
GAP_CPPFLAGS += -I$(srcdir)/src
GAP_PKG_CPPFLAGS += -I$(abs_srcdir)/src

# For backwards compatibility with certain packages and their kernel
# extensions, also add the root of the srcdir to the package CPPFLAGS
GAP_PKG_CPPFLAGS += -I$(abs_srcdir)

# Add DEFS (from autoconf, contains -D flags)
GAP_CPPFLAGS += $(DEFS)
GAP_PKG_CPPFLAGS += $(DEFS)

# Add flags for dependencies
GAP_CPPFLAGS += $(GMP_CPPFLAGS)
GAP_CPPFLAGS += $(ZLIB_CPPFLAGS)
GAP_CPPFLAGS += $(READLINE_CPPFLAGS)
GAP_CPPFLAGS += $(JULIA_CPPFLAGS)
GAP_CPPFLAGS += $(BOEHM_GC_CPPFLAGS)
GAP_CPPFLAGS += $(LIBATOMIC_OPS_CPPFLAGS)

GAP_PKG_CPPFLAGS += $(GMP_CPPFLAGS)
GAP_PKG_CPPFLAGS += $(ZLIB_CPPFLAGS)
GAP_PKG_CPPFLAGS += $(READLINE_CPPFLAGS)
GAP_PKG_CPPFLAGS += $(JULIA_CPPFLAGS)
GAP_PKG_CPPFLAGS += $(BOEHM_GC_CPPFLAGS)
GAP_PKG_CPPFLAGS += $(LIBATOMIC_OPS_CPPFLAGS)

# Finally add user provided flags
GAP_CPPFLAGS += $(CPPFLAGS)
GAP_PKG_CPPFLAGS += $(CPPFLAGS)


########################################################################
# C compiler flags
########################################################################
GAP_CFLAGS =

ifeq ($(HPCGAP),yes)
GAP_CFLAGS += $(PTHREAD_CFLAGS)
endif

# Finally add user provided CFLAGS
GAP_CFLAGS += $(CFLAGS)


########################################################################
# C++ compiler flags
########################################################################
GAP_CXXFLAGS =

ifeq ($(HPCGAP),yes)
GAP_CXXFLAGS += $(PTHREAD_CFLAGS)
endif

# Finally add user provided CXXFLAGS
GAP_CXXFLAGS += $(CXXFLAGS)


########################################################################
# Linker flags
########################################################################
GAP_LDFLAGS =

# Add flags for dependencies
GAP_LDFLAGS += $(GMP_LDFLAGS)
GAP_LDFLAGS += $(ZLIB_LDFLAGS)
GAP_LDFLAGS += $(READLINE_LDFLAGS)
GAP_LDFLAGS += $(JULIA_LDFLAGS)
GAP_LDFLAGS += $(BOEHM_GC_LDFLAGS)
GAP_LDFLAGS += $(LIBATOMIC_OPS_LDFLAGS)

ifeq ($(HPCGAP),yes)
GAP_LDFLAGS += $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
endif

# Finally add user provided flags
GAP_LDFLAGS += $(LDFLAGS)


# libs
GAP_LIBS =

# Add flags for dependencies
GAP_LIBS += $(GMP_LIBS)
GAP_LIBS += $(ZLIB_LIBS)
GAP_LIBS += $(READLINE_LIBS)
GAP_LIBS += $(JULIA_LIBS)
GAP_LIBS += $(BOEHM_GC_LIBS)
GAP_LIBS += $(LIBATOMIC_OPS_LIBS)

# Finally add user provided flags
GAP_LIBS += $(LIBS)


########################################################################
# Object files
########################################################################

# OBJS shall contain the names of all object files that constitute GAP.
# So turn all FOO/*.c and FOO/*.cc file names in SOURCES into obj/FOO/*.lo
OBJS = $(patsubst %.cc,obj/%.lo,$(patsubst %.c,obj/%.lo,$(SOURCES)))

# ensure config.h is built before the compilers gets invoked
$(OBJS): gen/config.h


########################################################################
# Quiet rules.
#
# Replace regular output with quiet messages, unless V is set,
# e.g. "make V=1"
########################################################################
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
QUIET_CC      = @echo "   C       $< => $@";
QUIET_CXX     = @echo "   CXX     $< => $@";
QUIET_LINK    = @echo "   LINK    $@";
QUIET_SED     = @echo "   SED     $< => $@";
QUIET         = @
LIBTOOL 	 += --silent
endif
endif


########################################################################
# Rules for automatic header dependency tracking.
#
# This is somewhat similar to what automake does, but relies on compiler
# support. The result is much simpler.
#
# So, here is what happens: In each directory containing source files,
# a ".deps" subdirectory is created. We then instruct the compiler via
# some flags to create a ".deps/FOO.d" file when it compiles "FOO.c".
# This file encodes the header dependencies of "FOO.c" in a way that
# make can read (i.e. simply as a bunch of make targets with
# dependencies).
#
# Finally, to let make track the header dependencies, we include the *.d files.
#
# For a more detailed explanation of a very similar scheme, read this:
# https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
#
########################################################################

# Name of subdirectories in which the generated dependencies are stored.
DEPDIRNAME := .deps

# List of all (potential) dependency directories, derived from OBJS
# and SOURCES (the latter for generated sources, which may also involve
# dependency tracking)
DEPDIRS = $(addsuffix $(DEPDIRNAME),$(sort $(dir $(SOURCES) $(OBJS))))

# Include the dependency tracking files.
-include $(wildcard $(addsuffix /*.d,$(DEPDIRS)))

# Mark *.d files as PHONY. This stops make from trying to
# recreate them (which it can't), and in particular from looking for potential
# source files. This can save quite a bit of disk access time.
.PHONY: $(wildcard $(addsuffix /*.d,$(DEPDIRS)))

DEPFILE = "$(@D)/$(DEPDIRNAME)/$(*F).d"

# The following flags instruct the compiler to enable advanced
# dependency tracking. Supported by GCC 3 and newer; clang; Intel C
# compiler; and more.
#
# TODO: use configure to compute DEPFLAGS, so that we can
# disable it for compilers that don't support it, resp. replace it
# something that works for that compiler
DEPFLAGS = -MQ "$@" -MMD -MP -MF $(DEPFILE)


########################################################################
# Compiler rules
########################################################################

# HACK: when we rename a file foobar.c to foobar.cc (i.e., only the extension
# is changed from C to C++), then this can cause problems in the .d file, as
# they contain rules which depend on the source file, and that is now gone.
# As a result, one may get errors like this:
#
#  make: *** No rule to make target 'src/objpcgel.c', needed by 'obj/src/objpcgel.lo'.  Stop.
#
# To avoid this, we simply add an empty rule  `foobar.c:` resp. `foobar.cc:`
# to the end of the .d files, via this line in the build rules:
#	@echo "$<:" >> $(DEPFILE)
#
# Extra hack: Since old versions of the build system don't have this,
# switching from a build with such an old version to one with a new version
# (e.g. during a `git bisect`) still runs into the above error. To work
# around that, we add a few explicit rules down below, for files that were
# changed from .c to .cc
$(srcdir)/src/objfgelm.c:
$(srcdir)/src/objpcgel.c:
$(srcdir)/src/permutat.c:
$(srcdir)/src/pperm.c:
$(srcdir)/src/trans.c:

# Build rule for C++ source files
#
# We disable support for exceptions and RTTI as we don't use them and they
# cause compiler/linker issues in some build configurations; but we are
# careful to not put these into GAP_CXXFLAGS, as kernel extensions may want to
# use GAP_CXXFLAGS but also may have a  need to interface with C++ code in
# libraries that use exceptions.
obj/%.lo: %.cc cnf/GAP-CXXFLAGS cnf/GAP-CPPFLAGS libtool
	@$(MKDIR_P) $(@D)/$(DEPDIRNAME)
	$(QUIET_CXX)$(LIBTOOL) --mode=compile --tag CXX $(CXX) $(DEPFLAGS) $(GAP_CXXFLAGS) -fno-exceptions -fno-rtti $(WARN_CXXFLAGS) $(GAP_CPPFLAGS) -c $< -o $@
	@echo "$<:" >> $(DEPFILE)

# Build rule for C source files
obj/%.lo: %.c cnf/GAP-CFLAGS cnf/GAP-CPPFLAGS libtool
	@$(MKDIR_P) $(@D)/$(DEPDIRNAME)
	$(QUIET_CC)$(LIBTOOL) --mode=compile --tag CC $(CC) $(DEPFLAGS) $(GAP_CFLAGS) $(WARN_CFLAGS) $(GAP_CPPFLAGS) -c $< -o $@
	@echo "$<:" >> $(DEPFILE)


########################################################################
# Linker rules for gap executable
########################################################################

LINK=$(LIBTOOL) --mode=link $(CC) -export-dynamic

libgap.la: $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) -no-undefined -rpath $(libdir) $(GAP_LDFLAGS) $(OBJS) $(GAP_LIBS) -o $@

ifeq ($(SYS_IS_CYGWIN32),yes)

all: bin/gapicon.bmp bin/gapicon.ico bin/instcygwinterminfo.sh bin/cygwin-version.txt
bin/gapicon.bmp: $(srcdir)/cnf/cygwin/gapicon.bmp
	cp $< $@
bin/gapicon.ico: $(srcdir)/cnf/cygwin/gapicon.ico
	cp $< $@
bin/instcygwinterminfo.sh: $(srcdir)/cnf/cygwin/instcygwinterminfo.sh
	cp $< $@
	chmod a+x $@
bin/cygwin-version.txt:
	uname -a > $@

GAP_CPPFLAGS += "-DCOMPILECYGWINDLL"

# increase stack size, the default is too small (see issue #1522)
GAP_LDFLAGS += -Wl,--stack,16777216

# Allow multiple definitions so we can declare a function multiple times with 'extern inline'
GAP_LDFLAGS += -Wl,--allow-multiple-definition

# Special build rules for CYGWIN / Windows: In order to allow kernel
# extensions, we employ a trick: GAP itself is compiled into DLL, in which 
# GAP's standard main function is renamed. And gap.exe is a tiny binary which
# loads that DLL and calls the renamed main function.
all: bin/$(GAPARCH)/gap.dll
bin/$(GAPARCH)/gap.dll: symlinks libgap.la
	cp .libs/cyggap-0.dll $@  # FIXME: HACK to support kernel extensions
gap$(EXEEXT): libgap.la cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $(srcdir)/src/gapw95.c $(GAP_LIBS) libgap.la -o $@
	@( if which peflags > /dev/null ; then peflags --cygwin-heap=2048 gap$(EXEEXT) ; fi )

else

# Linking rule and dependencies for the main gap executable
gap$(EXEEXT): $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $(OBJS) $(GAP_LIBS) -o $@

endif

########################################################################
# The "docomp" target regenerates the various src/c_*.c files, and
# replaces the old "etc/docomp" script.
########################################################################
ifeq ($(HPCGAP),yes)
DOCOMP_PREFIX = $(abs_srcdir)/src/hpc
else
DOCOMP_PREFIX = $(abs_srcdir)/src
endif
docomp: #gap$(EXEEXT)
	@"$(abs_srcdir)"/cnf/GAP-C-GEN $(abs_srcdir)/lib $(DOCOMP_PREFIX) oper1 ./gap$(EXEEXT)
	@"$(abs_srcdir)"/cnf/GAP-C-GEN $(abs_srcdir)/lib $(DOCOMP_PREFIX) type1 ./gap$(EXEEXT)

.PHONY: docomp


########################################################################
# The "ffdata" target regenerates src/ffdata.{c,h} using etc/ffgen.c
########################################################################

ffgen: etc/ffgen.c
	$(QUIET_CC)$(CC) -Wall -Wextra $< -o $@

ffdata: ffgen
	./ffgen -h > $(abs_srcdir)/src/ffdata.h
	./ffgen -c > $(abs_srcdir)/src/ffdata.c

.PHONY: ffdata


########################################################################
# The "tags" target regenerates the tags file using Exuberant Ctags
########################################################################

tags:
	cd $(abs_srcdir) && etc/tags.sh --recurse lib hpcgap/lib src

etags:
	cd $(abs_srcdir) && etc/tags.sh -e --recurse lib hpcgap/lib src

.PHONY: tags etags


########################################################################
# Rules for 'make clean'
########################################################################
distclean: clean
	rm -rf autom4te.cache
	rm -f config.log config.status libtool GNUmakefile
	rm -f stamp-h
	rm -f doc/make_doc
	rm -f doc/*/*.aux doc/*/*.bbl doc/*/*.blg doc/*/*.brf doc/*/*.idx doc/*/*.ilg doc/*/*.ind doc/*/*.log doc/*/*.out doc/*/*.pnr doc/*/*.tex doc/*/*.toc
	rm -rf gen
	rm -rf dev/log
	rm -rf tags
	rm -rf TAGS

clean:
	rm -rf bin/$(GAPARCH)
	rm -rf obj
	rm -rf extern/build extern/install
	rm -f bin/gap.sh sysinfo.gap*
	rm -f gap$(EXEEXT) gac ffgen
	rm -f libgap.la
	rm -rf .libs
	rm -f gen/gap_version.c
	rm -f doc/wsp.g
	rm -f cnf/GAP-{CFLAGS,CPPFLAGS,CXXFLAGS,LDFLAGS,LIBS,OBJS}
	rmdir bin cnf dev doc extern src 2>/dev/null || : # remove dirs if they are now empty

.PHONY: clean distclean


########################################################################
# Rules for 'make install'
########################################################################

LTINSTALL=$(LIBTOOL) --mode=install $(INSTALL)

install:
	@echo "Error, 'make install' has not yet been implemented"
	exit 1

# the following is wrapper script which is installed by the install-bin target
define gap_wrapper
#!/bin/sh
exec "$(bindir)/gap.real" -l "$(datarootdir)/gap" "$$@"
endef
export gap_wrapper

install-bin:
	@echo "Warning, 'make install-bin' is incomplete"
	$(INSTALL) -d -m 0755 $(DESTDIR)$(bindir)
	$(INSTALL) -m 0755 gap $(DESTDIR)$(bindir)/gap.real
	echo "$$gap_wrapper" > gap-wrapper.sh
	$(INSTALL) -m 0755 gap-wrapper.sh $(DESTDIR)$(bindir)/gap
	# TODO: make gac installable; this requires adjusting path in it, and
	# installing the libtool script generated by configure somewhere; and then
	# putting that path to it into gac)
	#$(INSTALL) gac $(DESTDIR)$(bindir)

install-gaproot:
	@echo "Warning, 'make install-gaproot' is incomplete"
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap
	# TODO: update paths and FLAGS in sysinfo.gap
	$(INSTALL) -m 0644 sysinfo.gap $(DESTDIR)$(datarootdir)/gap
	# the following lines should not use `cp -r`, which is not quite portable,
	# and which also may not deal with file permissions correctly
	cp -r $(srcdir)/doc $(DESTDIR)$(datarootdir)/gap/  # FIXME: don't use `cp -r`
	cp -r $(srcdir)/grp $(DESTDIR)$(datarootdir)/gap/  # FIXME: don't use `cp -r`
	cp -r $(srcdir)/lib $(DESTDIR)$(datarootdir)/gap/  # FIXME: don't use `cp -r`
	# TODO: what about CITATION, CONTRIBUTING.md, COPYRIGHT, INSTALL.md,
	# LICENSE, README* ? Copy them also here? Or into some other path?
	# TODO: also copy bin/BuildPackage.sh, as it is very useful?

install-pkg:
	@echo "Warning, 'make install-pkg' is incomplete"
	# TODO: should we try to compiled packages? perhaps better not, leave it
	# to the packagers, as they also need to consider build dependencies ?! If
	# we do try it, then we may need to deal with adjusting paths and so on...
	# we can't really install packages by any other means that copying their
	# whole directory... One strategy to overcome this: in the future, we
	# demand that packages which must be built using `make` also support
	#     `make install prefix=DIR DESTDIR=dir`
	# and/or allow packages to have a `Install(prefix, destdir)` field in
	# their `PackageInfo.g` which contains a function that takes care of
	# installation (e.g. by running `make install`, or by any other means).
	# This could also be used by the PackageManager package (or perhaps we
	# should just use PackageManager ourselves, and/or recommend it to
	# packagers).

install-headers:
	@echo "Warning, 'make install-headers' is incomplete"
	$(INSTALL) -d -m 0755 $(DESTDIR)$(includedir)/gap
	$(INSTALL) -m 0644 $(srcdir)/src/*.h $(DESTDIR)$(includedir)/gap
	# TODO: run the following only if HPC-GAP is enabled?
	$(INSTALL) -d -m 0755 $(DESTDIR)$(includedir)/gap/hpc
	$(INSTALL) -m 0644 $(srcdir)/src/hpc/*.h $(DESTDIR)$(includedir)/gap/hpc
	# TODO: take care of config.h, this is difficult

install-libgap: libgap.la
	@echo "Warning, 'make install-libgap' is incomplete"
	$(INSTALL) -d -m 0755 $(DESTDIR)$(libdir)
	$(LTINSTALL) libgap.la $(DESTDIR)$(libdir)


.PHONY: install install-bin install-gaproot install-headers install-libgap

########################################################################
# Building subprojects
########################################################################


# master target for external dependencies / subprojects
EXTERN_FILES =


#
# GMP
#
ifeq ($(BUILD_GMP),yes)

GMP_BUILDDIR := extern/build/gmp
GMP_PREFIX := extern/install/gmp
# GMP_PREREQ := $(GMP_BUILDDIR)/config.status
GMP_FILES := $(GMP_PREFIX)/lib/libgmp.la

EXTERN_FILES += $(GMP_FILES)

# Note: we pass the ABI flag to gmp, and also --enable-shared ; the latter
# is there for the benefit of cygwin builds, where GMP otherwise defaults
# to building only a static library.
# We touch gmp.info so GMP does not think it is out of date and rebuilds it,
# because that requires makeinfo
gmp: $(GMP_FILES)
$(GMP_FILES):
	touch "$(abs_srcdir)/extern/gmp/doc/gmp.info"
	MAKE=$(MAKE) $(srcdir)/cnf/build-extern.sh gmp "$(abs_srcdir)/extern/gmp" ABI=$(ABI) --disable-static --enable-shared

.PHONY: gmp

# TODO: add clean, distclean, check targets?
# TODO: pass on cachfile?
# TODO: pass on certain *FLAGS ?


else

gmp:
	echo "Using external GMP, nothing to do be done"

endif # BUILD_GMP


#
# ZLIB
#
ifeq ($(BUILD_ZLIB),yes)

ZLIB_BUILDDIR := extern/build/zlib
ZLIB_PREFIX := extern/install/zlib
# ZLIB_PREREQ := $(ZLIB_BUILDDIR)/config.status
ZLIB_FILES := $(ZLIB_PREFIX)/include/zlib.h

EXTERN_FILES += $(ZLIB_FILES)

zlib: $(ZLIB_FILES)
ifeq ($(SYS_IS_CYGWIN32),yes)
$(ZLIB_FILES):
	MAKE=$(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" $(srcdir)/cnf/build-cygwin-zlib.sh

else

$(ZLIB_FILES):
	MAKE=$(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" $(srcdir)/cnf/build-extern.sh zlib "$(abs_srcdir)/extern/zlib"

endif # SYS_IS_CYGWIN32

.PHONY: zlib

# TODO: add clean, distclean, check targets?
# TODO: pass on cachfile?
# TODO: pass on certain *FLAGS ?

else

zlib:
	echo "Using external zlib, nothing to do be done"

endif # BUILD_ZLIB


#
# libatomic_ops
#
ifeq ($(BUILD_LIBATOMIC_OPS),yes)

LIBATOMIC_OPS_BUILDDIR := extern/build/libatomic_ops
LIBATOMIC_OPS_PREFIX := extern/install/libatomic_ops
#LIBATOMIC_OPS_PREREQ := $(LIBATOMIC_OPS_BUILDDIR)/config.status
LIBATOMIC_OPS_FILES := $(LIBATOMIC_OPS_PREFIX)/lib/libatomic_ops.la

EXTERN_FILES += $(LIBATOMIC_OPS_FILES)

libatomic_ops: $(LIBATOMIC_OPS_FILES)
$(LIBATOMIC_OPS_FILES):
	MAKE=$(MAKE) CC="$(CC)"  \
	$(srcdir)/cnf/build-extern.sh libatomic_ops "$(abs_srcdir)/hpcgap/extern/libatomic_ops" --disable-static --enable-shared

# TODO: MAKEFLAGS=-j1

.PHONY: libatomic_ops

endif # BUILD_LIBATOMIC_OPS


#
# Boehm GC
#
ifeq ($(BUILD_BOEHM_GC),yes)

# TODO: ensure Boehm GC is built *after* libatomic_ops, at least if
# we are building or own libatomic_ops.
# Also, ensure that it uses the right version of libatomic_ops,
# by passing --with-libatomic-ops=...

# TODO: also pass

# TODO: refactor code which handles dependencies like GMP, Boehm, libatomic,
# to reduce code duplication.

# TODO: pass on more things to configure, e.g. the build / host system type...
# 

BOEHM_GC_BUILDDIR := extern/build/gc
BOEHM_GC_PREFIX := extern/install/gc
#BOEHM_GC_PREREQ := $(BOEHM_GC_BUILDDIR)/config.status
BOEHM_GC_FILES := $(BOEHM_GC_PREFIX)/lib/libgc.la

EXTERN_FILES += $(BOEHM_GC_FILES)

boehm: gc # alias
gc: $(BOEHM_GC_FILES)
$(BOEHM_GC_FILES):
	MAKE=$(MAKE) \
	CC="$(CC)" \
	ATOMIC_OPS_CFLAGS=$(LIBATOMIC_OPS_CPPFLAGS) \
	ATOMIC_OPS_LIBS=$(LIBATOMIC_OPS_LDFLAGS) \
	$(srcdir)/cnf/build-extern.sh gc "$(abs_srcdir)/hpcgap/extern/gc" --disable-static --enable-shared --enable-large-config

ifeq ($(BUILD_LIBATOMIC_OPS),yes)
$(BOEHM_GC_FILES): $(LIBATOMIC_OPS_FILES)
endif

.PHONY: boehm gc

endif # BUILD_BOEHM_GC


# ensure subprojects are built and "installed" before compiling and linking GAP
gap$(EXEEXT): $(EXTERN_FILES)
$(OBJS): $(EXTERN_FILES)
ifeq ($(HPCGAP),yes)
$(SOURCES): $(EXTERN_FILES)
endif


# regenerate sysinfo.gap if necessary
define sysinfo_gap
# This file has been generated by the GAP build system,
# do not edit manually!
GAParch=$(GAPARCH)
GAP_ABI=$(ABI)
GAP_HPCGAP=$(HPCGAP)

GAP_VERSION="$(GAP_VERSION)"
GAP_BUILD_VERSION="$(GAP_BUILD_VERSION)"
GAP_KERNEL_MAJOR_VERSION=$(GAP_KERNEL_MAJOR_VERSION)
GAP_KERNEL_MINOR_VERSION=$(GAP_KERNEL_MINOR_VERSION)

GAP_BIN_DIR="$(abs_builddir)"
GAP_LIB_DIR="$(abs_srcdir)"

GAP_CC="$(CC)"
GAP_CXX="$(CXX)"
GAP_CFLAGS="$(GAP_CFLAGS)"
GAP_CXXFLAGS="$(GAP_CXXFLAGS)"
GAP_CPPFLAGS="$(GAP_PKG_CPPFLAGS)"
GAP_LDFLAGS="$(GAP_LDFLAGS)"
GAP_LIBS="$(GAP_LIBS)"

GAP_OBJS="$(OBJS)"

JULIA="$(JULIA)"
JULIA_CPPFLAGS="$(JULIA_CPPFLAGS)"
JULIA_LDFLAGS="$(JULIA_LDFLAGS)"
JULIA_LIBS="$(JULIA_LIBS)"
endef
export sysinfo_gap

all: sysinfo.gap
sysinfo.gap: config.status $(srcdir)/Makefile.rules cnf/GAP-CFLAGS cnf/GAP-CPPFLAGS cnf/GAP-CXXFLAGS cnf/GAP-LDFLAGS cnf/GAP-LIBS
	@rm -f sysinfo.gap	# in case this is a symlink created by an older version of the build system
	@echo "$$sysinfo_gap" >sysinfo.gap


########################################################################
# Compatibility mode
#
# If enabled, we prepare the environment to look like it did with
# the old build system, thus enabling existing packages with kernel
# extensions to be compiled against this version of GAP/
########################################################################
ifeq ($(COMPAT_MODE),yes)

# regenerate bin/gap.sh if necessary
all: bin/gap.sh
bin/gap.sh: $(srcdir)/cnf/compat/gap.sh.in config.status
	$(SHELL) ./config.status $@

# regenerate symlinks if necessary
all: symlinks
symlinks: FORCE
	@$(MKDIR_P) bin/$(GAPARCH)
	@if test -L sysinfo.gap ; then rm -f sysinfo.gap && $(MAKE) sysinfo.gap ; fi
	@$(srcdir)/cnf/REGEN-SYMLINK sysinfo.gap sysinfo.gap-default$(ABI)
	@$(srcdir)/cnf/REGEN-SYMLINK $(abs_srcdir)/src bin/$(GAPARCH)/src
	@$(srcdir)/cnf/REGEN-SYMLINK ../../gac bin/$(GAPARCH)/gac
	@$(srcdir)/cnf/REGEN-SYMLINK ../../gap bin/$(GAPARCH)/gap
	@$(srcdir)/cnf/REGEN-SYMLINK ../../gen/config.h bin/$(GAPARCH)/config.h

.PHONY: symlinks

endif

########################################################################
# Specifying GAP calls to use for the test suite and building manuals
########################################################################

GAPARGS=
TESTGAP = $(abs_builddir)/bin/gap.sh --quitonbreak -b -m 100m -o 1g -q -x 80 -r -A $(GAPARGS)
TESTGAPauto = $(abs_builddir)/bin/gap.sh --quitonbreak -b -m 100m -o 1g -q -x 80 -r $(GAPARGS)

########################################################################
# Documentation rules
########################################################################

# Alias for backwards compatibility
manuals: doc

doc: gap$(EXEEXT) doc/make_doc doc/versiondata
	doc/make_doc

html: gap$(EXEEXT) doc/make_doc doc/versiondata
	doc/make_doc nopdf

clean-doc:
	rm -f doc/*/chap*.html doc/*/chap*.txt doc/*/*.css doc/*/*.js
	rm -f doc/*/chooser.html doc/*/manual*.pdf
	rm -f doc/*/*.{aux,bbl,blg,brf,idx,ilg,ind,lab,log,out,pnr,six,tex,toc}
	rm -f doc/manualbib.xml.bib

# FIXME: we currently build the manual inside $srcdir; so we don't want "make clean"
# to remove it, as other builds might share the manual.
#clean: clean-doc

# Manual consistency check
check-manuals: all
	$(MKDIR_P) dev/log
	( cd doc/ref ; echo 'Read("testconsistency.g");' | $(TESTGAP) | \
	               tee `date -u +../../dev/log/check_manuals_%Y-%m-%d-%H-%M` )

.PHONY: doc clean-doc manuals check-manuals html

########################################################################
# Rules for test{install/standard/etc.} targets
########################################################################

# run testinstall.g twice:
# - without packages (except needed to run GAP)
# - with all packages loaded
testinstall: all
	$(MKDIR_P) dev/log
	( echo 'SetUserPreference("UseColorsInTerminal",false); \
	        SetUserPreference("ReproducibleBehaviour", true); \
            ReadGapRoot( "tst/testinstall.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/testinstall1_%Y-%m-%d-%H-%M` )
	( echo 'SetUserPreference("UseColorsInTerminal",false); LoadAllPackages(); \
	        SetUserPreference("ReproducibleBehaviour", true); \
            ReadGapRoot( "tst/testinstall.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/testinstall2_%Y-%m-%d-%H-%M` )

# test manual examples three times:
# - without packages
# - with packages loaded by default
# - with all packages loaded
testmanuals: all
	$(MKDIR_P) dev/log
	((cd doc/tut ; \
	  echo 'SetUserPreference("UseColorsInTerminal",false); SetAssertionLevel( 2 ); \
	  SetUserPreference("ReproducibleBehaviour", true); \
	  Read("extractexamples.g"); Read("runexamples.g"); ' | $(TESTGAP);\
	  echo '============================================================';\
	  cd ../.. ; ff=`ls doc/tut/EXAMPLEDIFFS* 2> /dev/null | wc -l`; \
	  if [ $$ff != "0" ] ; then cat doc/tut/EXAMPLEDIFFS*; \
	  else echo "NO DIFFERENCES IN TUTORIAL EXAMPLES (NO PACKAGES)"; fi ; \
	  echo '============================================================';\
	  cd doc/ref ; \
	  echo 'SetUserPreference("UseColorsInTerminal",false); SetAssertionLevel( 2 ); \
	  SetUserPreference("ReproducibleBehaviour", true); \
	  Read("extractexamples.g"); Read("runexamples.g"); ' | $(TESTGAP);\
	  echo '============================================================';\
	  cd ../.. ; ff=`ls doc/ref/EXAMPLEDIFFS* 2> /dev/null | wc -l`; \
	  if [ $$ff != "0" ] ; then cat doc/ref/EXAMPLEDIFFS*; \
	  else echo "NO DIFFERENCES IN REFERENCE MANUAL EXAMPLES (NO PACKAGES)"; fi ) \
	  > `date -u +dev/log/testmanuals1_%Y-%m-%d-%H-%M` 2>&1 )
	( rm -rf doc/tut/EXAMPLEDIFFS*; rm -rf doc/ref/EXAMPLEDIFFS* )
	((cd doc/tut ; \
	  echo 'SetUserPreference("UseColorsInTerminal",false); SetAssertionLevel( 2 ); \
	  SetUserPreference("ReproducibleBehaviour", true); \
	  Read("extractexamples.g"); Read("runexamples.g"); ' | $(TESTGAPauto);\
	  echo '============================================================';\
	  cd ../.. ; ff=`ls doc/tut/EXAMPLEDIFFS* 2> /dev/null | wc -l`; \
	  if [ $$ff != "0" ] ; then cat doc/tut/EXAMPLEDIFFS*; \
	  else echo "NO DIFFERENCES IN TUTORIAL EXAMPLES (DEFAULT PACKAGES)"; fi ; \
	  echo '============================================================';\
	  cd doc/ref ; \
	  echo 'SetUserPreference("UseColorsInTerminal",false); SetAssertionLevel( 2 ); \
	  SetUserPreference("ReproducibleBehaviour", true); \
	  Read("extractexamples.g"); Read("runexamples.g"); ' | $(TESTGAPauto);\
	  echo '============================================================';\
	  cd ../.. ; ff=`ls doc/ref/EXAMPLEDIFFS* 2> /dev/null | wc -l`; \
	  if [ $$ff != "0" ] ; then cat doc/ref/EXAMPLEDIFFS*; \
	  else echo "NO DIFFERENCES IN REFERENCE MANUAL EXAMPLES (DEFAULT PACKAGES)"; fi ) \
	  > `date -u +dev/log/testmanualsA_%Y-%m-%d-%H-%M` 2>&1 )
	( rm -rf doc/tut/EXAMPLEDIFFS*; rm -rf doc/ref/EXAMPLEDIFFS* )
	((cd doc/tut ; \
	  echo 'SetUserPreference("UseColorsInTerminal",false); SetAssertionLevel( 2 ); \
	  LoadAllPackages() ; \
	  SetUserPreference("ReproducibleBehaviour", true); \
	  Read("extractexamples.g"); Read("runexamples.g"); ' | $(TESTGAP);\
	  echo '============================================================';\
	  cd ../.. ; ff=`ls doc/tut/EXAMPLEDIFFS* 2> /dev/null | wc -l`; \
	  if [ $$ff != "0" ] ; then cat doc/tut/EXAMPLEDIFFS*; \
	  else echo "NO DIFFERENCES IN TUTORIAL EXAMPLES (ALL PACKAGES)"; fi ; \
	  echo '============================================================';\
	  cd doc/ref ; \
	  echo 'SetUserPreference("UseColorsInTerminal",false); SetAssertionLevel( 2 ); \
	  LoadAllPackages() ; \
	  SetUserPreference("ReproducibleBehaviour", true); \
	  Read("extractexamples.g"); Read("runexamples.g"); ' | $(TESTGAP);\
	  echo '============================================================';\
	  cd ../.. ; ff=`ls doc/ref/EXAMPLEDIFFS* 2> /dev/null | wc -l`; \
	  if [ $$ff != "0" ] ; then cat doc/ref/EXAMPLEDIFFS*; \
	  else echo "NO DIFFERENCES IN REFERENCE MANUAL EXAMPLES (ALL PACKAGES)"; fi ) \
	  > `date -u +dev/log/testmanuals2_%Y-%m-%d-%H-%M` 2>&1 )
	( rm -rf doc/tut/EXAMPLEDIFFS*; rm -rf doc/ref/EXAMPLEDIFFS* )

# check how packages are loaded when loading obsoletes is disabled
# - when all dependencies are loaded
# - when packages are loaded with `OnlyNeeded` option
testobsoletes: all
	$(MKDIR_P) dev/log
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) -O )
	( echo 'CreatePackageLoadTestsInput( "testobsoletes1.in", \
            "dev/log/testobsoletes1", \
            "$(TESTGAP) -O -L wsp.g", false, false );'\
            | $(TESTGAP) -O -L wsp.g > /dev/null )
	( chmod 777 testobsoletes1.in; ./testobsoletes1.in > \
            `date -u +dev/log/testobsoletes1_%Y-%m-%d-%H-%M`; rm testobsoletes1.in )
	( rm wsp.g )
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) -O )
	( echo 'CreatePackageLoadTestsInput( "testobsoletesN1.in", \
            "dev/log/testobsoletesN1", \
            "$(TESTGAP) -O -L wsp.g", false, true );'\
            | $(TESTGAP) -O -L wsp.g > /dev/null )
	( chmod 777 testobsoletesN1.in; ./testobsoletesN1.in > \
            `date -u +dev/log/testobsoletesN1_%Y-%m-%d-%H-%M`; rm testobsoletesN1.in )
	( rm wsp.g )

# For a package with the name given by the PKGNAME variable,
# run its standard tests (i.e. those specified in PackageInfo.g):
# - in GAP started without packages
# - in GAP started with packages loaded by default
# - in GAP started with all packages loaded
testpackage: all
	$(MKDIR_P) dev/log
	( echo 'SetAssertionLevel( 2 ); ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageTestsInput( "testpackage.in", \
            "dev/log/testpackage1", \
            "$(TESTGAP) -L wsp.g", "false", "$(PKGNAME)" );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackage.in; ./testpackage.in; rm testpackage.in )
	( rm wsp.g )
	( echo 'SetAssertionLevel( 2 ); ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAPauto) )
	( echo 'CreatePackageTestsInput( "testpackage.in", \
            "dev/log/testpackageA", \
            "$(TESTGAPauto) -L wsp.g", "auto", "$(PKGNAME)" );'\
            | $(TESTGAPauto) -L wsp.g > /dev/null )
	( chmod 777 testpackage.in; ./testpackage.in; rm testpackage.in )
	( rm wsp.g )
	( echo 'SetAssertionLevel( 2 ); ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageTestsInput( "testpackage.in", \
            "dev/log/testpackage2", \
            "$(TESTGAP) -L wsp.g", "true", "$(PKGNAME)" );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackage.in; ./testpackage.in; rm testpackage.in )
	( rm wsp.g )

# For each package that specifies its standard tests in PackageInfo.g, run it
# - in GAP started without packages
# - in GAP started with packages loaded by default
# - in GAP started with all packages loaded
testpackages: all
	$(MKDIR_P) dev/log
	( echo 'SetAssertionLevel( 2 ); ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageTestsInput( "testpackages.in", \
            "dev/log/testpackages1", \
            "$(TESTGAP) -L wsp.g", "false" );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackages.in; ./testpackages.in; rm testpackages.in )
	( rm wsp.g )
	( echo 'SetAssertionLevel( 2 ); ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAPauto) )
	( echo 'CreatePackageTestsInput( "testpackages.in", \
            "dev/log/testpackagesA", \
            "$(TESTGAPauto) -L wsp.g", "auto" );'\
            | $(TESTGAPauto) -L wsp.g > /dev/null )
	( chmod 777 testpackages.in; ./testpackages.in; rm testpackages.in )
	( rm wsp.g )
	( echo 'SetAssertionLevel( 2 ); ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageTestsInput( "testpackages.in", \
            "dev/log/testpackages2", \
            "$(TESTGAP) -L wsp.g", "true" );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackages.in; ./testpackages.in; rm testpackages.in )
	( rm wsp.g )

# check how packages are loaded
# - when all dependencies are loaded
# - when packages are loaded with `OnlyNeeded` option
testpackagesload: all
	$(MKDIR_P) dev/log
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageLoadTestsInput( "testpackagesload.in", \
            "dev/log/testpackagesload1", \
            "$(TESTGAP) -L wsp.g", false, false );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackagesload.in; ./testpackagesload.in > \
            `date -u +dev/log/testpackagesload1_%Y-%m-%d-%H-%M`; rm testpackagesload.in )
	( rm wsp.g )
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageLoadTestsInput( "testpackagesload.in", \
            "dev/log/testpackagesloadN1", \
            "$(TESTGAP) -L wsp.g", false, true );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackagesload.in; ./testpackagesload.in > \
            `date -u +dev/log/testpackagesloadN1_%Y-%m-%d-%H-%M`; rm testpackagesload.in )
	( rm wsp.g )
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAPauto) )
	( echo 'CreatePackageLoadTestsInput( "testpackagesload.in", \
            "testpackagesloadA", \
            "$(TESTGAPauto) -L wsp.g", true, false );'\
            | $(TESTGAPauto) -L wsp.g > /dev/null )
	( chmod 777 testpackagesload.in; ./testpackagesload.in > \
            `date -u +dev/log/testpackagesloadA_%Y-%m-%d-%H-%M`; rm testpackagesload.in )
	( rm wsp.g )
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAPauto) )
	( echo 'CreatePackageLoadTestsInput( "testpackagesload.in", \
            "testpackagesloadNA", \
            "$(TESTGAPauto) -L wsp.g", true, true );'\
            | $(TESTGAPauto) -L wsp.g > /dev/null )
	( chmod 777 testpackagesload.in; ./testpackagesload.in > \
            `date -u +dev/log/testpackagesloadNA_%Y-%m-%d-%H-%M`; rm testpackagesload.in )
	( rm wsp.g )

# Produce an overview of new variables defined by each package
testpackagesvars: all
	$(MKDIR_P) dev/log
	( echo 'ReadGapRoot( "tst/testutil.g" ); \
            SaveWorkspace( "wsp.g" );' | $(TESTGAP) )
	( echo 'CreatePackageVarsTestsInput( "testpackagesvars.in", \
            "dev/log/testpackagesvars", \
            "$(TESTGAP) -L wsp.g" );'\
            | $(TESTGAP) -L wsp.g > /dev/null )
	( chmod 777 testpackagesvars.in; ./testpackagesvars.in > \
            `date -u +dev/log/testpackagesvars_%Y-%m-%d-%H-%M`; rm testpackagesvars.in )
	( rm wsp.g )

# run teststandard.g twice:
# - without packages (except needed to run GAP)
# - with all packages loaded
teststandard: all
	$(MKDIR_P) dev/log
	( echo 'SetUserPreference("UseColorsInTerminal",false); \
          SetUserPreference("ReproducibleBehaviour", true); \
          ReadGapRoot( "tst/teststandard.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/teststandard1_%Y-%m-%d-%H-%M` )
	( echo 'SetUserPreference("UseColorsInTerminal",false); LoadAllPackages(); \
	      SetUserPreference("ReproducibleBehaviour", true); \
          ReadGapRoot( "tst/teststandard.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/teststandard2_%Y-%m-%d-%H-%M` )

# run testextra.g twice:
# - without packages (except needed to run GAP)
# - with all packages loaded
testextra: all
	$(MKDIR_P) dev/log
	( echo 'SetUserPreference("UseColorsInTerminal",false); \
          SetUserPreference("ReproducibleBehaviour", true); \
          ReadGapRoot( "tst/testextra.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/testextra1_%Y-%m-%d-%H-%M` )
	( echo 'SetUserPreference("UseColorsInTerminal",false); LoadAllPackages(); \
	      SetUserPreference("ReproducibleBehaviour", true); \
          ReadGapRoot( "tst/testextra.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/testextra2_%Y-%m-%d-%H-%M` )

# run testbugfix.g twice:
# - without packages (except needed to run GAP)
# - with all packages loaded
testbugfix: all
	$(MKDIR_P) dev/log
	( echo 'SetUserPreference("UseColorsInTerminal",false); \
	      SetUserPreference("ReproducibleBehaviour", true); \
          ReadGapRoot( "tst/testbugfix.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/testbugfix1_%Y-%m-%d-%H-%M` )
	( echo 'SetUserPreference("UseColorsInTerminal",false); LoadAllPackages(); \
	      SetUserPreference("ReproducibleBehaviour", true); \
          ReadGapRoot( "tst/testbugfix.g" );' | $(TESTGAP) | \
            tee `date -u +dev/log/testbugfix2_%Y-%m-%d-%H-%M` )

#
check: all
	$(TESTGAP) $(top_srcdir)/tst/testinstall.g

LIBGAPTESTS := $(addprefix tst/testlibgap/,basic api wscreate wsload)

# run a test in tst/testlibgap
tst/testlibgap/%: obj/tst/testlibgap/%.lo obj/tst/testlibgap/common.lo libgap.la
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $^ $(GAP_LIBS) -o $@

clean: clean-testlibgap
clean-testlibgap:
	rm -f ${LIBGAPTESTS}

# run all the tests in tst/testlibgap
testlibgap: ${LIBGAPTESTS}
	$(foreach v,$^, \
		echo "Running $(v) ..." && \
		$(v) -A -l $(top_srcdir) -q -T --nointeract >$(v).out && \
		diff $(top_srcdir)/$(v).expect $(v).out && ) :

KERNELTESTS := $(addprefix tst/testkernel/,dstruct)

# run a test in tst/testkernel
tst/testkernel/%: obj/tst/testkernel/%.lo libgap.la
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $^ $(GAP_LIBS) -o $@

clean: clean-testkernel
clean-testkernel:
	rm -f ${KERNELTESTS}

# run all the tests in tst/testkernel
testkernel: ${KERNELTESTS}
	$(foreach v,$^, \
		echo "Running $(v) ..." && \
		$(v) -A -l $(top_srcdir) -q -T --nointeract >$(v).out && \
		diff $(top_srcdir)/$(v).expect $(v).out && ) :

.PHONY: testlibgap testkernel

.PHONY: testinstall testmanuals testobsoletes teststandard testbugfix
.PHONY: testpackage testpackages testpackagesload testpackagesvars
.PHONY: check

########################################################################
# Bootstrap rules
########################################################################

# change PKG_BRANCH to stable-X.Y in the stable branch
PKG_BRANCH = stable-4.11
PKG_BOOTSTRAP_URL = https://github.com/gap-system/gap-distribution/releases/download/package-archives/
PKG_MINIMAL = packages-required-$(PKG_BRANCH).tar.gz
PKG_FULL = packages-$(PKG_BRANCH).tar.gz
DOWNLOAD = $(abs_srcdir)/cnf/download.sh

bootstrap-pkg-minimal:
	@if test -e pkg; then \
        echo "The pkg directory already exists. Please move or remove it to proceed."; \
    else \
        $(DOWNLOAD) $(PKG_BOOTSTRAP_URL)$(PKG_MINIMAL) && \
        mkdir pkg && \
        cd pkg && \
        tar xzf ../$(PKG_MINIMAL) ; \
    fi;

bootstrap-pkg-full:
	@if test -e pkg; then \
        echo "The pkg directory already exists. Please move or remove it to proceed" ; \
    else \
        $(DOWNLOAD) $(PKG_BOOTSTRAP_URL)$(PKG_FULL) && \
        mkdir pkg && \
        cd pkg && \
        tar xzf ../$(PKG_FULL) ; \
    fi;

.PHONY: bootstrap-pkg-minimal bootstrap-pkg-full

########################################################################
# Test runner rules
########################################################################

# TODO


########################################################################
# Track CFLAGS, CPPFLAGS, CXXFLAGS, LDFLAGS, LIBS, OBJS
#
# For each variable GAP_XYZ in the above list, we do the following:
# First, escape all single quotation marks in GAP_XYZ. Then compare
# GAP_XYZ with the content of file cnf/GAP-XYZ. Do nothing if they
# match. Otherwise, write GAP_XYZ into cnf/GAP-XYZ. By only writing
# something if there is a change, we avoid triggering unnecessary
# rebuilds.
#
# The files cnf/GAP-XYZ in turn now allow us to rebuild things if any of
# these variables change. Moreover, package build systems can extract
# relevant flags from them.
#
# This code is closely based on code from the git build system.
########################################################################

ESCAPED_CFLAGS = $(subst ','\'',$(GAP_CFLAGS))

cnf/GAP-CFLAGS: FORCE
	@mkdir -p cnf
	@FLAGS='$(ESCAPED_CFLAGS)'; \
	    if test x"$$FLAGS" != x"`cat cnf/GAP-CFLAGS 2>/dev/null`" ; then \
		echo >&2 "    * new C compiler flags"; \
		echo "$$FLAGS" >cnf/GAP-CFLAGS; \
            fi

ESCAPED_CXXFLAGS = $(subst ','\'',$(GAP_CXXFLAGS))

cnf/GAP-CXXFLAGS: FORCE
	@mkdir -p cnf
	@FLAGS='$(ESCAPED_CXXFLAGS)'; \
	    if test x"$$FLAGS" != x"`cat cnf/GAP-CXXFLAGS 2>/dev/null`" ; then \
		echo >&2 "    * new C++ compiler flags"; \
		echo "$$FLAGS" >cnf/GAP-CXXFLAGS; \
            fi

ESCAPED_CPPFLAGS = $(subst ','\'',$(GAP_CPPFLAGS))

cnf/GAP-CPPFLAGS: FORCE
	@mkdir -p cnf
	@FLAGS='$(ESCAPED_CPPFLAGS)'; \
	    if test x"$$FLAGS" != x"`cat cnf/GAP-CPPFLAGS 2>/dev/null`" ; then \
		echo >&2 "    * new preprocessor flags"; \
		echo "$$FLAGS" >cnf/GAP-CPPFLAGS; \
            fi

ESCAPED_LDFLAGS = $(subst ','\'',$(GAP_LDFLAGS))

cnf/GAP-LDFLAGS: FORCE
	@mkdir -p cnf
	@FLAGS='$(ESCAPED_LDFLAGS)'; \
	    if test x"$$FLAGS" != x"`cat cnf/GAP-LDFLAGS 2>/dev/null`" ; then \
		echo >&2 "    * new link flags"; \
		echo "$$FLAGS" >cnf/GAP-LDFLAGS; \
            fi

ESCAPED_LIBS = $(subst ','\'',$(GAP_LIBS))

cnf/GAP-LIBS: FORCE
	@mkdir -p cnf
	@FLAGS='$(ESCAPED_LIBS)'; \
	    if test x"$$FLAGS" != x"`cat cnf/GAP-LIBS 2>/dev/null`" ; then \
		echo >&2 "    * new library flags"; \
		echo "$$FLAGS" >cnf/GAP-LIBS; \
            fi

ESCAPED_OBJS = $(subst ','\'',$(OBJS))

cnf/GAP-OBJS: FORCE
	@mkdir -p cnf
	@FLAGS='$(ESCAPED_OBJS)'; \
	    if test x"$$FLAGS" != x"`cat cnf/GAP-OBJS 2>/dev/null`" ; then \
		echo >&2 "    * new object list"; \
		echo "$$FLAGS" >cnf/GAP-OBJS; \
            fi


########################################################################
# Handle version information
#
# The approach we use is based on what git.git does. It stores the
# generated version in a separate file cnf/GAP-VERSION-FILE, which makes
# it possible to cleverly handle rebuilding files that use the version.
# It also makes it possible to use version in non-C-code later one,
# should we need to.
########################################################################

GVF = $(srcdir)/cnf/GAP-VERSION-FILE

# the GAP-VERSION-FILE contains the raw version, nothing else
$(GVF): FORCE
	@cd $(srcdir) && $(SHELL) cnf/GAP-VERSION-GEN $(GAP_VERSION)
-include $(GVF)

# generate gen/gap_version.c
gen/gap_version.c: $(srcdir)/src/gap_version.c.in $(GVF) $(srcdir)/Makefile.rules
	@$(MKDIR_P) $(@D)
	$(QUIET_SED)sed -e "s/@GAP_VERSION@/$(GAP_VERSION)/" \
				    -e "s/@GAP_RELEASEDAY@/$(GAP_RELEASEDAY)/" \
					-e "s/@GAP_BUILD_VERSION@/$(GAP_BUILD_VERSION)/" \
					-e "s/@GAP_BUILD_DATETIME@/$(GAP_BUILD_DATETIME)/" < $< > $@


########################################################################
# Regenerate parts of the build system as needed.
# The following is based in parts on the corresponding automake rules,
# and in parts on an example in the autoconf manual.
########################################################################

ACLOCAL_M4 = $(srcdir)/aclocal.m4 $(wildcard $(srcdir)/cnf/m4/*.m4)
configure_deps = $(srcdir)/configure.ac $(ACLOCAL_M4)

config.status: $(srcdir)/configure
	$(SHELL) ./config.status --recheck

ifneq ($(MAINTAINER_MODE),no)
$(srcdir)/configure: $(configure_deps)
	@if command -v autoconf >/dev/null 2>&1 ; then \
	   echo "running autoconf" ; \
	   cd $(srcdir) && autoconf ; \
	 else \
	   echo "autoconf not available, proceeding with stale configure" ; \
	 fi
endif

gen/config.h: gen/stamp-h
	@if test ! -f $@; then rm -f gen/stamp-h; else :; fi
	@if test ! -f $@; then $(MAKE) gen/stamp-h; else :; fi

gen/stamp-h: $(srcdir)/src/config.h.in config.status
	@rm -f gen/stamp-h
	$(SHELL) ./config.status gen/config.h
	echo > $@

ifneq ($(MAINTAINER_MODE),no)
$(srcdir)/src/config.h.in: $(configure_deps) 
	@if command -v autoheader >/dev/null 2>&1 ; then \
	   echo "running autoheader" ; \
	   cd $(srcdir) && autoheader ; \
	   rm -f gen/stamp-h ; \
	 else \
	   echo "autoheader not available, proceeding with stale config.h" ; \
	 fi
	touch $@
endif

doc/versiondata: $(srcdir)/doc/versiondata.in config.status
	@$(SHELL) ./config.status $@

doc/make_doc: $(srcdir)/doc/make_doc.in config.status
	@$(SHELL) ./config.status $@

CITATION: $(srcdir)/CITATION.in config.status
	@$(SHELL) ./config.status $@

gac: $(srcdir)/cnf/gac.in config.status
	@$(SHELL) ./config.status $@

GNUmakefile: $(srcdir)/GNUmakefile.in config.status
	$(SHELL) ./config.status $@

libtool: config.status
	@$(SHELL) ./config.status $@

########################################################################
# Special .PHONY target: targets depending on it will always be
# considered dirty by target, hence are forced to be re-run
########################################################################
.PHONY: FORCE

########################################################################
# Makefile debugging trick:
# call print-VARIABLE to see the runtime value of any variable
########################################################################
print-%:
	@echo '$*=$($*)'
