# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
# This file is offered as-is, without any warranty.

PROJECT       = amalthea
DESCR         = "Small general Linux-specific library"
DC            = ldc2
PREFIX        = usr
DESTDIR       =

VERSION       := $(shell cat source/$(PROJECT)/version)
MAJOR_VERSION := $(shell cat source/$(PROJECT)/version | cut -d'.' -f1)

BASENAME                 := $(PROJECT)-$(DC)
LIBRARY                  := lib$(BASENAME)
PCFILE_NAME              := $(BASENAME).pc
PCFILE_NAME_ST           := $(BASENAME)-static.pc
OBJFILE                  := $(LIBRARY).o
SHLIB_BASE               := $(LIBRARY).so
STLIB_NAME               := $(LIBRARY).a
SHLIB_WITH_VERSION       := $(SHLIB_BASE).$(VERSION)
SHLIB_WITH_MAJOR_VERSION := $(SHLIB_BASE).$(MAJOR_VERSION)
SHLIB_WITHOUT_VERSION    := $(SHLIB_BASE)

B_DIR  := build
OBJECT := $(B_DIR)/$(OBJFILE)
SHLIB  := $(B_DIR)/$(SHLIB_WITH_VERSION)
STLIB  := $(B_DIR)/$(STLIB_NAME)
PCFILE    := $(B_DIR)/$(PCFILE_NAME)
PCFILE_ST := $(B_DIR)/$(PCFILE_NAME_ST)

SONAME := $(SHLIB_BASE).$(MAJOR_VERSION)

SHLIB_FLAGS   := $(shell ./mh.sh $(DC) shared-flags $(SONAME))
EXTERNAL_LIBS := $(shell ./mh.sh $(DC) external-libs)
DEBUG_FLAGS   := $(shell ./mh.sh $(DC) debug-flags)
RELEASE_FLAGS := $(shell ./mh.sh $(DC) release-flags)
OTHER_FLAGS   := -J.

SOURCES   := $(wildcard source/$(PROJECT)/*.d)
RESOURCES := $(wildcard res/*)

LIBDIR          := $(shell ./mh.sh $(DC) library-path)
INCDIR          := $(shell ./mh.sh $(DC) include-path)
INST_LIBDIR     := $(DESTDIR)/$(PREFIX)/$(LIBDIR)
INST_INCDIR_TOP := $(DESTDIR)/$(PREFIX)/$(INCDIR)
INST_INCDIR     := $(INST_INCDIR_TOP)/$(PROJECT)
INST_PCDIR      := $(INST_LIBDIR)/pkgconfig

SYS_CONF_DIR := $(DESTDIR)/etc/$(BASENAME)/

OUT       := -of
TESTFLAGS := -unittest -main
ifeq ($(DC),gdc)
	OUT := -o
	TESTFLAGS := -funittest -fmain
endif

.PHONY: all clean *install *-settings shared static test \
doc examples example* dub meson generate-pc

all: shared static

shared: compilation-settings $(SHLIB)
	@echo "Compiled to" $(SHLIB)

static: compilation-settings $(STLIB)
	@echo "Compiled to" $(STLIB)

compilation-settings:
	@echo "Project:" $(PROJECT)
	@echo "Version:" $(VERSION)
	@echo "Major version:" $(MAJOR_VERSION)
	@echo ""
	@echo "Compiler:" $(DC)
	@echo "Options of debug compilation:  " $(DEBUG_FLAGS)
	@echo "Options of release compilation:" $(RELEASE_FLAGS)
	@echo "Options for shared library:    " $(SHLIB_FLAGS) $(EXTERNAL_LIBS)
	@echo ""

installation-settings:
	@echo "Library directory:" $(INST_LIBDIR)/
	@echo "Files to import:  " $(INST_INCDIR)/

$(OBJECT): $(SOURCES)
	mkdir -p $(B_DIR)
	$(DC) $^ -c $(OUT)$@ $(DEBUG_FLAGS) $(OTHER_FLAGS)

$(SHLIB): $(OBJECT)
	$(DC) $^ $(OUT)$@ $(SHLIB_FLAGS) $(EXTERNAL_LIBS)

$(STLIB): $(OBJECT)
	ar r $@ $^

test: $(SOURCES)
	$(DC) $^ $(OUT)$(B_DIR)/libapp $(TESTFLAGS) -J. $(EXTERNAL_LIBS)
	@echo "================================"
	$(B_DIR)/libapp
	@echo "================================"

# https://codeberg.org/os-18/hgen
doc:
	hgen source/ --macros ddoc-macros

dub:
	dub build --compiler=$(DC) -v --force

meson:
	meson meson_builddir --prefix=/$(PREFIX)
	cd meson_builddir ; meson compile

meson-install:
	cd meson_builddir ; meson install --destdir=$(DESTDIR)

clean:
	rm -rf build/ doc/ meson_builddir/

install: installation-settings generate-pc
	mkdir -p "$(INST_INCDIR)" "$(INST_LIBDIR)" "$(INST_PCDIR)"
	cp $(SHLIB) "$(INST_LIBDIR)"
	cp $(STLIB) "$(INST_LIBDIR)"
	cp $(SOURCES) "$(INST_INCDIR)"
	ln -sf $(SHLIB_WITH_VERSION) "$(INST_LIBDIR)/$(SHLIB_WITH_MAJOR_VERSION)"
	ln -sf $(SHLIB_WITH_MAJOR_VERSION) "$(INST_LIBDIR)/$(SHLIB_WITHOUT_VERSION)"
	cp $(PCFILE) $(PCFILE_ST) "$(INST_PCDIR)/"
	mkdir -p "$(SYS_CONF_DIR)"
	[ -n "$(RESOURCES)" ] && install -m 644 $(RESOURCES) "$(SYS_CONF_DIR)"

uninstall: installation-settings
	rm -f "$(INST_LIBDIR)/$(SHLIB_WITH_VERSION)"
	rm -f "$(INST_LIBDIR)/$(SHLIB_WITH_MAJOR_VERSION)"
	rm -f "$(INST_LIBDIR)/$(SHLIB_WITHOUT_VERSION)"
	rm -f "$(INST_LIBDIR)/$(STLIB_NAME)"
	rm -rf "$(INST_INCDIR)"
	rm -rf $(SYS_CONF_DIR)
	rm -f "$(INST_PCDIR)/$(PCFILE_NAME)" "$(INST_PCDIR)/$(PCFILE_NAME_ST)"



DESCR_ENDING := "the $(shell echo $(DC) | tr a-z A-Z) version"
PC_DESCR     := "Description: $(DESCR), $(DESCR_ENDING)"
PC_LDIR      := $(subst //,/,/$(PREFIX)/$(LIBDIR))
PC_IDIR      := $(subst //,/,/$(PREFIX)/$(INCDIR))
LPATH_OPT    := $(shell ./mh.sh $(DC) libpath-opt)
LN_OPT       := $(shell ./mh.sh $(DC) libname-opt)
SHARED_OPTS  := $(LPATH_OPT)$(PC_LDIR) $(LN_OPT)$(BASENAME)
STATIC_OPTS  := $(LPATH_OPT)$(PC_LDIR) $(LN_OPT):lib$(BASENAME).a

generate-pc:
	mkdir -p $(B_DIR)
	# for dynamic version
	echo "Name: $(BASENAME)" > $(PCFILE)
	echo "$(PC_DESCR)" >> $(PCFILE)
	echo "Version: $(VERSION)" >> $(PCFILE)
	echo "Libs: $(SHARED_OPTS) $(EXTERNAL_LIBS)" >> $(PCFILE)
	echo "Cflags: -I$(PC_IDIR)" >> $(PCFILE)
	# for static version
	echo "Name: $(BASENAME)-static" > $(PCFILE_ST)
	echo "$(PC_DESCR). Static library" >> $(PCFILE_ST)
	echo "Version: $(VERSION)" >> $(PCFILE_ST)
	echo "Libs: $(STATIC_OPTS) $(EXTERNAL_LIBS)" >> $(PCFILE_ST)
	echo "Cflags: -I$(PC_IDIR)" >> $(PCFILE_ST)


# EXAMPLES

RVREF := -preview=rvaluerefparam
ifeq ($(DC),gdc)
	RVREF := -fpreview=rvaluerefparam
endif

EXAMPLE_OPTS := $(DEBUG_FLAGS) $(EXTERNAL_LIBS) -Isource/ $(RVREF)

EXAMPLE_SOURCES := $(wildcard examples/*/*.d)
EXAMPLE_NAMES := $(basename $(notdir $(EXAMPLE_SOURCES)))
EXAMPLE_BINS := $(addprefix example-,$(EXAMPLE_NAMES))

examples: $(EXAMPLE_BINS)

define EXAMPLE_RULE
$(addprefix example-,$(notdir $(basename $(1)))): $(OBJECT) $(1) | $(B_DIR)
	$$(DC) $$^ $$(OUT)$$(B_DIR)/examples/$$@ $$(EXAMPLE_OPTS) -J$(dir $(1))
endef
$(foreach src,$(EXAMPLE_SOURCES),$(eval $(call EXAMPLE_RULE,$(src))))
