# =============================================================================
# Copyright (c) 2026 Huawei Technologies Co., Ltd.
# openFuyao is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# =============================================================================
#
# MCO Many-Core Orchestrator — Build System
#
# Targets:
#   make build-analyzer       Build the Analyzer binary
#   make build-collector      Build the Collector binary
#   make build-plugin-so      Build the MCO scheduler plugin (.so)
#   make build-scheduler      Build Volcano vc-scheduler with plugin support
#   make image-analyzer       Build Analyzer Docker image
#   make image-collector      Build Collector Docker image
#   make image-scheduler      Build scheduler+plugin Docker image
#   make generate             Run controller-gen to regenerate deepcopy + CRD YAML
#   make tidy                 Run go mod tidy
#   make clean                Remove build artifacts
#
# Prerequisites for plugin/scheduler builds:
#   - musl toolchain (for Alpine compatibility): musl-gcc on PATH
#     Install: wget http://musl.libc.org/releases/musl-1.2.1.tar.gz && ...
#   - Docker (for image targets)
#   - Volcano v1.9.0 source checked out at ${VOLCANO_SRC}
# =============================================================================

SHELL := /bin/bash

# ── Go build settings ──
GO          ?= go
CGO_ENABLED ?= 1
MUSL_CC     ?= /usr/local/musl/bin/musl-gcc

# ── Image settings ──
REGISTRY    ?= cr.openfuyao.cn/openfuyao
TAG         ?= latest
ANALYZER_IMG   := $(REGISTRY)/mco-analyzer:$(TAG)
COLLECTOR_IMG  := $(REGISTRY)/mco-collector:$(TAG)
SCHEDULER_IMG  := $(REGISTRY)/mco-volcano-scheduler:$(TAG)

# ── Volcano source (for building vc-scheduler with plugin support) ──
VOLCANO_SRC    ?= /tmp/volcano-1.9
VOLCANO_VERSION ?= v1.9.0

# ── Output directories ──
BIN_DIR    := bin
PLUGIN_DIR := plugins

.PHONY: all clean \
        build-analyzer build-collector build-plugin-so build-scheduler \
        image-analyzer image-collector image-scheduler

all: build-analyzer build-collector

# ──────────────────────── Binary builds ────────────────────────

build-analyzer:
	@echo "=== Building Analyzer ==="
	@mkdir -p $(BIN_DIR)
	$(GO) build -o $(BIN_DIR)/analyzer ./cmd/analyzer/

build-collector:
	@echo "=== Building Collector ==="
	@mkdir -p $(BIN_DIR)
	$(GO) build -o $(BIN_DIR)/collector ./cmd/collector/

# ──────────────────────── Plugin .so build ────────────────────────

# Build the MCO scheduler plugin as a shared object (.so) compatible with
# Volcano's musl-libc based Alpine scheduler image.
#
# The plugin MUST be built with:
#   - CGO_ENABLED=1
#   - The same musl-gcc toolchain used to build vc-scheduler
#   - -buildmode=plugin
#
# The resulting .so is loaded at scheduler startup via --plugins-dir.
build-plugin-so:
	@echo "=== Building MCO Plugin .so ==="
	@mkdir -p $(PLUGIN_DIR)
	@if [ ! -f "$(MUSL_CC)" ]; then \
		echo "ERROR: musl-gcc not found at $(MUSL_CC)"; \
		echo "Install: wget http://musl.libc.org/releases/musl-1.2.1.tar.gz"; \
		exit 1; \
	fi
	CGO_ENABLED=$(CGO_ENABLED) CC=$(MUSL_CC) \
		$(GO) build -buildmode=plugin -o $(PLUGIN_DIR)/mco-plugin.so ./cmd/plugin/

# Build plugin .so in a Docker container (no local musl required).
# Output: plugins/mco-plugin.so
build-plugin-so-docker:
	@echo "=== Building MCO Plugin .so (Docker) ==="
	@mkdir -p $(PLUGIN_DIR)
	docker run --rm \
		-v $(PWD):/work \
		golang:1.24-alpine sh -c \
		"cd /work && apk add musl-dev gcc && \
		CGO_ENABLED=1 CC=/usr/bin/musl-gcc \
		go build -buildmode=plugin -o $(PLUGIN_DIR)/mco-plugin.so ./cmd/plugin/"

# ──────────────────────── Volcano scheduler build ────────────────────────

# Build vc-scheduler from Volcano source with plugin support enabled.
# Requires Volcano source at VOLCANO_SRC.
build-scheduler:
	@echo "=== Building Volcano vc-scheduler (plugin support) ==="
	@if [ ! -d "$(VOLCANO_SRC)" ]; then \
		echo "ERROR: Volcano source not found at $(VOLCANO_SRC)"; \
		echo "Clone: git clone --branch $(VOLCANO_VERSION) --depth 1 https://github.com/volcano-sh/volcano.git $(VOLCANO_SRC)"; \
		exit 1; \
	fi
	cd $(VOLCANO_SRC) && \
		CC=$(MUSL_CC) CGO_ENABLED=1 SUPPORT_PLUGINS=yes make vc-scheduler
	@mkdir -p $(BIN_DIR)
	cp $(VOLCANO_SRC)/_output/bin/vc-scheduler $(BIN_DIR)/vc-scheduler
	@echo "vc-scheduler built → $(BIN_DIR)/vc-scheduler"

# ──────────────────────── Docker images ────────────────────────

image-analyzer:
	docker build -f build/mco-analyzer.Dockerfile -t $(ANALYZER_IMG) .

image-collector:
	docker build -f build/mco-collector.Dockerfile -t $(COLLECTOR_IMG) .

# Build the scheduler+plugin image.
# Requires:
#   1. vc-scheduler binary (built from Volcano source with SUPPORT_PLUGINS=yes)
#   2. mco-plugin.so (built with musl-gcc, -buildmode=plugin)
image-scheduler:
	docker build -f build/mco-volcano-scheduler.Dockerfile -t $(SCHEDULER_IMG) .

# ──────────────────────── Utility ────────────────────────

clean:
	rm -rf $(BIN_DIR) $(PLUGIN_DIR)

# Print build environment diagnostics.
diagnostics:
	@echo "=== Build Diagnostics ==="
	@echo "Go version: $$($(GO) version)"
	@echo "Go path: $$($(GO) env GOPATH)"
	@echo "Module: $$($(GO) list -m)"
	@echo "musl-gcc: $$(which musl-gcc 2>/dev/null || echo 'NOT FOUND')"
	@echo "Docker: $$(docker --version 2>/dev/null || echo 'NOT FOUND')"
	@echo "Volcano source: $(VOLCANO_SRC) $$(test -d $(VOLCANO_SRC) && echo '(exists)' || echo '(MISSING)')"
	@echo "CGO_ENABLED: $(CGO_ENABLED)"

# ──────────────────────── Code generation ────────────────────────

# Regenerate deepcopy methods and CRD manifests.
# Requires controller-gen: go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.17.3
generate:
	@which controller-gen >/dev/null 2>&1 || { \
		echo "controller-gen not found, install with:"; \
		echo "  go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.17.3"; \
		exit 1; \
	}
	controller-gen object paths=./api/v1alpha1/
	controller-gen crd:allowDangerousTypes=true paths=./api/v1alpha1/ output:crd:artifacts:config=charts/many-core-orchestrator/crds/

# Clean go.sum and regenerate.
tidy:
	$(GO) mod tidy