# Root makefile that can be used to build/run tests and/or examples for
# some or all databases:
#
# make              - build tests and examples for all the databases
# make t            - build only tests for all the databases
# make e            - build only examples for all the databases
#
# make <db>         - build tests and examples for <db>
# make <db>-t       - build only tests for <db>
# make <db>-e       - build only examples for <db>
#
# make test         - run tests and examples for all the databases
# make ttest        - run only tests for all the databases
# make etest        - run only examples for all the databases
#
# make <db>-test    - run tests and examples for <db>
# make <db>-ttest   - run only tests for <db>
# make <db>-etest   - run only examples for <db>
#
# make clean        - clean tests and examples for all the databases
# make tclean       - clean only tests for all the databases
# make eclean       - clean only examples for all the databases
#
# make <db>-clean   - clean tests and examples for <db>
# make <db>-tclean  - clean only tests for <db>
# make <db>-eclean  - clean only examples for <db>
#
# Additional command line variables:
#
# conf           - configuration to build (e.g., conf=c++)
#
# Note that you can run tests and examples with -j; the makefile is
# smart enough to build the tests and examples in parallel but run
# them sequentially.
#
# Ordering:
#  - tests before examples
#  - build before run
#
db := mssql oracle pgsql sqlite mysql common

tdb := $(db)
edb := $(filter-out common,$(db)) # No multi-database build for examples.

# Disable parallelism for this makefile (the sub-directories will
# still be built with parallelism). This makes this makefile much
# more usable.
#
.NOTPARALLEL:

ifeq ($(conf),)
conf_suffix := default
else
conf_suffix := builds/$(conf)
endif

.PHONY: t e all $(db)                        \
ttest etest test $(addsuffix -test,$(db))    \
tclean eclean clean $(addsuffix -clean,$(db))

all: t e
t: $(addsuffix -t,$(tdb))
e: $(addsuffix -e,$(edb))

test: ttest etest
ttest: t $(addsuffix -ttest,$(tdb)) 
etest: e $(addsuffix -etest,$(edb))

clean: tclean eclean
tclean: $(addsuffix -tclean,$(tdb))
eclean: $(addsuffix -eclean,$(edb))

define test_deps
$1-test: $1-t $1-e

endef

$(eval $(foreach d,$(tdb),$(call test_deps,$d)))

define set_edir
edir := $$(wildcard examples-$1-$(conf_suffix))
ifeq ($(conf),)
ifeq ($$(edir),)
edir := examples-$1
endif
endif
endef

define set_tdir
tdir := $$(wildcard tests-$1-$(conf_suffix))
ifeq ($(conf),)
ifeq ($$(tdir),)
tdir := tests-$1
endif
endif
endef

define ebuild_rule
.PHONY: $1-e
$1: $1-e
$1-e: dir := $$(edir)
$1-e:
	@$$(MAKE) -C $$(dir)
endef

define tbuild_rule
.PHONY: $1-t
$1: $1-t
$1-t: dir := $$(tdir)
$1-t:
	@$$(MAKE) -C $$(dir)
endef

define etest_rule
.PHONY: $1-etest
$1-test: $1-etest
$1-etest: dir := $$(edir)
$1-etest: $1-e
	@$$(MAKE) -C $$(dir) -j 1 test
endef

define ttest_rule
.PHONY: $1-ttest
$1-test: $1-ttest
$1-ttest: dir := $$(tdir)
$1-ttest: $1-t
	@$$(MAKE) -C $$(dir) -j 1 test
endef

define eclean_rule
.PHONY: $1-eclean
$1-clean: $1-eclean
$1-eclean: dir := $$(edir)
$1-eclean:
	@$$(MAKE) -C $$(dir) clean
endef

define tclean_rule
.PHONY: $1-tclean
$1-clean: $1-tclean
$1-tclean: dir := $$(tdir)
$1-tclean:
	@$$(MAKE) -C $$(dir) clean
endef

# Note: empty line at the end is important.
#
#
define erules
$(call set_edir,$1)
$(call ebuild_rule,$1)
$(call etest_rule,$1)
$(call eclean_rule,$1)

endef

define trules
$(call set_tdir,$1)
$(call tbuild_rule,$1)
$(call ttest_rule,$1)
$(call tclean_rule,$1)

endef

# Do all tests for all the database first. Then examples.
#
$(eval $(foreach d,$(tdb),$(call trules,$d)))
$(eval $(foreach d,$(edb),$(call erules,$d)))