APP_NAME := ric930-fake-smtp
VERSION ?= 1.1.0

GO := go

BUILD_DIR := builds
LINUX_DIR := $(BUILD_DIR)/linux
WINDOWS_DIR := $(BUILD_DIR)/windows
RELEASE_DIR := $(BUILD_DIR)/releases

LINUX_BIN := $(LINUX_DIR)/$(APP_NAME)
WINDOWS_BIN := $(WINDOWS_DIR)/$(APP_NAME).exe

LINUX_ARCHIVE := $(RELEASE_DIR)/$(APP_NAME)_$(VERSION)_linux_amd64.tar.gz
WINDOWS_ARCHIVE := $(RELEASE_DIR)/$(APP_NAME)_$(VERSION)_windows_amd64.zip

BUILD_FLAGS := -trimpath
LDFLAGS := -s -w


.PHONY: all
.PHONY: build
.PHONY: build-all
.PHONY: build-linux
.PHONY: build-windows
.PHONY: release
.PHONY: package-linux
.PHONY: package-windows
.PHONY: clean
.PHONY: fmt
.PHONY: tidy
.PHONY: check


# ============================================================
# Host OS helpers
# ============================================================

ifeq ($(OS),Windows_NT)

define remove_dir
	@if exist "$(subst /,\,$(1))" rmdir /S /Q "$(subst /,\,$(1))"
endef

define make_dir
	@if not exist "$(subst /,\,$(1))" mkdir "$(subst /,\,$(1))"
endef

define copy_file
	@copy /Y "$(subst /,\,$(1))" "$(subst /,\,$(2))" >NUL
endef

define copy_dir
	@if exist "$(subst /,\,$(2))" rmdir /S /Q "$(subst /,\,$(2))"
	@xcopy /E /I /Y "$(subst /,\,$(1))" "$(subst /,\,$(2))" >NUL
endef

else

define remove_dir
	@rm -rf "$(1)"
endef

define make_dir
	@mkdir -p "$(1)"
endef

define copy_file
	@cp "$(1)" "$(2)"
endef

define copy_dir
	@rm -rf "$(2)"
	@cp -R "$(1)" "$(2)"
endef

endif


# ============================================================
# Default targets
# ============================================================

all: build-all

build: build-all

build-all: build-linux build-windows


# ============================================================
# Linux build
# ============================================================

build-linux:
	@echo "==> Building Linux amd64"

	$(call remove_dir,$(LINUX_DIR))
	$(call make_dir,$(LINUX_DIR))

ifeq ($(OS),Windows_NT)
	@set "CGO_ENABLED=0" && \
	set "GOOS=linux" && \
	set "GOARCH=amd64" && \
	$(GO) build \
		$(BUILD_FLAGS) \
		-ldflags="$(LDFLAGS)" \
		-o "$(subst /,\,$(LINUX_BIN))" \
		.
else
	@CGO_ENABLED=0 \
	GOOS=linux \
	GOARCH=amd64 \
	$(GO) build \
		$(BUILD_FLAGS) \
		-ldflags="$(LDFLAGS)" \
		-o "$(LINUX_BIN)" \
		.
endif

	$(call copy_file,config.yaml,$(LINUX_DIR)/config.yaml)
	$(call copy_dir,web,$(LINUX_DIR)/web)

	@echo "==> Linux build created: $(LINUX_DIR)"


# ============================================================
# Windows build
# ============================================================

build-windows:
	@echo "==> Building Windows amd64"

	$(call remove_dir,$(WINDOWS_DIR))
	$(call make_dir,$(WINDOWS_DIR))

ifeq ($(OS),Windows_NT)
	@set "CGO_ENABLED=0" && \
	set "GOOS=windows" && \
	set "GOARCH=amd64" && \
	$(GO) build \
		$(BUILD_FLAGS) \
		-ldflags="$(LDFLAGS)" \
		-o "$(subst /,\,$(WINDOWS_BIN))" \
		.
else
	@CGO_ENABLED=0 \
	GOOS=windows \
	GOARCH=amd64 \
	$(GO) build \
		$(BUILD_FLAGS) \
		-ldflags="$(LDFLAGS)" \
		-o "$(WINDOWS_BIN)" \
		.
endif

	$(call copy_file,config.yaml,$(WINDOWS_DIR)/config.yaml)
	$(call copy_dir,web,$(WINDOWS_DIR)/web)

	@echo "==> Windows build created: $(WINDOWS_DIR)"


# ============================================================
# Release
# ============================================================

release: build-all package-linux package-windows
	@echo ""
	@echo "==> Release $(VERSION) created"
	@echo "    Linux:   $(LINUX_ARCHIVE)"
	@echo "    Windows: $(WINDOWS_ARCHIVE)"


# ============================================================
# Linux package
# ============================================================

package-linux:
	@echo "==> Creating Linux release archive"
	$(call make_dir,$(RELEASE_DIR))

ifeq ($(OS),Windows_NT)
	@tar \
		-C "$(subst /,\,$(LINUX_DIR))" \
		-czf "$(subst /,\,$(LINUX_ARCHIVE))" \
		.
else
	@tar \
		-C "$(LINUX_DIR)" \
		-czf "$(LINUX_ARCHIVE)" \
		.
endif

	@echo "==> Linux archive created: $(LINUX_ARCHIVE)"


# ============================================================
# Windows package
# ============================================================

package-windows:
	@echo "==> Creating Windows release archive"
	$(call make_dir,$(RELEASE_DIR))

ifeq ($(OS),Windows_NT)
	@powershell -NoProfile -Command \
		"Compress-Archive \
		-Path '$(subst /,\,$(WINDOWS_DIR))\*' \
		-DestinationPath '$(subst /,\,$(WINDOWS_ARCHIVE))' \
		-Force"
else
	@rm -f "$(WINDOWS_ARCHIVE)"
	@cd "$(WINDOWS_DIR)" && \
	zip -qr \
		"../releases/$(APP_NAME)_$(VERSION)_windows_amd64.zip" \
		.
endif

	@echo "==> Windows archive created: $(WINDOWS_ARCHIVE)"


# ============================================================
# Maintenance
# ============================================================

clean:
	@echo "==> Cleaning build directory"
	$(call remove_dir,$(BUILD_DIR))


fmt:
	@echo "==> Formatting Go sources"
	@$(GO) fmt ./...


tidy:
	@echo "==> Updating Go modules"
	@$(GO) mod tidy


check:
	@echo "==> Running Go checks"
	@$(GO) vet ./...
	@$(GO) test ./...

