# Steward build and install.
#
#   make              build bin/stewardd and bin/steward (and their bash completion)
#   make test         vet, gofmt check and unit tests
#   make e2e          end-to-end test with real DHCP clients in Docker (scripts/e2e.sh)
#   sudo make install install binaries, bash completion, systemd units,
#                     sysusers/tmpfiles files and an example /etc/steward/steward.yaml
#   make deb          Debian packages in dist/ (DEB_ARCH=arm64 for another
#                     architecture): steward (the server) and steward-cli (the CLI,
#                     which steward depends on); 'sudo apt install ./dist/steward*_amd64.deb'
#   make dist         static binaries for linux/amd64 and linux/arm64 in dist/
#   make cli-dist     the CLI alone for Linux, macOS and Windows in dist/
#                     (steward-cli-<version>-<os>-<arch>[.exe])

VERSION ?= $(shell cat VERSION 2>/dev/null || echo 0.0.0-dev)
# RELEASE_TAG marks a build of a release (the web UI then shows and links
# the release rather than the commit): set when HEAD is tagged v$(VERSION)
# and no tracked file is changed.
RELEASE_TAG ?= $(shell t=v$(VERSION); git tag --points-at HEAD 2>/dev/null | grep -qx "$$t" && git diff --quiet HEAD 2>/dev/null && echo $$t)
# DESCRIBE places other builds relative to the last tag ("3 commits after
# v0.2.0-rc.1").
DESCRIBE ?= $(shell git describe --tags --long --match 'v[0-9]*' --abbrev=12 HEAD 2>/dev/null)
LDFLAGS := -s -w -X steward/internal/version.Version=$(VERSION) -X steward/internal/version.Tag=$(RELEASE_TAG) \
	-X steward/internal/version.Describe=$(DESCRIBE)
GOFLAGS := -trimpath
export CGO_ENABLED := 0

PREFIX      ?= /usr/local
BINDIR      ?= $(PREFIX)/bin
DOCDIR      ?= $(PREFIX)/share/doc/steward
# bash-completion also looks in /usr/local/share (XDG_DATA_DIRS).
BASHCOMPDIR ?= $(PREFIX)/share/bash-completion/completions
UNITDIR     ?= /etc/systemd/system
SYSUSERSDIR ?= /usr/lib/sysusers.d
TMPFILESDIR ?= /usr/lib/tmpfiles.d
DESTDIR     ?=

# The binaries install-files copies (make deb points these at other
# architectures' builds).
STEWARDD_BIN ?= bin/stewardd
STEWARD_BIN  ?= bin/steward

# make deb: the package's architecture (Debian name) and version. A
# release is VERSION with ~ for - (0.2.0-rc.1 -> 0.2.0~rc.1, which apt
# sorts before 0.2.0). A development build is versioned after the last
# tag: 3 commits past v0.2.0-rc.1 is 0.2.0~rc.1+git3.gca0f148, which apt
# sorts after that RC and before 0.2.0, so installing it upgrades without
# --reinstall. Uncommitted changes add the build time (.m20261009153000),
# so each such build is newer than the last.
DEB_ARCH    ?= $(shell dpkg --print-architecture 2>/dev/null || go env GOARCH)
DEB_DEV_VERSION := $(shell [ -n '$(DESCRIBE)' ] || exit 0; \
	m=; git diff --quiet HEAD 2>/dev/null || m=.m$$(date -u +%Y%m%d%H%M%S); \
	echo '$(DESCRIBE)' | sed -E 's/^v(.*)-([0-9]+)-g([0-9a-f]{7})[0-9a-f]*$$/\1+git\2.g\3/' | tr - '~' | sed "s/$$/$$m/")
DEB_VERSION ?= $(if $(RELEASE_TAG),$(subst -,~,$(VERSION)),$(or $(DEB_DEV_VERSION),$(subst -,~,$(VERSION))))

.PHONY: all build completion test vet e2e install install-files uninstall deb dist cli-dist clean

all: build

build:
	go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o bin/stewardd ./cmd/stewardd
	go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o bin/steward ./cmd/steward
	$(MAKE) --no-print-directory completion

# Bash completion scripts, generated by the binaries themselves.
completion:
	@mkdir -p bin/completion
	bin/steward completion bash > bin/completion/steward
	bin/stewardd completion bash > bin/completion/stewardd

vet:
	go vet ./...
	@test -z "$$(gofmt -l cmd internal)" || { echo "gofmt needed:"; gofmt -l cmd internal; exit 1; }

test: vet
	go test ./...

e2e:
	scripts/e2e.sh

install: build install-files
	@if [ ! -e $(DESTDIR)/etc/steward/steward.yaml ]; then \
		install -d -m 0750 $(DESTDIR)/etc/steward; \
		bin/stewardd config --example > $(DESTDIR)/etc/steward/steward.yaml; \
		chmod 0640 $(DESTDIR)/etc/steward/steward.yaml; \
		echo "wrote $(DESTDIR)/etc/steward/steward.yaml"; \
	fi
	@echo
	@echo "Next (as root): systemd-sysusers steward.conf && systemd-tmpfiles --create steward.conf"
	@echo "                chgrp steward /etc/steward /etc/steward/steward.yaml && systemctl daemon-reload"
	@echo "Then follow docs/install.md (init, start, add subnets or import Kea), and turn on the daily"
	@echo "database backup:  systemctl enable --now steward-backup.timer"

# Everything but /etc/steward/steward.yaml (shared by install and deb).
install-files:
	install -D -m 0755 $(STEWARDD_BIN) $(DESTDIR)$(BINDIR)/stewardd
	install -D -m 0755 $(STEWARD_BIN) $(DESTDIR)$(BINDIR)/steward
	install -D -m 0644 bin/completion/steward $(DESTDIR)$(BASHCOMPDIR)/steward
	install -D -m 0644 bin/completion/stewardd $(DESTDIR)$(BASHCOMPDIR)/stewardd
	for u in steward.service steward-backup.service steward-backup.timer; do \
		install -D -m 0644 deploy/systemd/$$u $(DESTDIR)$(UNITDIR)/$$u && \
		sed -i 's#/usr/local/bin/stewardd#$(BINDIR)/stewardd#; s#/usr/local/share/doc/steward#$(DOCDIR)#' $(DESTDIR)$(UNITDIR)/$$u || exit 1; \
	done
	install -D -m 0644 deploy/sysusers.d/steward.conf $(DESTDIR)$(SYSUSERSDIR)/steward.conf
	install -D -m 0644 deploy/tmpfiles.d/steward.conf $(DESTDIR)$(TMPFILESDIR)/steward.conf
	install -D -m 0644 README.md $(DESTDIR)$(DOCDIR)/README.md
	install -D -m 0644 LICENSE $(DESTDIR)$(DOCDIR)/LICENSE
	install -D -m 0644 CHANGELOG.md $(DESTDIR)$(DOCDIR)/CHANGELOG.md
	install -d $(DESTDIR)$(DOCDIR)/docs
	install -m 0644 docs/*.md $(DESTDIR)$(DOCDIR)/docs/

uninstall:
	rm -f $(DESTDIR)$(BINDIR)/stewardd $(DESTDIR)$(BINDIR)/steward $(DESTDIR)$(UNITDIR)/steward.service \
		$(DESTDIR)$(UNITDIR)/stewardd.service \
		$(DESTDIR)$(UNITDIR)/steward-backup.service $(DESTDIR)$(UNITDIR)/steward-backup.timer \
		$(DESTDIR)$(BASHCOMPDIR)/steward $(DESTDIR)$(BASHCOMPDIR)/stewardd \
		$(DESTDIR)$(SYSUSERSDIR)/steward.conf $(DESTDIR)$(TMPFILESDIR)/steward.conf
	rm -rf $(DESTDIR)$(DOCDIR)
	@echo "Kept /etc/steward, /var/lib/steward and /var/backups/steward."

# A Debian package, built with dpkg-deb (no root needed). The package's
# scripts are in deploy/debian; scripts/mkdeb.sh explains the layout.
deb: build
	DEB_ARCH='$(DEB_ARCH)' DEB_VERSION='$(DEB_VERSION)' VERSION='$(VERSION)' \
		LDFLAGS='$(LDFLAGS)' GOFLAGS='$(GOFLAGS)' scripts/mkdeb.sh

dist: build
	for arch in amd64 arm64; do \
		GOOS=linux GOARCH=$$arch go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o dist/steward-$(VERSION)-linux-$$arch/stewardd ./cmd/stewardd && \
		GOOS=linux GOARCH=$$arch go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o dist/steward-$(VERSION)-linux-$$arch/steward ./cmd/steward && \
		tar -C dist -czf dist/steward-$(VERSION)-linux-$$arch.tar.gz steward-$(VERSION)-linux-$$arch || exit 1; \
	done

# The platforms cli-dist builds the CLI for.
CLI_PLATFORMS ?= linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64

cli-dist:
	@mkdir -p dist
	for p in $(CLI_PLATFORMS); do \
		os=$${p%/*} arch=$${p#*/} ext=; [ $$os = windows ] && ext=.exe; \
		GOOS=$$os GOARCH=$$arch go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o dist/steward-cli-$(VERSION)-$$os-$$arch$$ext ./cmd/steward || exit 1; \
	done

clean:
	rm -rf bin dist
