# Sorcery-Go Sovereign Coven - Multi-Arch Makefile
# "The Forge is hot. The Warding is strong. The Coven is ready."

BINARY       = sorcery
VERSION     ?= 1.1.0
BUILD_DIR   := build
GO_FLAGS    := -ldflags="-s -w -X main.Version=$(VERSION)"
CGO         ?= 0
PREFIX      ?= /usr/local/sbin
STATE_ROOT  ?= /var/lib/sorcery-go
SPOOL_DIR   ?= /var/spool/sorcery-go

.PHONY: all build x86_64 aarch64 static clean test lint install caps check-efficiency uninstall smgl-help smgl-extract smgl-mount smgl-unmount smgl-inject-sorcery smgl-inject-kernel smgl-inject-sorcery-go smgl-enter ebpf

all: x86_64 aarch64

# Host-architecture build (dev / CI)
build:
        @echo "⚡ Compiling Sorcery-Go (host arch)..."
        CGO_ENABLED=$(CGO) go build $(GO_FLAGS) -o $(BUILD_DIR)/$(BINARY) ./cmd/sorcery
        @echo "✓ Built $(BUILD_DIR)/$(BINARY)"

# x86_64 target (default container fleet)
x86_64:
        @echo "⚡ Forging x86_64 binary..."
        GOOS=linux GOARCH=amd64 CGO_ENABLED=$(CGO) \
        go build $(GO_FLAGS) -o $(BUILD_DIR)/$(BINARY)-x86_64 ./cmd/sorcery
        @echo "✓ Built $(BUILD_DIR)/$(BINARY)-x86_64"

# AArch64 target (edge nodes / ARM containers)
aarch64:
        @echo "⚡ Forging aarch64 binary..."
        GOOS=linux GOARCH=arm64 CGO_ENABLED=$(CGO) \
        go build $(GO_FLAGS) -o $(BUILD_DIR)/$(BINARY)-aarch64 ./cmd/sorcery
        @echo "✓ Built $(BUILD_DIR)/$(BINARY)-aarch64"

# Strictly static, hermetic build (for rescue / Portable Bin bootstrap)
static:
        @echo "⚡ Forging static (musl-compatible) binary..."
        CGO_ENABLED=0 go build $(GO_FLAGS) \
        -o $(BUILD_DIR)/$(BINARY)-static ./cmd/sorcery
        @echo "✓ Built $(BUILD_DIR)/$(BINARY)-static"

# Apply Linux capabilities (CAP_SYS_ADMIN for OverlayFS, CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_BPF for eBPF)
caps: build
        @echo "🛡  Applying Linux capabilities..."
        setcap 'cap_sys_admin,cap_chown,cap_dac_override,cap_bpf+ep' $(BUILD_DIR)/$(BINARY)
        @echo "✓ Capabilities applied (includes CAP_BPF for eBPF Tomb Guard)."

# Install to PREFIX (default /usr/local/sbin). Coexists with the legacy
# /usr/sbin/sorcery — installs as `sorcery-go` so both tools can run side
# by side during the migration.
install: build
        @echo "📦 Installing to $(PREFIX)/sorcery-go..."
        install -d $(PREFIX)
        install -m 755 $(BUILD_DIR)/$(BINARY) $(PREFIX)/sorcery-go
        @echo "✓ Installed. Run 'sudo $(PREFIX)/sorcery-go init' to bootstrap."

# Drop-in install for an existing Source Mage chroot: install binary,
# create state dirs, init DB, apply capabilities.
drop-in: install
        @echo "⚡ Drop-in setup for Source Mage chroot..."
        mkdir -p $(STATE_ROOT)/{state,tomb/{epitaphs,blobs},build,log,ebpf/maps}
        mkdir -p $(SPOOL_DIR)
        chmod 700 $(STATE_ROOT)/state $(STATE_ROOT)/tomb
        setcap 'cap_sys_admin,cap_chown,cap_dac_override,cap_bpf+ep' $(PREFIX)/sorcery-go || true
        SORCERY_GO_ROOT=$(STATE_ROOT) SORCERY_GO_SPOOL=$(SPOOL_DIR) \
        $(PREFIX)/sorcery-go init --force
        @echo "✓ Drop-in complete. Try: sudo $(PREFIX)/sorcery-go cast busybox --static --default"

# Remove the installed binary (does NOT touch /var/lib/sorcery-go state).
uninstall:
        rm -f $(PREFIX)/sorcery-go
        @echo "✓ Uninstalled (state at $(STATE_ROOT) preserved)."

# Run the test suite (DAG cycle detection, Warding, Legal, Tomb)
test:
        go test -v ./pkg/...

# Lightweight linter pass
lint:
        go vet ./...
        @if command -v golangci-lint >/dev/null 2>&1; then golangci-lint run; fi

# "Self-Check" — grimoire lint + fsck of Tomb
check-efficiency:
        @echo "🔮 Scanning Grimoire for redundant dependencies..."
        ./$(BUILD_DIR)/$(BINARY) legal audit --all
        @echo "🪦 Checking Tomb for bit-rot..."
        ./$(BUILD_DIR)/$(BINARY) tomb verify --all

clean:
        rm -rf $(BUILD_DIR)/*
        rm -f pkg/warding/ebpf/c/*.bpf.o
        rm -f pkg/warding/ebpf/*.go.bpf.*
        @echo "✓ Cleaned build artifacts."

# Compile eBPF C programs to .bpf.o using clang + bpf2go.
# Requires: clang, llvm, linux-headers, bpftool
# This is optional — the ebpf package falls back to programmatic map
# creation if no .bpf.o files are present (maps work, programs are stubs).
ebpf:
        @echo "⚡ Compiling eBPF programs..."
        @if ! command -v clang >/dev/null 2>&1; then \
                echo "  clang not found — skipping eBPF compilation (maps-only mode)."; \
                echo "  Install clang + llvm + linux-headers for full eBPF enforcement."; \
                exit 0; \
        fi
        cd pkg/warding/ebpf && go generate ./...
        @echo "✓ eBPF programs compiled."

# =============================================================================
# Source Mage chroot resurrection helpers
# =============================================================================
# Thin wrappers around scripts/smgl-getting-started.sh so you can drive the
# whole 9-phase pipeline from make. See docs/GETTING_STARTED_SMGL_CHROOT.md
# for the full walkthrough.
#
# Example:
#   sudo make smgl-extract TARBALL=~/Downloads/smgl-0.62-11.tar.xz MP=/mnt/smgl
#   sudo make smgl-mount MP=/mnt/smgl
#   sudo make smgl-inject-sorcery MP=/mnt/smgl
#   sudo make smgl-inject-kernel MP=/mnt/smgl BZIMAGE=/usr/src/linux/arch/x86/boot/bzImage
#   sudo make smgl-inject-sorcery-go MP=/mnt/smgl
#   sudo make smgl-enter MP=/mnt/smgl
#   # inside chroot: smgl-getting-started.sh chroot-scribe-test etc.
#   sudo make smgl-unmount MP=/mnt/smgl

smgl-help:
        @./scripts/smgl-getting-started.sh --help

smgl-extract:
        @./scripts/smgl-getting-started.sh extract "$(TARBALL)" "$(MP)"

smgl-mount:
        @./scripts/smgl-getting-started.sh mount "$(MP)"

smgl-unmount:
        @./scripts/smgl-getting-started.sh unmount "$(MP)"

smgl-inject-sorcery:
        @./scripts/smgl-getting-started.sh inject-sorcery "$(MP)" $(SORCERY_TARBALL)

smgl-inject-kernel:
        @./scripts/smgl-getting-started.sh inject-kernel "$(MP)" "$(BZIMAGE)" $(MODULES_DIR)

smgl-inject-sorcery-go:
        @./scripts/smgl-getting-started.sh inject-sorcery-go "$(MP)" $(SORCERY_GO_BIN)

smgl-enter:
        @./scripts/smgl-getting-started.sh enter "$(MP)"
