# Lux Consensus C Library Makefile
CC = gcc
CXX = c++
AR = ar
CFLAGS = -Wall -Wextra -O3 -fPIC -pthread -I./include
LDFLAGS = -shared -pthread

# Platform detection
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
    DYLIB_EXT = dylib
    LDFLAGS += -dynamiclib -install_name @rpath/libluxconsensus.dylib
else
    DYLIB_EXT = so
    LDFLAGS += -Wl,-soname,libluxconsensus.so
endif

# Source files
SOURCES = src/consensus_engine.c
OBJECTS = $(SOURCES:.c=.o)

# Target files
STATIC_LIB = lib/libluxconsensus.a
SHARED_LIB = lib/libluxconsensus.$(DYLIB_EXT)
BENCHMARK_BIN = benchmark

# Build targets
all: $(STATIC_LIB) $(SHARED_LIB)

%.o: %.c
	@echo "Compiling $<..."
	$(CC) $(CFLAGS) -c $< -o $@
	@echo "Verifying object file..."
	@file $@ || (echo "ERROR: Invalid object file $@"; exit 1)
	@test -s $@ || (echo "ERROR: Empty object file $@"; exit 1)

$(STATIC_LIB): $(OBJECTS) | lib
	@echo "Creating static library $@..."
	$(AR) rcs $@ $^
	@echo "Verifying static library..."
	@file $@ || (echo "ERROR: Invalid static library $@"; exit 1)

$(SHARED_LIB): $(OBJECTS) | lib
	@echo "Creating shared library $@..."
	@echo "Object files to link: $(OBJECTS)"
	@for obj in $(OBJECTS); do echo "Checking $$obj..."; file $$obj; done
	$(CC) $(LDFLAGS) -o $@ $^
	@echo "Verifying shared library..."
	@file $@ || (echo "ERROR: Invalid shared library $@"; exit 1)

lib:
	mkdir -p lib

clean:
	rm -f $(OBJECTS)
	rm -f $(STATIC_LIB) $(SHARED_LIB)
	rm -rf lib
	rm -rf test/bin

install: $(STATIC_LIB) $(SHARED_LIB)
	install -d /usr/local/lib
	install -d /usr/local/include
	install -m 644 $(STATIC_LIB) /usr/local/lib/
	install -m 755 $(SHARED_LIB) /usr/local/lib/
	install -m 644 include/lux_consensus.h /usr/local/include/

test: $(SHARED_LIB)
	@echo "Building C test suite..."
	@mkdir -p test/bin
	$(CC) $(CFLAGS) -o test/bin/test_consensus test/test_consensus.c -L./lib -lluxconsensus -pthread
	@echo "Running C tests..."
	@if [ "$(UNAME_S)" = "Darwin" ]; then \
		DYLD_LIBRARY_PATH=./lib ./test/bin/test_consensus; \
	else \
		LD_LIBRARY_PATH=./lib ./test/bin/test_consensus; \
	fi

test-cpp: $(STATIC_LIB)
	@echo "Building C++ consumer example (links libluxconsensus statically)..."
	@mkdir -p examples/bin
	$(CXX) -std=c++17 -Iinclude -o examples/bin/cpp_consumer examples/cpp_consumer.cpp $(STATIC_LIB) -pthread
	@echo "Running C++ consumer..."
	@./examples/bin/cpp_consumer

test-keeper: $(STATIC_LIB)
	@echo "Building Keeper-on-Quasar state machine proof (links libluxconsensus statically)..."
	@mkdir -p examples/bin
	$(CXX) -std=c++17 -Iinclude -o examples/bin/keeper_quasar examples/keeper_quasar.cpp $(STATIC_LIB) -pthread
	@echo "Running Keeper-on-Quasar proof..."
	@./examples/bin/keeper_quasar

$(BENCHMARK_BIN): benchmark.c $(SHARED_LIB)
	@echo "Building benchmark..."
	$(CC) $(CFLAGS) -O3 -o $@ $< -L./lib -lluxconsensus -pthread

run-benchmark: $(BENCHMARK_BIN)
	@echo "Running benchmarks..."
	@if [ "$(UNAME_S)" = "Darwin" ]; then \
		DYLD_LIBRARY_PATH=./lib ./$(BENCHMARK_BIN); \
	else \
		LD_LIBRARY_PATH=./lib ./$(BENCHMARK_BIN); \
	fi

.PHONY: all clean install test run-benchmark