#
# Copyright (C) 2003-2005 by David J. Hardy.  All rights reserved.
#
# GNUmakefile
# master makefile for MDX

# name of hidden config file
cfgsave := $(CURDIR)/build/.config.$(shell whoami).$(shell hostname)

# if "config" is a target, then skip trying to read in config file
# and instead set config options to their default values
ifneq (,$(filter config,$(MAKECMDGOALS)))

# default values for config options
OS ?= $(shell uname)
ARCH ?= generic
BUILD ?= $(OS)_$(ARCH)
BUILD_TYPE ?= dynamic plugin bin
BUILD_DEMO ?= yes
SRC ?= $(shell cat $(CURDIR)/src.lst)
DOC ?= $(shell cat $(CURDIR)/doc.lst)
INSTALL ?= yes
INSTALL_DEMO ?= no
#INSTALL_DIR ?= /usr/local
INSTALL_DIR ?= $(HOME)
INSTALL_BIN ?= $(INSTALL_DIR)/bin
INSTALL_LIB ?= $(INSTALL_DIR)/lib
INSTALL_INCLUDE ?= $(INSTALL_DIR)/include/mdx
INSTALL_DOC ?= $(INSTALL_DIR)/doc

# otherwise include the already saved config file
else
include $(cfgsave)
endif

# name of architecture build file
buildfile := $(CURDIR)/arch/$(BUILD).mk
include $(buildfile)

# targets
buildtarg := src doc all
cfgtarg := config
instarg := install
cleantarg := clean cleanobj cleanconfig cleandoc cleandoctmp cleanall veryclean

# directories
buildir := $(CURDIR)/build/$(BUILD)
objdirprefix := $(buildir)/obj_
objdirlist := $(addprefix $(objdirprefix),$(BUILD_TYPE))
ifeq (yes,$(strip $(BUILD_DEMO)))
objdirlist += $(objdirprefix)demo
endif
bindir := $(buildir)/bin
libdir := $(buildir)/lib
demodir := $(buildir)/demo
srcdir := $(CURDIR)/src
docdir := $(CURDIR)/doc
mkdirlist := $(buildir) $(bindir) $(libdir) $(demodir) $(objdirlist)
instdirlist := $(INSTALL_BIN) $(INSTALL_LIB) $(INSTALL_INCLUDE) $(INSTALL_DOC)
#instdirlist += $(addprefix $(INSTALL_INCLUDE)/,$(SRC))

# documentation wildcard matches
docsuffix := .pdf .ps
doctextsuffix := .txt
doctmpsuffix := .aux .bbl .blg .log .toc .dvi
## expand wildcards to match existing doc files
docfiles := $(wildcard $(addprefix $(docdir)/*,$(docsuffix)))
doctextfiles := $(wildcard $(addprefix $(docdir)/*,$(doctextsuffix)))
## don't yet expand wildcards in temp files
doctmpfiles := $(addprefix *,$(doctmpsuffix))

# this is the default target
src : $(cfgsave) $(buildfile) $(SRC)

# call src.mk for each directory listed in SRC
# the target is set to the particular src/ directory
# include the makefile listed in that directory
$(SRC) : $(mkdirlist)
	@$(MAKE) -C $(CURDIR) -f $(CURDIR)/src.mk $@ SRC="$@" \
	  MAKEFILES="$(cfgsave) $(buildfile) $(srcdir)/$@/GNUmakefile"

# directories that don't exist get created
$(mkdirlist) :
	mkdir -p $@

# call doc.mk file on each subdirectory listed in DOC
doc : $(cfgsave)
ifneq (,$(strip $(DOC)))
	@for d in $(DOC); do \
	  $(MAKE) -C $(docdir)/$$d -f $(CURDIR)/doc.mk $$d DOC="$$d" \
	    MAKEFILES="$(cfgsave) $(buildfile) $(docdir)/$$d/GNUmakefile"; \
	done
endif

all : src doc

# save the options to the config file
config : $(buildfile)
	@echo "# ./build/$(notdir $(cfgsave))" > $(cfgsave)
	@echo '# (use "make config" to generate)' >> $(cfgsave)
	@echo OS := $(OS) >> $(cfgsave)
	@echo ARCH := $(ARCH) >> $(cfgsave)
	@echo BUILD := $(BUILD) >> $(cfgsave)
	@echo BUILD_TYPE := $(BUILD_TYPE) >> $(cfgsave)
	@echo BUILD_DEMO := $(BUILD_DEMO) >> $(cfgsave)
	@echo SRC := $(SRC) >> $(cfgsave)
	@echo DOC := $(DOC) >> $(cfgsave)
	@echo INSTALL := $(INSTALL) >> $(cfgsave)
	@echo INSTALL_DEMO := $(INSTALL_DEMO) >> $(cfgsave)
	@echo INSTALL_DIR := $(INSTALL_DIR) >> $(cfgsave)
	@echo INSTALL_BIN := $(INSTALL_BIN) >> $(cfgsave)
	@echo INSTALL_LIB := $(INSTALL_LIB) >> $(cfgsave)
	@echo INSTALL_INCLUDE := $(INSTALL_INCLUDE) >> $(cfgsave)
	@echo INSTALL_DOC := $(INSTALL_DOC) >> $(cfgsave)
	@cat $(cfgsave)

show : $(cfgsave)
	@cat $^

ifeq (yes,$(strip $(INSTALL)))
install : $(instdirlist) $(bindir) $(libdir)
ifeq (yes,$(strip $(INSTALL_DEMO)))
ifneq (,$(strip $(wildcard $(demodir)/*)))
	cp $(wildcard $(demodir)/*) $(INSTALL_BIN)/.
endif
endif
ifneq (,$(strip $(wildcard $(bindir)/*)))
	cp $(wildcard $(bindir)/*) $(INSTALL_BIN)/.
endif
ifneq (,$(strip $(wildcard $(libdir)/*)))
	cp $(wildcard $(libdir)/*) $(INSTALL_LIB)/.
endif
ifneq (,$(strip $(docfiles) $(doctextfiles)))
	cp $(docfiles) $(doctextfiles) $(INSTALL_DOC)/.
endif
ifneq (,$(strip $(SRC)))
	@for s in $(SRC); do \
	  $(MAKE) -C $(CURDIR) install_header SRC="$$s" \
	    MAKEFILES="$(cfgsave) $(buildfile) $(srcdir)/$$s/GNUmakefile"; \
	done
endif
else
install :
endif

# make install subdirs for header files only if something gets copied there
install_header :
ifneq (,$(strip $(HEADER)))
	@if [ ! -d "$(INSTALL_INCLUDE)/$(SRC)" ] ; then \
	  mkdir $(INSTALL_INCLUDE)/$(SRC) ; \
	  echo mkdir $(INSTALL_INCLUDE)/$(SRC) ; \
	fi
	cp $(addprefix $(srcdir)/$(SRC)/,$(addsuffix .h,$(basename $(HEADER)))) $(INSTALL_INCLUDE)/$(SRC)/.
endif

# directories that don't exist get created
$(sort $(instdirlist)) :
	mkdir -p $@

clean :
ifeq (0,$(MAKELEVEL))
	-rm -rf $(buildir)
else
	-rm -rf $(addsuffix /$(SRC),$(objdirlist))
endif

cleanobj :
	-rm -rf $(objdirlist)

cleanconfig :
	-rm -f $(cfgsave)

cleandoc : cleandoctmp
ifeq (0,$(MAKELEVEL))
ifneq (,$(strip $(docfiles)))
#	-rm -f $(docfiles)
endif
else
	-rm -f $(addprefix $(docdir)/$(DOC),$(docsuffix))
endif

cleandoctmp :
	-rm -f $(foreach d,$(DOC),$(addprefix $(docdir)/$(d)/,$(doctmpfiles)))

cleandemo :
	@( cd demo ; make clean )

cleanall : cleandemo cleandoc clean cleanconfig

# remove build subdirectories containing object files
# (but leave any other subdirectories, e.g. build/CVS)
# remove build .config files
veryclean : cleandemo cleandoc
	-rm -rf $(addprefix $(CURDIR)/build/,$(notdir $(basename $(wildcard $(CURDIR)/arch/*.mk)))) $(CURDIR)/build/.config.*

ifeq (.mk,$(notdir $(buildfile)))
$(cfgsave) $(buildfile) :
	$(error Try doing "make config" to configure build system)
else
$(buildfile) :
	$(error Build file ./arch/$(notdir $(buildfile)) does not exist)
endif

.PHONY : $(buildtarg) $(cfgtarg) $(instarg) $(cleantarg) $(SRC)

export
