# SPDX-License-Identifier: MIT


-include Makefile.local

KLAPKI_VERSION ?= "$(patsubst v%,%,$(shell git describe))"
SOURCE_DATE_EPOCH ?= $(shell git log -1 --no-show-signature --format=%at man/klapki.8)
KLAPKI_DATE ?= $(shell LC_ALL=C date -d@$(SOURCE_DATE_EPOCH) '+%B %e, %Y')
MANDOC ?= mandoc
PKG_CONFIG ?= pkgconf
NOLOCREGEN ?=

# Set these to "{}" to compile-time-validate libfmt format strings (on CI)
FGETTEXT  ?= fmt::runtime(gettext({}))
FNGETTEXT ?= fmt::runtime(ngettext({}, plur, cnt))

OUTDIR := out/
BLDDIR := out/build/

CXXFLAGS += -O3 -g -std=c++20 -Wall -Wextra -pipe -fPIC -fno-rtti
CPPFLAGS += -MD $(shell $(PKG_CONFIG) --cflags efivar efiboot fmt libmd zlib 2>/dev/null) -DKLAPKI_VERSION='$(KLAPKI_VERSION)' -D'fgettext(str)=$(subst {},str,$(FGETTEXT))' -D'fngettext(sing, plur, cnt)=$(subst {},sing,$(FNGETTEXT))'
LDLIBS   += $(shell for l in efivar efiboot fmt libmd; do $(PKG_CONFIG) --libs $$l 2>/dev/null || echo -l$${l#lib}; done) $(shell $(PKG_CONFIG) --libs zlib 2>/dev/null || echo -DKLAPKI_NO_ZLIB)

SOURCES := $(sort $(wildcard src/*.cpp))
TEST_SOURCES := $(sort $(wildcard test/*.cpp))
MANPAGES := $(sort $(wildcard man/*.8))
ifneq (,$(shell command -v msgfmt))
	LOCALES := $(wildcard po/*.po)
endif

ifneq "$(findstring clang,$(shell $(CXX) --version))" ""
	# GCC doesn't have this granularity
	CXXFLAGS += -pedantic -Wno-gnu-statement-expression -flto=full
else
	CXXFLAGS += -flto
endif


.PHONY : all clean build build-test manpages htmlpages
.SECONDARY:


all : build locales manpages htmlpages build-test test

test: build-test
	$(OUTDIR)klapki-test

clean :
	rm -rf $(OUTDIR)

build : $(OUTDIR)klapki
build-test : $(OUTDIR)klapki-test
manpages : $(patsubst %,$(OUTDIR)%,$(MANPAGES))
htmlpages : $(patsubst %,$(OUTDIR)%.html,$(MANPAGES)) $(OUTDIR)man/style.css
locales : $(patsubst po/%.po,$(OUTDIR)locale/%/LC_MESSAGES/klapki.mo,$(LOCALES))


$(OUTDIR)klapki : $(patsubst %.cpp,$(BLDDIR)%.o,$(SOURCES))
	$(CXX) $(CXXFLAGS) $(LDFLAGS) -o$@ $^ $(LDLIBS)

$(BLDDIR)test/%.o $(OUTDIR)klapki-test : CXXFLAGS += -O0
$(BLDDIR)test/%.o $(OUTDIR)klapki-test : CPPFLAGS += -Isrc/
$(OUTDIR)klapki-test : $(patsubst %.cpp,$(BLDDIR)%.o,$(TEST_SOURCES) $(filter-out src/main.cpp,$(SOURCES)))
	$(CXX) $(CXXFLAGS) $(LDFLAGS) -o$@ $^ $(LDLIBS)


$(BLDDIR)klapki.pot: src/*.[ch]pp
	@mkdir -p $(@D)
	$(NOLOCREGEN)xgettext --check=ellipsis-unicode -kfgettext -kfngettext:1,2 --from-code=UTF-8 -c -io- $^ | sed -n '/^#[:.]/,$$p' > $@
	$(NOLOCREGEN)$(foreach l,$(LOCALES),msgmerge --backup=off --no-wrap -Uiq $(l) $@ &&) :
	@>> $@

$(OUTDIR)locale/%/LC_MESSAGES/klapki.mo : po/%.po $(BLDDIR)klapki.pot
	@mkdir -p $(@D)
	msgfmt --statistics --check-format --check-domain -o $@ $<


# The d-v-o-s string starts at "BSD" (hence the "BSD General Commands Manual" default); we're not BSD, so hide it
# Can't put it at the very top, since man(1) only loads mdoc *after* the first mdoc macro (.Dd in our case)
$(OUTDIR)man/% : man/%
	@mkdir -p $(@D)
	awk '$$0 == ".Dd" {$$2 = "$(KLAPKI_DATE)"}  $$1 == ".Dt" { print ".ds doc-volume-operating-system" }  $$0 == ".Os" {$$2 = "klapki"; $$3 = $(KLAPKI_VERSION)}  {print}' $< > $@
	! $(MANDOC) -Tlint $@ 2>&1 | grep -vF -e 'mandoc: outdated mandoc.db' -e 'STYLE: referenced manual not found' -e 'STYLE: input text line longer than 80 bytes:' -e 'STYLE: operating system explicitly specified: Os klapki' -e 'STYLE: no blank before trailing delimiter: Pa /sys/\:firmware/\:efi/\:efivars/\:'

# https://manpages.debian.org/bookworm/SHA1.3
$(OUTDIR)man/%.html : $(OUTDIR)man/%
	@mkdir -p $(@D)
	sed -e 's/^\(\.i[ef]\) n/\1 0/' $< | \
		$(MANDOC) -Thtml -Ostyle="style.css",man="https://manpages.debian.org/bookworm/%N.%S" $< | \
		awk '/^<h1/ {in_syn = $$0 ~ /id="SYNOPSIS"/}  /^<br/ {if(in_syn) {print >"/dev/stderr"; next}}  {print}' | \
		sed -Ee 's/ title=".."//g' -e 's/<a class="permalink" href="#([^"]*)"><span class="No" id="([^"]*)">/<a><span class="No">/g' > $@

$(OUTDIR)man/style.css : man/style.css
	@mkdir -p $(@D)
	cp $^ $@


$(BLDDIR)%.o : %.cpp
	@mkdir -p $(@D)
	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<


include $(wildcard $(BLDDIR)*/*.d)
