all: install
.PHONY: .
.SECONDARY:
.SUFFIXES:
	MAKEFLAGS += -r
.SHELLFLAGS += -e

#
##  environment
###
CABAL_SANDBOX:=.cabal-sandbox
GHC_PKG:=ghc-pkg
GHC_PROF_CATEGORIES:=hc hm hd hy hr hb
GHC_PROF_CPUS:=
GHC_PROF_PS_WIDTH:=11in
GHC_PROF_RATE:=0.1
GHC_PROF_CC_LENGTH:=50
HCOMPTA_CLI_PROF:=$(CABAL_SANDBOX)/bin/hcompta-cli-prof
HCOMPTA_COMMANDS:=balance
# gl journal
commit:=$(shell if which git >/dev/null; then git describe --long; else echo COMMIT; fi)

#
##  helpers
###
if_arg=$(if $2,$1 $2)
rmw=$(call if_arg,rm,$(wildcard $1))
rmdirw=$(call if_arg,rmdir -p --ignore-fail-on-non-empty,$(wildcard $1))

#
##  install
###
install: cabal/install lib/install cli/install web/install
cabal/install:
	cabal $(CABAL_FLAGS) update $(CABAL_UPDATE_FLAGS)
	cabal $(CABAL_FLAGS) install -v $(CABAL_INSTALL_FLAGS) cabal
.PHONY: lib cli web
lib lib/install: cli/unregister web/unregister cli/unregister/sandbox web/unregister/sandbox
	cabal $(CABAL_FLAGS) install -v $(CABAL_INSTALL_FLAGS) ./lib
cli cli/install:
	cabal $(CABAL_FLAGS) install -v $(CABAL_INSTALL_FLAGS) ./cli
web web/install:
	cabal $(CABAL_FLAGS) install -v $(CABAL_INSTALL_FLAGS) alex happy
	cabal $(CABAL_FLAGS) install -v $(CABAL_INSTALL_FLAGS) ./web

%/recomp: CABAL_INSTALL_FLAGS+=--ghc-options -fforce-recomp
%/recomp: %
	

#
##  clean
###
clean: lib/clean cli/clean web/clean doc/clean
lib/clean:
	(cd lib && cabal clean)
cli/clean:
	(cd cli && cabal clean)
web/clean:
	(cd web && cabal clean)

#
##  test
###
test: lib/test cli/test web/test
lib/test:
	(cd lib && cabal $(CABAL_FLAGS) test --show-details=always $(CABAL_TEST_FLAGS))
cli/test:
	(cd cli && cabal $(CABAL_FLAGS) test --show-details=always $(CABAL_TEST_FLAGS))
web/test:
	(cd web && cabal $(CABAL_FLAGS) test --show-details=always $(CABAL_TEST_FLAGS))
%/install/test: CABAL_INSTALL_FLAGS+=--enable-tests
%/install/test: %/install
	

#
##  doc
###
.PHONY: doc
doc: doc/xhtml lib/doc cli/doc web/doc
%/prof: CABAL_INSTALL_FLAGS+=-fprof --enable-library-profiling --enable-executable-profiling
%/prof: $(CABAL_SANDBOX) %
	

lib/doc:
	(cd lib && cabal $(CABAL_FLAGS) haddock --hyperlink-source $(CABAL_HADDOCK_FLAGS))
cli/doc:
	(cd cli && cabal $(CABAL_FLAGS) haddock --hyperlink-source $(CABAL_HADDOCK_FLAGS))
web/doc:
	(cd web && cabal $(CABAL_FLAGS) haddock --hyperlink-source $(CABAL_HADDOCK_FLAGS))
doc/%: .
	$(MAKE) -C doc $*

#
##  dev
###
%/dev: CABAL_INSTALL_FLAGS+=-fdev
%/dev: %
	

#
##  dump
###
%/dump: CABAL_INSTALL_FLAGS+=-fdump
%/dump: %
	

#
##  prof
###
.PHONY: prof
prof: $(foreach command,$(HCOMPTA_COMMANDS),prof/$(command))

prof/commit/$(commit):
	mkdir -p "$@"

lib/install/prof: CABAL_INSTALL_FLAGS+=-fprof --enable-library-profiling
lib/install/prof: cli/unregister/sandbox lib/install | $(CABAL_SANDBOX)
	

cli/install/prof: CABAL_INSTALL_FLAGS+=-fprof --enable-library-profiling --enable-executable-profiling
cli/install/prof: cli/install | $(CABAL_SANDBOX)
	mv \
	 $(CABAL_SANDBOX)/bin/hcompta-cli \
	 $(CABAL_SANDBOX)/bin/hcompta-cli-prof

define prof/command

prof/clean: prof/$(command)/clean

prof/%.ledger/$(command)/clean: \
 $(foreach hC,$(GHC_PROF_CATEGORIES), \
 prof/%.ledger/$(command)/$(hC)/clean \
 )
	$$(call rmw, \
	 prof/$$*.ledger.$(command) \
	 )

endef

define prof/command/hC

prof/$(command):                prof/$(command)/$(hC)
prof/$(command)/clean:          prof/$(command)/$(hC)/clean
prof/%.ledger/$(command):       prof/%.ledger.$(command)/$(hC)
prof/%.ledger/$(command)/$(hC): prof/commit/$$(commit)/%.ledger.$(command).$(hC).ps
	

prof/%.ledger.$(command): \
 prof/commit/$$(commit)/%.ledger.$(command).$(hC).hs

prof/commit/$$(commit)/%.ledger.$(command).$(hC).hp \
prof/%.ledger.$(command): \
 $$(HCOMPTA_CLI_PROF) \
 prof/%.ledger \
 | prof/commit/$$(commit)
	GHCRTS=' \
	 -$(hC)$$(GHC_PROF_$(hC)) \
	 -i$$(GHC_PROF_RATE) \
	 -L$$(GHC_PROF_CC_LENGTH) \
	 -N$$(GHC_PROF_CPUS) \
	 -tprof/commit/$(commit)/$$*.ledger.$(command).$(hC).stats \
	 -p \
	 $$(GHCRTS)' \
	$$(HCOMPTA_CLI_PROF) $$(HCOMPTA_FLAGS) \
	 $(command) $$(HCOMPTA_COMMAND_FLAGS) $$(filter %.ledger,$$^) \
	 >prof/$$*.ledger.$(command)
	mv $(notdir $(HCOMPTA_CLI_PROF)).hp   prof/commit/$(commit)/$$*.ledger.$(command).$(hC).hp
	mv $(notdir $(HCOMPTA_CLI_PROF)).prof prof/commit/$(commit)/$$*.ledger.$(command).$(hC).prof

prof/$(command)/$(hC): \
 $(addsuffix /$(command)/$(hC),$(wildcard prof/*.ledger))
prof/$(command)/$(hC)/clean:
	$$(call rmw, \
	 prof/commit/$$(commit)/*.ledger.$(command).$(hC).aux \
	 prof/commit/$$(commit)/*.ledger.$(command).$(hC).hp \
	 prof/commit/$$(commit)/*.ledger.$(command).$(hC).prof \
	 prof/commit/$$(commit)/*.ledger.$(command).$(hC).ps \
	 prof/commit/$$(commit)/*.ledger.$(command).$(hC).stats \
	 )
prof/%.ledger/$(command)/$(hC)/clean:
	$$(call rmw, \
	 prof/commit/$$(commit)/$$*.ledger.$(command).$(hC).aux \
	 prof/commit/$$(commit)/$$*.ledger.$(command).$(hC).hp \
	 prof/commit/$$(commit)/$$*.ledger.$(command).$(hC).prof \
	 prof/commit/$$(commit)/$$*.ledger.$(command).$(hC).ps \
	 prof/commit/$$(commit)/$$*.ledger.$(command).$(hC).stats \
	 )

endef

prof/%.ledger/clean: \
 $(foreach command,$(HCOMPTA_COMMANDS), \
 prof/%.ledger/$(command)/clean )
	

$(foreach command,$(HCOMPTA_COMMANDS), \
 $(eval $(call prof/command)) \
 $(foreach hC,$(GHC_PROF_CATEGORIES), \
  $(eval $(call prof/command/hC)) ))

%.hC.hp: $(foreach hC,$(GHC_PROF_CATEGORIES),%.$(hC).hp)
	
%.hC.ps: $(foreach hC,$(GHC_PROF_CATEGORIES),%.$(hC).ps)
	
%.ps: %.hp
	(cd $(@D) && hp2ps -b -c -e$(GHC_PROF_PS_WIDTH) -g $(notdir $*.hp))

#
##  not-threaded
###
%/not-threaded: CABAL_INSTALL_FLAGS+=-f-threaded
%/not-threaded: %
	

#
##  ghc-pkg
###
unregister: $(addsuffix /unregister,web cli lib)

%/unregister: .
	if    $(GHC_PKG) list       hcompta-$* | grep -q '^ * hcompta-$*-' ; \
	 then $(GHC_PKG) unregister hcompta-$* ; \
	 fi

%/unregister/sandbox: GHC_PKG:=cabal sandbox hc-pkg
%/unregister/sandbox: .
	if    $(GHC_PKG) list       hcompta-$* | grep -q '^ * hcompta-$*-' ; \
	 then $(GHC_PKG) unregister hcompta-$* ; \
	 fi

#
##  sandbox
###
$(CABAL_SANDBOX):
	cabal $(CABAL_FLAGS) sandbox --sandbox="$@" $(CABAL_SANDBOX_FLAGS) init

%/sandbox: GHC_PKG:=cabal sandbox hc-pkg
%/sandbox: %
	

#
##  stats
###
.PHONY: stats
stats:
	gitstats . $@