# DESI Explorer — root Makefile
#
# Lean orchestrator: the "base" commands (`run`, `build`, `test`, ...) delegate
# into the per-project Makefiles in `gui/`, `api/`, and `infra/`. Project-
# specific commands live in those directories and are reached with
# `make -C
` (or the thin passthrough targets below).
GUI := gui
API := api
INFRA := infra
# Local dev/test assets live under resources/dev. These are the defaults for
# the run/*-web targets; override any of them on the command line, e.g.
# make run GUI_ENV_FILE=/path/to/gui.env API_DESI_DATA=/path/to/data.json
RESOURCE_DIR := $(CURDIR)/resources/dev
GUI_ENV_FILE ?= $(RESOURCE_DIR)/gui.env.example
API_ENV_FILE ?= $(RESOURCE_DIR)/api.env.example
API_DESI_DATA ?= $(RESOURCE_DIR)/desi_subset.json
# The API binds here for local dev (see api/src/config.rs); `make run` passes
# it through and waits for $(API_HEALTH_URL) to respond before launching the
# GUI, so the renderer never races the API on startup. A bind host of
# 0.0.0.0 is probed via 127.0.0.1. Adjust API_WAIT_TIMEOUT (seconds) if the
# API takes longer than 60s to become healthy on a given machine.
API_BIND_ADDR ?= 127.0.0.1:8080
API_HEALTH_URL := http://$(subst 0.0.0.0,127.0.0.1,$(API_BIND_ADDR))/health
API_WAIT_TIMEOUT ?= 60
.PHONY: help setup run run-web build build-debug build-web test clean fmt \
api-wait renovate-validate
help: ## List available targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
@echo ""
@echo "Sub-project targets:"
@echo " \033[36mmake -C gui help\033[0m Odin renderer (run, build, build-web, test, fmt, ...)"
@echo " \033[36mmake -C api help\033[0m Rust API (run, build, test, check, fmt, ...)"
@echo " \033[36mmake -C infra help\033[0m Infra (preview, up, down, refresh, test, ...)"
## ---- Setup ---------------------------------------------------------------
setup: ## Setup all sub-projects (submodules, gui deps, api deps, infra deps)
@git submodule update --init --recursive
@$(MAKE) -C $(GUI) setup
@$(MAKE) -C $(API) setup
@$(MAKE) -C $(INFRA) tidy
## ---- Renderer (Odin) -----------------------------------------------------
run: ## Run the native app (gui/); waits for the API to be healthy first
@API_ENV_FILE="$(API_ENV_FILE)" API_DESI_DATA="$(API_DESI_DATA)" API_BIND_ADDR="$(API_BIND_ADDR)" $(MAKE) -C $(API) run & api_pid=$$!; \
trap 'kill $$api_pid 2>/dev/null' INT TERM EXIT; \
$(MAKE) api-wait || { kill $$api_pid 2>/dev/null; exit 1; }; \
GUI_ENV_FILE="$(GUI_ENV_FILE)" $(MAKE) -C $(GUI) run; \
kill $$api_pid 2>/dev/null
build: ## Release build (gui/ + api/)
@$(MAKE) -C $(GUI) build
@$(MAKE) -C $(API) build
build-debug: ## Debug build (gui/ + api/)
@$(MAKE) -C $(GUI) build-debug
@$(MAKE) -C $(API) build
build-web: ## WebAssembly build -> build/web (gui/, needs emscripten)
@$(MAKE) -C $(GUI) build-web
run-web: ## Start WASM build + API server for web dev (waits for API health)
@API_ENV_FILE="$(API_ENV_FILE)" API_DESI_DATA="$(API_DESI_DATA)" API_BIND_ADDR="$(API_BIND_ADDR)" $(MAKE) -C $(API) run & api_pid=$$!; \
trap 'kill $$api_pid 2>/dev/null' INT TERM EXIT; \
$(MAKE) api-wait || { kill $$api_pid 2>/dev/null; exit 1; }; \
GUI_ENV_FILE="$(GUI_ENV_FILE)" $(MAKE) -C $(GUI) build-web; \
kill $$api_pid 2>/dev/null
## ---- Dev helpers ----------------------------------------------------------
api-wait: ## Poll the API health endpoint until it responds (or times out)
@echo "Waiting for API at $(API_HEALTH_URL) ..."; \
elapsed=0; \
while ! curl -sf "$(API_HEALTH_URL)" >/dev/null 2>&1; do \
elapsed=$$((elapsed + 1)); \
if [ "$${elapsed}" -ge "$(API_WAIT_TIMEOUT)" ]; then \
echo "Error: API at $(API_HEALTH_URL) not healthy after $(API_WAIT_TIMEOUT)s" >&2; \
exit 1; \
fi; \
sleep 1; \
done; \
echo "API is up."
## ---- Aggregates ----------------------------------------------------------
test: ## Test all projects (odin + cargo + go)
@$(MAKE) -C $(GUI) test
@$(MAKE) -C $(API) test
@$(MAKE) -C $(INFRA) test
clean: ## Remove build artifacts from all projects
@$(MAKE) -C $(GUI) clean
@$(MAKE) -C $(API) clean
@$(MAKE) -C $(INFRA) clean
fmt: ## Format all projects (odin + rust)
@$(MAKE) -C $(GUI) fmt
@$(MAKE) -C $(API) fmt
## ---- Passthrough to sub-project Makefiles --------------------------------
api-%: ## Forward a target to the api/ Makefile
@$(MAKE) -C $(API) $*
infra-%: ## Forward a target to the infra/ Makefile
@$(MAKE) -C $(INFRA) $*
## ---- Tooling -------------------------------------------------------------
renovate-validate: ## Validate renovate.json
bunx --package renovate renovate-config-validator renovate.json --strict