########################################################################
#
# 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 CITATION doc/versiondata build/gap
.PHONY: all

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


########################################################################
# Developer helper targets
########################################################################
test_release_notes:
	cd dev/releases && python3 -m pytest test_release_notes.py
.PHONY: test_release_notes


########################################################################
# 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
SOURCES += src/calls.c
SOURCES += src/code.c
SOURCES += src/collectors.cc
SOURCES += src/compiler.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/finfield.c
SOURCES += src/funcs.c
SOURCES += src/gap.c
SOURCES += src/gaptime.c
SOURCES += build/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_builtin.c
SOURCES += src/modules.c
SOURCES += src/objcftl.c
SOURCES += src/objects.c
SOURCES += src/objfgelm.cc
SOURCES += src/objpcgel.cc
SOURCES += src/objset.c
SOURCES += src/opers.cc
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/sha256.c
SOURCES += src/set.c
SOURCES += src/stats.c
SOURCES += src/streams.c
SOURCES += src/stringobj.c
SOURCES += src/symbols.c
SOURCES += src/syntaxtree.c
SOURCES += src/sysfiles.c
SOURCES += src/sysroots.c
SOURCES += src/sysstr.c
SOURCES += src/system.c
SOURCES += src/tietze.c
SOURCES += src/tracing.c
SOURCES += src/trans.cc
SOURCES += src/trycatch.c
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/cpu.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

# allow overriding ffdata.c with a fixed version for cross compilation
ifneq ("$(wildcard $(srcdir)/src/ffdata.c)","")
SOURCES += src/ffdata.c
else
SOURCES += build/ffdata.c
endif

# allow overriding ffdata.h with a fixed version for cross compilation
ifneq ("$(wildcard $(srcdir)/src/ffdata.h)","")
FFDATA_H := $(srcdir)/src/ffdata.h
else
FFDATA_H := $(builddir)/build/ffdata.h
endif


# deal with C sources generated by gac
SOURCES_NOCOMP := $(SOURCES)
SOURCES_NOCOMP += src/compstat_empty.c
SOURCES_NOCOMP += src/main.c

SOURCE_C_OPER1 := $(builddir)/build/c_oper1.c
SOURCE_C_TYPE1 := $(builddir)/build/c_type1.c
ifeq ($(HPCGAP),yes)
  ifneq ("$(wildcard $(srcdir)/src/hpc/c_oper1.c)","")
  SOURCE_C_OPER1 := $(srcdir)/src/hpc/c_oper1.c
  endif

  ifneq ("$(wildcard $(srcdir)/src/hpc/c_type1.c)","")
  SOURCE_C_TYPE1 := $(srcdir)/src/hpc/c_type1.c
  endif
else
  ifneq ("$(wildcard $(srcdir)/src/c_oper1.c)","")
  SOURCE_C_OPER1 := $(srcdir)/src/c_oper1.c
  endif

  ifneq ("$(wildcard $(srcdir)/src/c_type1.c)","")
  SOURCE_C_TYPE1 := $(srcdir)/src/c_type1.c
  endif
endif

SOURCES += $(SOURCE_C_OPER1) $(SOURCE_C_TYPE1)
SOURCES += src/compstat.c

SOURCES_ALL := $(SOURCES)
SOURCES_ALL += src/compstat_empty.c
SOURCES_ALL += src/main.c


########################################################################
#
########################################################################

SYSINFO_CC := $(CC)
SYSINFO_CXX := $(CXX)

########################################################################
# Preprocessor flags
#
# GAP_CPPFLAGS is for the GAP build system, while SYSINFO_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 =
SYSINFO_CPPFLAGS =

# First add include paths

# The "build/" directory contains generated header files and thus is
# placed into the list of include directories.
GAP_CPPFLAGS += -I$(builddir)/build
SYSINFO_CPPFLAGS += -I$(abs_builddir)/build

# The other source files are bundled and exported through the few headers in
# the `src/extra/` directory. We deliberately do not add `src/` itself as an
# include directory to improve portability: it helps avoid clashes between our
# headers and system headers (e.g. for `io.h` this would otherwise be a
# problem on MinGW).
GAP_CPPFLAGS += -I$(srcdir)/src/extra
SYSINFO_CPPFLAGS += -I$(abs_srcdir)/src/extra

# Add GAP_DEFINES (from autoconf, contains -D flags)
GAP_CPPFLAGS += $(GAP_DEFINES)
SYSINFO_CPPFLAGS += $(GAP_DEFINES)

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

# For packages, only libatomic headers are needed, as they are
# used in hpc/atomic.h
SYSINFO_CPPFLAGS += $(LIBATOMIC_OPS_CPPFLAGS)

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


########################################################################
# C compiler flags
########################################################################
GAP_CFLAGS = $(ABI_CFLAGS)
SYSINFO_CFLAGS = $(ABI_CFLAGS)

GAP_CFLAGS += $(PTHREAD_CFLAGS)
SYSINFO_CFLAGS += $(PTHREAD_CFLAGS)

GAP_CFLAGS += $(JULIA_CFLAGS) # not added to SYSINFO_CFLAGS

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


########################################################################
# C++ compiler flags
########################################################################
GAP_CXXFLAGS = $(ABI_CFLAGS)
SYSINFO_CXXFLAGS = $(ABI_CFLAGS)

GAP_CXXFLAGS += $(PTHREAD_CFLAGS)
SYSINFO_CXXFLAGS += $(PTHREAD_CFLAGS)

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


########################################################################
# Linker flags
########################################################################
GAP_LDFLAGS = $(ABI_CFLAGS)
SYSINFO_LDFLAGS = $(ABI_CFLAGS)

# 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)

GAP_LDFLAGS += $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)

# Finally add user provided flags
GAP_LDFLAGS += $(LDFLAGS)
SYSINFO_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)


########################################################################
# gac flags
########################################################################

#
# Determine flags for building kernel extensions for use in GAC
#
# For now we basically support GCC and clang, on Linux/macOS/Windows,
# and as a side effect also some other systems such as FreeBSD.
# Support for other compilers or operating systems will require some
# extra tweaks.
#
ifneq (,$(findstring cygwin,$(host_os)))
  GAC_CFLAGS =
  GAC_LDFLAGS = -shared -Wl,$(abs_builddir)/bin/$(GAPARCH)/gap.dll -Wl,--enable-auto-image-base
  # Note: the above won't be correct after "make install"; but then I am not
  # sure we care about "make install" on Cygwin, so I am not going to work on
  # this until someone specifically asks for it (and even then I'll require
  # that person to help test it)
else
  ifneq (,$(findstring darwin,$(host_os)))
    GAC_CFLAGS = -fno-common
    GAC_LDFLAGS = -bundle -undefined dynamic_lookup -Wl,-no_fixup_chains
  else
    GAC_CFLAGS = -fPIC
    GAC_LDFLAGS = -shared -fPIC
  endif
endif


########################################################################
# additional settings for use in sysinfo.gap
########################################################################

# paths to gap and gac executable
SYSINFO_GAP = $(abs_builddir)/gap
SYSINFO_GAC = $(abs_builddir)/gac


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

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

OBJS_NOCOMP = $(patsubst %,build/obj/%.o,$(SOURCES_NOCOMP))

########################################################################
# 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       $< => $(OBJFILE)";
QUIET_CXX     = @echo "   CXX     $< => $(OBJFILE)";
QUIET_LINK    = @echo "   LINK    $@";
QUIET_SED     = @echo "   SED     $< => $@";
QUIET         = @
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 :We instruct the compiler via some flags to
# create a "build/deps/FOO.d" file whenever 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). Then, to
# let make track the header dependencies, we include the *.d files.
#
# For a detailed explanation of a very similar scheme, read this:
# https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
#
########################################################################

# List of all dependency tracking files, derived from SOURCES; the use of
# wildcard ensures that only existing files are listed
DEPFILES = $(wildcard $(patsubst %,build/deps/%.d,$(SOURCES_ALL)))

# Include the dependency tracking files
-include $(DEPFILES)

# the name of the .d and .o file generated by one of our compiler
# rules; you may wonder why we don't just use $@ here: this is needed
# because our compile rules have two targets, the .o and the .d file;
# and the value of $@ will be whichever of the two files triggered the
# compiler rule, so we cannot use it directly
DEPFILE = build/deps/$(*D)/$(<F).d
OBJFILE = build/obj/$(*D)/$(<F).o

# 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 $(OBJFILE) -MMD -MP -MF $(DEPFILE)


########################################################################
# Compiler rules
#
# Note that these rules have two targets, the .o and the .d file; this
# models their relationship accurately and allows us to deal with some
# corner cases, e.g. when switching branches after a file got renamed;
# unfortunately it also means we can't just use $@ here (see comments on
# DEPFILE and OBJFILE above)
########################################################################

obj_deps = build/config.h build/version.h $(FFDATA_H)


# 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 need to interface with C++ code in
# libraries that use exceptions.
build/obj/%.cc.o: %.cc cnf/GAP-CXXFLAGS cnf/GAP-CPPFLAGS $(obj_deps)
	@$(MKDIR_P) build/obj/$(*D) build/deps/$(*D)
	$(QUIET_CXX)$(CXX) $(DEPFLAGS) $(GAP_CXXFLAGS) -fno-exceptions -fno-rtti $(WARN_CXXFLAGS) $(GAP_CPPFLAGS) -c $< -o $(OBJFILE)
	@echo "$<:" >> $(DEPFILE)

# Build rule for C source files
build/obj/%.c.o: %.c cnf/GAP-CFLAGS cnf/GAP-CPPFLAGS $(obj_deps)
	@$(MKDIR_P) build/obj/$(*D) build/deps/$(*D)
	$(QUIET_CC)$(CC) $(DEPFLAGS) $(GAP_CFLAGS) $(WARN_CFLAGS) $(GAP_CPPFLAGS) -c $< -o $(OBJFILE)
	@echo "$<:" >> $(DEPFILE)

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

LINK=$(CC)
GAP_INSTALL_EXTRAFLAGS =
SHLIB_MAJOR = $(GAP_KERNEL_MAJOR_VERSION)
ifneq (,$(findstring cygwin,$(host_os)))
  SHLIB_EXT=.dll
  LIBGAP_FULL = libgap$(SHLIB_EXT)

  LINK_SHLIB_FLAGS = -shared -Wl,--enable-auto-image-base -Wl,--out-implib,libgap.dll.a
else ifneq (,$(findstring darwin,$(host_os)))
  SHLIB_EXT=.dylib
  LIBGAP_FULL = libgap.$(SHLIB_MAJOR)$(SHLIB_EXT)
  LIBGAP_COMPAT_VER = $(shell expr $(GAP_KERNEL_MAJOR_VERSION) + 1 )
  LIBGAP_CURRENT_VER = $(LIBGAP_COMPAT_VER).$(GAP_KERNEL_MINOR_VERSION)
  LINK_SHLIB_FLAGS = -dynamiclib
  LINK_SHLIB_FLAGS += -compatibility_version $(LIBGAP_COMPAT_VER)
  LINK_SHLIB_FLAGS += -current_version $(LIBGAP_CURRENT_VER)
  LINK_SHLIB_FLAGS += -Wl,-single_module
  LINK_SHLIB_FLAGS += -Wl,-headerpad_max_install_names
  GAP_INSTALL_EXTRAFLAGS = -Wl,-headerpad_max_install_names

  GAP_CPPFLAGS += -DPIC
  GAP_CFLAGS += -fno-common
  GAP_CXXFLAGS += -fno-common
else
  # Note: the following was tested on Linux -- patches making this work better
  # on e.g. FreeBSD/OpenBSD/... are highly welcome
  SHLIB_EXT=.so
  LIBGAP_FULL = libgap$(SHLIB_EXT).$(SHLIB_MAJOR)
  LINK_SHLIB_FLAGS = -shared -fPIC -DPIC -Wl,-soname,$(LIBGAP_FULL)

  GAP_CPPFLAGS += -DPIC
  GAP_CFLAGS += -fPIC
  GAP_CXXFLAGS += -fPIC
  GAP_LDFLAGS += -Wl,--export-dynamic
endif

ifneq (,$(findstring darwin,$(host_os)))
INSTALL_NAME_TOOL = @install_name_tool
else
INSTALL_NAME_TOOL = @echo > /dev/null
endif

libgap: libgap$(SHLIB_EXT) $(LIBGAP_FULL)
.PHONY: libgap

# Linking rule and dependencies for libgap
$(LIBGAP_FULL): $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) -o $@ $(LINK_SHLIB_FLAGS) $(GAP_LDFLAGS) $(OBJS) $(GAP_LIBS)

ifneq (,$(findstring cygwin,$(host_os)))

# 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: libgap$(SHLIB_EXT)
	@$(MKDIR_P) bin/$(GAPARCH)
	cp $< $@

# build rule for the main gap executable
gap$(EXEEXT): build/obj/src/main.c.o libgap$(SHLIB_EXT) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) -Wl,--export-all-symbols $< $(GAP_LIBS) -L${abs_builddir} -lgap -o $@
	@( if which peflags > /dev/null ; then peflags --cygwin-heap=2048 gap$(EXEEXT) ; fi )

else

# create a symlink  libgap.so -> libgap.so.9   resp.  libgap.dylib -> libgap.9.dylib
libgap$(SHLIB_EXT): $(LIBGAP_FULL)
	@rm -f $@
	ln -sf $< $@

# build rule for the main gap executable
gap$(EXEEXT): build/obj/src/main.c.o $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $< $(OBJS) $(GAP_LIBS) -o $@

# generate a special main.c which sets SYS_DEFAULT_PATHS and then includes
# regular main.c; this is used to build the `gap-install` binary
build/main.c: sysinfo.gap
	@echo "#define SYS_DEFAULT_PATHS \"$(libdir)/gap;$(datarootdir)/gap\"" > $@
	@echo "#include \"$(abs_srcdir)/src/main.c\"" >> $@

# build rule for the gap executable used by the `install-bin` target
build/gap-install: build/obj/build/main.c.o libgap$(SHLIB_EXT) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $(GAP_INSTALL_EXTRAFLAGS) $< $(GAP_LIBS) -L${abs_builddir} -lgap -o $@
	$(INSTALL_NAME_TOOL) -change $(LIBGAP_FULL) $(libdir)/$(LIBGAP_FULL) $@

endif

########################################################################
# Rules for rebuilding C code generated from GAP code via gac.
########################################################################

build/gap-nocomp$(EXEEXT): $(OBJS_NOCOMP) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $(OBJS_NOCOMP) $(GAP_LIBS) -o $@

build/c_%.c: $(srcdir)/lib/%.g build/gap-nocomp$(EXEEXT)
	@$(MKDIR_P) $(@D)
	@"$(abs_srcdir)"/cnf/gap-c-gen.sh $< $@ $(basename $(notdir $<)) build/gap-nocomp$(EXEEXT)
.PRECIOUS: build/c_%.c


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

ffgen: $(srcdir)/etc/ffgen.c build/config.h
	$(QUIET_CC)$(CC) -Wall -Wextra $(GAP_CPPFLAGS) $< -o $@

build/ffdata.h build/ffdata.c: ffgen
	./ffgen -b build/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 GNUmakefile
	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 tags
	rm -rf TAGS

clean:
	rm -rf bin/$(GAPARCH)
	rm -rf build
	rm -rf extern/build extern/install
	rm -f bin/gap.sh sysinfo.gap*
	rm -f gap$(EXEEXT) gac ffgen
	rm -f libgap$(SHLIB_EXT) $(LIBGAP_FULL)
	rm -f libgap.pc
	rm -rf .libs
	rm -f doc/wsp.g
	rm -f cnf/GAP-*
	rm -f configure~ src/config.h.in~
	rmdir bin cnf dev doc extern src 2>/dev/null || : # remove dirs if they are now empty

cleanall: clean distclean clean-doc
	rm -f src/config.h.in

.PHONY: clean distclean cleanall


########################################################################
# Rules for 'make install'
#
#
# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING
#
# The following code has not yet been tested very extensively, so use at your
# own peril -- that said, if you find any issues with them NOT COVERED BELOW
# or have suggestions for improvements, please contact us.
#
# The main thing that is missing (no need to inform us about it) is that it
# does not install packages -- doing so is tricky, depending on what
# assumptions one is willing to make or require; we may never support this
# *here*; instead individual packages may gain a `make install`. How to
# go about this exactly has not yet been decided.
#
########################################################################

install: install-bin install-doc install-gaproot install-sysinfo install-headers install-libgap
	@echo "+--------------------------------------------------------------------------+"
	@echo "| WARNING, 'make install' support is still experimental, and may be buggy. |"
	@echo "| It also does not take care of installing GAP packages (and may never).   |"
	@echo "|                                                                          |"
	@echo "| If you observe any issues with 'make install', please report them to us  |"
	@echo "| via support@gap-system.org or https://github.com/gap-system/gap/issues   |"
	@echo "+--------------------------------------------------------------------------+"

# auxiliary target to prevent race conditions when creating certain directories
install-dirs:
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap
	$(INSTALL) -d -m 0755 $(DESTDIR)$(libdir)/gap
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/pkg

install-bin: build/gap-install
	# install a special build of gap with SYS_DEFAULT_PATHS set suitably
	$(INSTALL) -d -m 0755 $(DESTDIR)$(bindir)
	$(INSTALL) -m 0755 build/gap-install $(DESTDIR)$(bindir)/gap
	# install gac
	sed -e "s;@SYSINFO_GAPROOT@;$(libdir)/gap;" < $(srcdir)/cnf/gac.in > $(DESTDIR)$(bindir)/gac
	chmod 0755 $(DESTDIR)$(bindir)/gac

# TODO: should 'install-doc' depend on the 'doc' target? but that target is phony
# and will re-run each time it is invoked, which is not really what we want.
install-doc: install-dirs
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/doc
	$(INSTALL) -m 0644 $(srcdir)/doc/gapmacro.tex $(DESTDIR)$(datarootdir)/gap/doc/
	$(INSTALL) -m 0644 $(srcdir)/doc/manualindex $(DESTDIR)$(datarootdir)/gap/doc/
	for book in ref tut hpc ; do \
		$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/doc/$$book ; \
		for ext in css html js txt pdf six lab; do \
			$(INSTALL) -m 0644  $(srcdir)/doc/$$book/*.$$ext $(DESTDIR)$(datarootdir)/gap/doc/$$book/ ; \
		done \
	done

# install most of the GAP "root" directory (containing arch independent files),
# with a few exceptions: the `doc` dir is installed by `install-doc`, and
# `install-sysinfo` creates `sysinfo.gap`
install-gaproot: install-dirs CITATION
	# install GAP library files
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/hpcgap
	for dir in grp lib lib/hpc hpcgap/lib hpcgap/lib/hpc hpcgap/lib/distributed ; do \
	  $(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/$$dir ; \
	  $(INSTALL) -m 0644 $(srcdir)/$$dir/*.g* $(DESTDIR)$(datarootdir)/gap/$$dir ; \
	done

	# install various files in the root dir
	$(INSTALL) -m 0644 CITATION $(DESTDIR)$(datarootdir)/gap/
	$(INSTALL) -m 0644 $(srcdir)/CONTRIBUTING.md $(DESTDIR)$(datarootdir)/gap/
	$(INSTALL) -m 0644 $(srcdir)/COPYRIGHT $(DESTDIR)$(datarootdir)/gap/
	$(INSTALL) -m 0644 $(srcdir)/INSTALL.md $(DESTDIR)$(datarootdir)/gap/
	$(INSTALL) -m 0644 $(srcdir)/LICENSE $(DESTDIR)$(datarootdir)/gap/
	$(INSTALL) -m 0644 $(srcdir)/README.md $(DESTDIR)$(datarootdir)/gap/

	# install helpers for developers
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/etc
	$(INSTALL) -m 0755 $(srcdir)/etc/convert.pl $(DESTDIR)$(datarootdir)/gap/etc/
	$(INSTALL) -d -m 0755 $(DESTDIR)$(datarootdir)/gap/etc/vim
	$(INSTALL) -m 0644 $(srcdir)/etc/vim/*.* $(DESTDIR)$(datarootdir)/gap/etc/vim/


# the following lines adjust variables for the installed sysinfo.gap
install-sysinfo: SYSINFO_CPPFLAGS = -I${includedir}/gap/extra $(GAP_DEFINES)
install-sysinfo: SYSINFO_LDFLAGS = $(ABI_CFLAGS)
install-sysinfo: SYSINFO_GAP = $(bindir)/gap
install-sysinfo: SYSINFO_GAC = $(bindir)/gac
install-sysinfo: GMP_PREFIX =
install-sysinfo: install-dirs
	@echo "$$sysinfo_gap" > $(DESTDIR)$(libdir)/gap/sysinfo.gap
	chmod 0644 $(DESTDIR)$(libdir)/gap/sysinfo.gap

# install kernel headers
install-headers: $(FFDATA_H) build/version.h
	$(INSTALL) -d -m 0755 $(DESTDIR)$(includedir)/gap
	$(INSTALL) -m 0644 $(srcdir)/src/*.h $(DESTDIR)$(includedir)/gap
	$(INSTALL) -m 0644 $(FFDATA_H) $(DESTDIR)$(includedir)/gap
	$(INSTALL) -m 0644 $(builddir)/build/version.h $(DESTDIR)$(includedir)/gap
	$(INSTALL) -d -m 0755 $(DESTDIR)$(includedir)/gap/hpc
	$(INSTALL) -m 0644 $(srcdir)/src/hpc/*.h $(DESTDIR)$(includedir)/gap/hpc
	$(INSTALL) -d -m 0755 $(DESTDIR)$(includedir)/gap/extra
	$(INSTALL) -m 0644 $(srcdir)/src/extra/*.h $(DESTDIR)$(includedir)/gap/extra

install-libgap: install-dirs $(LIBGAP_FULL) libgap.pc
	$(INSTALL) -d -m 0755 $(DESTDIR)$(libdir)
	$(INSTALL) -m 0644 $(LIBGAP_FULL) $(DESTDIR)$(libdir)
	ln -sf $(LIBGAP_FULL) $(DESTDIR)$(libdir)/libgap$(SHLIB_EXT)
	$(INSTALL_NAME_TOOL) -id $(libdir)/$(LIBGAP_FULL) $(DESTDIR)$(libdir)/$(LIBGAP_FULL)
	$(INSTALL) -d -m 0755 $(DESTDIR)$(libdir)/pkgconfig
	$(INSTALL) -m 0644 libgap.pc $(DESTDIR)$(libdir)/pkgconfig


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

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


# master target for external dependencies / subprojects
EXTERN_FILES =

# pass on some settings to external dependencies / subprojects which use
# autoconf; this is helpful for cross compilation
EXTERN_CONFIGFLAGS := \
	CC="$(CC)" \
	CXX="$(CXX)" \
	--build="$(build)" \
	--host="$(host)"

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

GMP_BUILDDIR := extern/build/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" \
	$(EXTERN_CONFIGFLAGS) \
	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)

ifneq (,$(findstring cygwin,$(host_os)))
$(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

.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) $(srcdir)/cnf/build-extern.sh libatomic_ops "$(abs_srcdir)/hpcgap/extern/libatomic_ops" \
	$(EXTERN_CONFIGFLAGS) \
	--disable-static \
	--enable-shared

.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: refactor code which handles dependencies like GMP, Boehm, libatomic,
# to reduce code duplication.

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) $(srcdir)/cnf/build-extern.sh gc "$(abs_srcdir)/hpcgap/extern/gc" \
	$(EXTERN_CONFIGFLAGS) \
	ATOMIC_OPS_CFLAGS="$(LIBATOMIC_OPS_CPPFLAGS)" \
	ATOMIC_OPS_LIBS="$(LIBATOMIC_OPS_LDFLAGS)" \
	--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)
$(OBJS_NOCOMP): $(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!

# This file exists for use by the GAP compiler `gac` and also by the build
# systems of GAP packages.
#
# It is deliberately written in a way that makes it usable from shell scripts
# *and* Makefiles: It only consists of comment lines like this one, starting
# with a '#'; blank linkes; or lines containing assignments of the form
#  VARIABLE_NAME="CONTENT"


# GAParch: the "architecture" of this GAP build. First comes the result of
# `config.guess`. Next one of the strings "-default", "-hpcgap", "-julia" to
# indicate various major build variants of GAP. Then the ABI (32 or 64). Then
# a string of the form '-kvNNN' where NNN is the GAP kernel major version.
#
# Used to decide where to load package binaries from (to support installing
# binaries for multiple architectures in parallel on a single computer).
GAParch=$(GAPARCH)

# GAP_ABI: indicates whether GAP was built in 32 or 64 bit mode.
# Deprecated, may be removed in a future GAP release.
# Possible values: 32, 64
GAP_ABI=$(ABI)

# GAP_HPCGAP: indicates whether HPC-GAP support was compiled in.
# Possible values: yes, no
GAP_HPCGAP=$(HPCGAP)

# GAP_VERSION: GAP version.
GAP_VERSION="$(GAP_VERSION)"

# GAP_BUILD_VERSION: GAP build version. For releases, this is identical to
# GAP_VERSION. For development builds, it is the version followed by extra
# data indicating which git commit the build was based on
GAP_BUILD_VERSION="$(GAP_BUILD_VERSION)"

# GAP_KERNEL_{MAJOR,MINOR}_VERSION: the GAP kernel version (both integer values).
GAP_KERNEL_MAJOR_VERSION=$(GAP_KERNEL_MAJOR_VERSION)
GAP_KERNEL_MINOR_VERSION=$(GAP_KERNEL_MINOR_VERSION)

# GAP: path to the `gap` executable (may be a shell script)
GAP="$(SYSINFO_GAP)"

# GAC: path to the `gac` executable (may be a shell script)
GAC="$(SYSINFO_GAC)"

# File extension used by object files created by GAC
GAP_OBJEXT=o

# Build flags for use by `gac` resp. package build systems: these correspond to
# the usual variables as used by e.g. autotools, with the added prefix `GAP_`.
GAP_CC="$(SYSINFO_CC)"
GAP_CXX="$(SYSINFO_CXX)"
GAP_CFLAGS="$(SYSINFO_CFLAGS)"
GAP_CXXFLAGS="$(SYSINFO_CXXFLAGS)"
GAP_CPPFLAGS="$(SYSINFO_CPPFLAGS)"
GAP_LDFLAGS="$(SYSINFO_LDFLAGS)"

# Extra flags for use by `gac`
GAC_CFLAGS="$(GAC_CFLAGS)"
GAC_LDFLAGS="$(GAC_LDFLAGS)"

# For packages: the search prefix for GMP used by GAP
# (this is left empty when none was specified, or when
# GAP is installed via 'make install')
GMP_PREFIX="$(GMP_PREFIX)"
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" > $@


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

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

########################################################################
# 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
	rm -f doc/ref/user_pref_list.xml

# 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
	cd doc/ref && $(TESTGAP) testconsistency.g

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

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

# citests runs a subset of the tests run by CI -- this is SLOW and still doesn't
# quite cover everything (e.g. we don't test out-of-tree builds and `make install`)
citests: all
	SRCDIR=$(abs_srcdir) dev/ci.sh testmockpkg testspecial test-compile testlibgap testkernel testworkspace

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

build-testlibgap: ${LIBGAPTESTS}

# run a test in tst/testlibgap
tst/testlibgap/%: build/obj/tst/testlibgap/%.c.o build/obj/tst/testlibgap/common.c.o libgap$(SHLIB_EXT)
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) -Wl,-rpath,$(abs_builddir) $^ $(GAP_LIBS) -o $@

clean: clean-testlibgap
clean-testlibgap:
	rm -f ${LIBGAPTESTS}
	rm -f $(addsuffix .out,$(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 && ) :

# test libgap's pkg-config's libgap version reporting
testpkgconfigversion: install-libgap
	$(eval PKG_REPORTED_VERSION := $(shell PKG_CONFIG_PATH=$(DESTDIR)$(libdir)/pkgconfig pkg-config --modversion libgap))
	@echo "pkg-config reports version $(PKG_REPORTED_VERSION)"
	@if [ $(PKG_REPORTED_VERSION) != $(GAP_VERSION) ] ; then \
	   echo "reported version does not match GAP_VERSION = $(GAP_VERSION)" ; \
	   exit 1 ; \
	fi

# test libgap's pkg-config's libgap flags fetching
testpkgconfigbuild: install-libgap install-headers
	$(eval PKG_REPORTED_CFLAGS := $(shell PKG_CONFIG_PATH=$(DESTDIR)$(libdir)/pkgconfig pkg-config --cflags libgap | cut -d' ' -f 1)/gap)
	$(eval PKG_REPORTED_LDFLAGS := $(shell PKG_CONFIG_PATH=$(DESTDIR)$(libdir)/pkgconfig pkg-config --libs libgap))
	$(eval v := "tst/testlibgap/basic")
	$(eval com := "tst/testlibgap/common")
	$(CC) -c $(v).c -o $(v).o $(PKG_REPORTED_CFLAGS)
	$(CC) -c $(com).c -o $(com).o $(PKG_REPORTED_CFLAGS)
	$(QUIET_LINK)$(LINK) $(v).o -o $(v) $(com).o $(PKG_REPORTED_LDFLAGS) -Wl,-rpath,$(abs_builddir)
	$(v) -A -l $(top_srcdir) -q -T --nointeract >$(v).out && \
        diff $(top_srcdir)/$(v).expect $(v).out


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

build-testkernel: ${KERNELTESTS}

# run a test in tst/testkernel
tst/testkernel/%: build/obj/tst/testkernel/%.c.o libgap$(SHLIB_EXT)
	$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) -Wl,-rpath,$(abs_builddir) $^ $(GAP_LIBS) -o $@

clean: clean-testkernel
clean-testkernel:
	rm -f ${KERNELTESTS}
	rm -f $(addsuffix .out,$(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 build-testlibgap build-testkernel

.PHONY: testpkgconfigbuild testpkgconfigversion

.PHONY: check citests

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

# change PKG_BRANCH to stable-X.Y in the stable branch
PKG_BRANCH = master
PKG_BOOTSTRAP_URL = https://github.com/gap-system/PackageDistro/releases/download/latest/
PKG_MINIMAL = packages-required.tar.gz
PKG_FULL = packages.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 = cnf/GAP-VERSION-FILE

# the GAP-VERSION-FILE contains the raw version, nothing else
$(GVF): FORCE
	@$(MKDIR_P) $(@D)
	@$(SHELL) $(srcdir)/cnf/gap-version-gen.sh $(GAP_VERSION)
-include $(GVF)

# (re)generate build/version.c
build/version.c: $(srcdir)/src/version.c.in $(srcdir)/Makefile.rules $(GVF)
	@$(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)/" \
		< $< > $@

# (re)generate build/version.h ; only regenerate if the content actually
# changed, to avoid unnecessary recompilation
build/version.h: $(srcdir)/src/version.h.in $(srcdir)/Makefile.rules
	@$(MKDIR_P) $(@D)
	$(QUIET)sed \
		-e "s/@GAP_KERNEL_MAJOR_VERSION@/$(GAP_KERNEL_MAJOR_VERSION)/" \
		-e "s/@GAP_KERNEL_MINOR_VERSION@/$(GAP_KERNEL_MINOR_VERSION)/" \
		< $< > $@.tmp
	$(QUIET)if ! test -f $@ || ! cmp $@ $@.tmp ; then mv $@.tmp $@ ; fi


########################################################################
# 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

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

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

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

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 build/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
	sed -e "s;@SYSINFO_GAPROOT@;$(abs_top_builddir);" < $< > $@
	chmod a+x $@

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

build/gap:
	@mkdir -p $(@D) && ln -sf $(abs_srcdir)/src build/gap

########################################################################
# 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 '$*=$($*)'
