#!/usr/bin/make # help out emacs
#
# Top-level autosetup-filtered Makefile for libfossil. This particular
# build is for Unix platforms with GNU Make 4+.
all:
ROOT.MAKEFILE := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
DISTCLEAN.root += $(ROOT.MAKEFILE)
TOP_DIR := $(patsubst %/,%,$(dir $(ROOT.MAKEFILE)))

#ShakeNMake.CISH_SOURCES := $(wildcard *.c) $(wildcard $(SRC.DIR)/*.c)

########################################################################
# Some common vars used by shakenmake.make and/or the sub-makes
# (make-*.make).
DIR.top := @srcdir@
DIR.src := $(DIR.top)/src
DIR.client := $(DIR.top)/client
DIR.tools := $(DIR.top)/tools
DIR.include := $(DIR.top)/include
DIR.bindings := $(DIR.top)/bindings
DIR.f-apps := $(DIR.top)/f-apps
DIR.sql := $(DIR.top)/sql

LIB_CURSES := @LIB_CURSES@
CFLAGS_CURSES := @CFLAGS_CURSES@
include config.make
ShakeNMake.USE_MKDEPS := 0
include shakenmake.make


########################################################################
# Dependencies generation.
deps:
########################################################################
# $(eval $(call ADD_C_DEPS...))
# $1 = deps set name: must match the X part of one of the project's
#      rule set names.
# $2 = the list of .c/.cpp files to generate deps for.
#
# Creates and imports deps file named $(DEPS.$(1).make).
#
# Optionally set DEPS.$(1).EXTRADEPS to any extra files the generated
# deps file should depend on.
#
# Optionally set DEPS.$(1).INCDIRS to any additional directories which
# should be added to the -I CPPFLAGS. The directories containing the
# files in $(2) are automatically added, as are $(PROJECT_INCLUDES).
########################################################################
# C_DEPS_MAKEFILES = list of makefiles all .o files depend on.
PROJECT_INCLUDES := -I$(DIR.include) -I$(DIR.include)/fossil-scm
C_DEPS_MAKEFILES := $(ROOT.MAKEFILE) auto.make shakenmake.make
MKCDEP.BIN := $(DIR.tools)/mkcdep
# ^^^ Frankly, this does a better job than (gcc -e -E ...) and is tons
# faster. It is less portable, though.
$(MKCDEP.BIN): $(MKCDEP.BIN).c
	$(CC) -o $@ $^
CLEAN.root += $(MKCDEP.BIN)
define ADD_C_DEPS
DEPS.$(1).make := .deps.$(1).make
CLEAN.$(1) += $$(DEPS.$(1).make)
ifneq (1,$(MAKING_CLEAN))
$$(DEPS.$(1).make): $(MKCDEP.BIN) $$(wildcard make-$(1).make) $$(DEPS.$(1).EXTRADEPS) $(2)
	@echo "Generating deps set [$(1)] [$$@]..."; \
	$$(MKCDEP.BIN) $$(PROJECT_INCLUDES) \
		$$(patsubst %,-I%,$$(sort $$(dir $(2)))) \
		$$(patsubst %,-I%,$$(DEPS.$(1).INCDIRS)) \
		-- $(2) > $$@
deps-$(1): $$(DEPS.$(1).make)
deps: deps-$(1)
$$(eval -include $$(DEPS.$(1).make))
endif
endef
# ^^^ ADD_C_DEPS
########################################################################

########################################################################
# Transform schema SQL files into source form. We don't use fossil(1)'s
# approach because it relies on unspecified length limits on C string
# literals. Yeah, it works, but i'm funny about the C Standard.
#include $(TOP_SRCDIR_REL)/tools.make
BIN.TEXT2C := $(DIR.tools)/text2c
$(BIN.TEXT2C): $(DIR.tools)/text2c.c
	cc $< -o $@
DISTCLEAN.root += $(BIN.TEXT2C)

########################################################################
# Transforms file $(2) to $(1).c in the form of a byte array and
# accessor function.
define FILE2C
$(2):
$(1).c: $(2) $$(BIN.TEXT2C) $(PACKAGE.C_DEPS.MAKEFILES)
ifneq (1,$(MAKING_CLEAN))
	@echo "Creating $$@ from $(2)..."; \
	{ \
		echo '/** @page page_$$(notdir $1) $$(notdir $(2))'; echo; \
    echo 'Binary form of file $(2).'; echo; \
		echo '*/'; \
		$$(BIN.TEXT2C) fsl_$$(notdir $1) < $(2); \
		echo '/* end of $(2) */'; \
	} > $$@;
endif
endef

########################################################################
# Subdir/module builds...
#
# Maintenance reminders: all relevant symbols in the sub-makefiles
# (make-XXX.make) MUST be unique across the whole global
# namespace. Similarly, all relevant paths must point to that
# subdir. That is particularly of interest with the BIN/DLL/LIB and
# CLEAN.xxx rules, which may require another level of $(var)
# indirection for that purpose. It's also important when using
# CPPFLAGS and such, to keep subdir-specific flags from leaking across
# makefiles. Similarly, when using ShakeNMake.install.XXX, the install
# vars must appended to instead of overwritten.
########################################################################
# INCLUDE_SINGLE_SUBMAKE includes file make-$(1).make if it exists,
# else this is a no-op. It protects against multiple inclusion.
INCLUDED_SUBMAKES :=
define INCLUDE_SINGLE_SUBMAKE
  SINGLE.$(1) := $$(wildcard make-$(1).make)
  ifneq (,$$(SINGLE.$(1)))
  ifneq ($(1),$$(strip $$(filter $(1),$$(INCLUDED_SUBMAKES))))
    $(1):# kludge
    ifneq (,$$(strip $$(filter distclean-$(1) clean-$(1),$(MAKECMDGOALS))))
      MAKING_CLEAN.$(1):=1
    endif
    INCLUDED_SUBMAKES+=$(1)
    $$(info Importing sub-make: $(1))
    include $$(SINGLE.$(1))
  endif
  endif
endef
# If passed an explicit make target matching make-XXX.make then
# include that makefile. Note that we must always include
# make-libf.make because all sub-makes depend on those bits.
$(eval $(call INCLUDE_SINGLE_SUBMAKE,libf))
ifneq (,$(MAKECMDGOALS))
  $(foreach f,$(MAKECMDGOALS),$(eval $(call INCLUDE_SINGLE_SUBMAKE,$(f))))
endif
INCLUDED_SUBMAKES:=$(strip $(INCLUDED_SUBMAKES))
#$(info INCLUDED_SUBMAKES=$(INCLUDED_SUBMAKES))
ifneq (libf-only,$(strip $(filter libf-only,$(INCLUDED_SUBMAKES))))
ifeq (libf,$(INCLUDED_SUBMAKES))
  # ^^^^ no submakes were explicitly called for, so include them all...
  themakes := f-apps
  ifeq (1,$(BUILD_CLIENT_FNC))
    themakes += client-fnc
  endif
  ifneq (,$(CXX))
    themakes += binding-cpp
  endif
#TODO:  themakes += binding-s2
  $(foreach f,$(themakes),$(eval $(call INCLUDE_SINGLE_SUBMAKE,$(f))))
#  undefine themakes
  #$(info MAKEFILE_LIST=$(MAKEFILE_LIST))
endif
endif
#undefine INCLUDED_SUBMAKES
#undefine INCLUDE_SINGLE_SUBMAKE
# /subdir builds
########################################################################

$(call ShakeNMake.CALL.CLEAN-SET,root)
DISTCLEAN.root += config.make
# All GENERATED make-*.make files...
DISTCLEAN.root += make-libf.make \
  make-f-apps.make \
  make-client-fnc.make \
  make-binding-cpp.make


ifeq ($(MAKE_COMPILATION_DB),yes)
all: compile_commands.json
compile_commands.json:
	@$(RM) $@
	sed -e '1s/^/[\'$$'\n''/' -e '$$s/,$$/\'$$'\n'']/' $(compdb_dir)/*.o.json > $@+
	@if test -s $@+; then mv $@+ $@; else $(RM) $@+; fi
endif

AUTOCONFIG_H := $(DIR.include)/fossil-scm/autoconfig.h
DISTCLEAN.root += $(AUTOCONFIG_H) $(ROOT.MAKEFILE) config.log \
  autosetup/jimsh0 \
	$(wildcard compile_commands/*) compile_commands.json+

# automake compatibility. do nothing for all these targets
#EMPTY_AUTOMAKE_TARGETS := dvi pdf ps info html tags ctags mostlyclean maintainer-clean check installcheck installdirs \
# install-pdf install-ps install-info install-html -install-dvi uninstall install-exec install-data distdir
#.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
#$(EMPTY_AUTOMAKE_TARGETS):

## @top_srcdir@/Makefile.in: # b/c AUTODEPS contains this name (it probably shouldn't)
#$(FSL.OBJ): @AUTODEPS@ @top_srcdir@/Makefile @top_srcdir@/config.make

# Reconfigure if needed
#ifeq ($(findstring clean,$(MAKECMDGOALS)),)
#@top_srcdir@/config.make: @AUTODEPS@ @top_srcdir@/config.make.in
#	@@AUTOREMAKE@
#endif

# Or on demand
reconfig:
	@AUTOREMAKE@

CLEAN.root += $(wildcard $(DIR.top)/*~)
