# MoloApp root Makefile. Aggregates the per-part subdir fragments:
# each part ships src/<part>/<part>.mk (plus example/example.mk).
# Targets: all, test, clean, interop, lint.
#
# Composition rules used here:
# - Double-colon all::/test::/clean:: so supervisor.mk and example.mk can
#   append their own branches without editing this file.
# - Fragments are included byte-exact from the parts; integration-only
#   wiring (missing rules, missing pattern edges) lives below the includes
#   and is marked INTEGRATION.

CXX ?= g++
CXXFLAGS ?= -std=c++23 -O2 -Wall -Wextra -pthread
AR ?= ar

# Consumed by src/runtime/runtime.mk (verified runtime flags).
MOLO_CXXFLAGS ?= -std=c++23 -O1 -g -Wall -Wextra -Werror -Isrc
MOLO_ALL =
MOLO_TEST_BINS =
MOLO_INTEROP =

# Default goal is `all`: these are the first ordinary targets in this file.
all::
test::
clean::
	rm -rf build

# Operability first: supervisor.mk and cli.mk reference OPERABILITY_LIB.
-include src/operability.mk
-include src/runtime/runtime.mk
-include src/observability/observability.mk
-include src/security/security.mk
-include src/data/data.mk
-include src/app/app.mk
-include src/realtime/realtime.mk
-include src/supervisor/supervisor.mk
-include src/clients/clients.mk
# NOTE: supplychain.mk and operability.mk precede cli.mk and supervisor.mk
# so SUPPLY_LIB / OPERABILITY_LIB are defined when those add link edges
# (supply PATCHES section 2, operability PATCHES sections 5-6 and 10).
-include src/supplychain.mk
-include src/cli/cli.mk
-include src/tenancy.mk
-include src/audit.mk
-include src/governance.mk
-include example/example.mk

# --- all wiring (INTEGRATION; supervisor/example self-append via all::) ---
all:: $(MOLO_ALL)
all:: $(OBS_LIB)
all:: security-all
all:: data-all
all:: app-build
all:: $(REALTIME_LIB)
all:: clients
all:: $(MOLO_BIN)
all:: tenancy-tests
all:: audit-tests
all:: operability-tests
all:: govern-build
all:: supply-all

# --- test wiring (INTEGRATION; supervisor/example self-append via test::) --
test:: $(MOLO_TEST_BINS)
	set -e; for t in $(MOLO_TEST_BINS); do ./$$t; done
test:: obs-test
test:: security-test
test:: data-test
test:: app-test
test:: realtime-test
test:: clients-test
test:: cli-test
test:: tenancy-check
test:: audit-check
test:: operability-check
test:: govern-test
test:: supply-test

# --- data rules (INTEGRATION: data.mk ships variables only, no rules) ------
# Mirrors the verified standalone flags (src/data/Makefile): header-only
# lib, one binary per suite, -Isrc/data -Itests/src/data.
DATA_BINS = $(addprefix build/data/test_,$(DATA_TESTS))

data-all: $(DATA_BINS)

build/data/test_%: tests/src/data/test_%.cpp $(DATA_HEADERS) tests/src/data/mini.hpp
	@mkdir -p build/data
	$(CXX) $(CXXFLAGS) -Isrc/data -Itests/src/data $< -o $@

data-test: data-all
	@for t in $(DATA_BINS); do echo "== $$t"; ./$$t || exit 1; done
	@echo "data: all suites green"

data-clean:
	rm -rf build/data

# --- realtime test runner (INTEGRATION: realtime.mk ships bins, no runner) --
realtime-test: $(REALTIME_TESTS)
	@pass=0; fail=0; \
	for t in $(REALTIME_TESTS); do \
	  if ./$$t; then pass=$$((pass+1)); else fail=$$((fail+1)); \
	    echo "FAIL: $$t"; fi; \
	done; \
	echo "realtime tests passed=$$pass failed=$$fail"; \
	test $$fail -eq 0

# --- cli main object (INTEGRATION: cli.mk's build/obj/%.o pattern cannot ----
# derive build/obj/src/cli/main.cpp.o from src/cli/main.cpp, since the stem
# would require a nonexistent src/cli/main.cpp.cpp. Explicit edge fixes it;
# `make -f src/cli/cli.mk -n build/obj/src/cli/main.cpp.o` fails without it.
$(CLI_MAIN_OBJ): src/cli/main.cpp
	@mkdir -p $(dir $@)
	$(CXX) $(CXXFLAGS) $(CLI_INC) -c $< -o $@

# --- interop (runtime loopback servers; kept out of `test` per the ---------
# runtime author's own split between `test` and `interop`) ------------------
interop: $(MOLO_ALL)
	set -e; for t in $(MOLO_INTEROP); do $(MAKE) $$t; done

# --- lint (referenced by AGENTS.md; falls back to the warning-free build) --
lint: all
	@if grep -rl --exclude-dir=build "$$(printf '\342\200\224')" src tests example Makefile 2>/dev/null; then \
	  echo "lint: em dash found"; exit 1; \
	else echo "lint: no em dash, build warning-free"; fi

# --- audit test runner (INTEGRATION: audit.mk builds bins, no runner) ---------
audit-check: audit-tests
	@for t in $(AUDIT_TEST_BINS); do echo "== $$t"; ./$$t || exit 1; done
	@echo "audit: all suites green"

# --- operability production link (INTEGRATION: with the base tree present ---
# the real supervisor/common Clock/KvStore/Observer satisfy the includes, so
# their TU definitions ride along on the test link lines).
OPERABILITY_TEST_SRCS += src/supervisor/common/clock.cpp
OPERABILITY_TEST_SRCS += src/supervisor/common/kv_store.cpp
OPERABILITY_TEST_SRCS += src/supervisor/common/observer.cpp

.PHONY: all test clean interop lint data-all data-test data-clean realtime-test cli-test audit-check
