# Makefile for HPRLP Pure C Examples

# Path to HPRLP installation
HPRLP_ROOT := ../..
HPRLP_LIB_DIR := $(HPRLP_ROOT)/lib
HPRLP_INCLUDE_DIR := $(HPRLP_ROOT)/include

# Auto-detect CUDA
CUDA_PATH ?= $(shell if [ -n "$${CUDA_HOME}" ] && [ -x "$${CUDA_HOME}/bin/nvcc" ]; then echo "$${CUDA_HOME}"; \
                      elif [ -d /usr/local/cuda ]; then echo /usr/local/cuda; \
                      elif [ -d /opt/cuda ]; then echo /opt/cuda; \
                      elif command -v nvcc >/dev/null 2>&1; then dirname $$(dirname $$(command -v nvcc)); \
                      else echo /usr/local/cuda; fi)

NVCC := $(CUDA_PATH)/bin/nvcc

# Check if nvcc exists
ifeq ($(shell test -x $(NVCC) && echo yes),)
    $(error CUDA compiler not found at $(NVCC))
endif

# Match the core build's centralized GPU detector and preserve GPU_SM as an
# explicit cross-build override.
CUDA_ARCH_DETECTOR := $(HPRLP_ROOT)/scripts/detect_cuda_arch.sh
DETECTED_SM := $(strip $(shell bash $(CUDA_ARCH_DETECTOR)))
SELECTED_SM := $(if $(strip $(GPU_SM)),$(strip $(GPU_SM)),$(DETECTED_SM))

ifeq ($(SELECTED_SM),)
	CUDA_ARCH :=
else
	CUDA_ARCH := -arch=sm_$(SELECTED_SM)
endif

# Compiler flags for pure C
# Note: NVCC doesn't have --std=c99, but compiles C code by default when using -x cu
NVCC_FLAGS := -w -O2 $(CUDA_ARCH) -x cu
INCLUDES := -I$(HPRLP_INCLUDE_DIR) -I$(CUDA_PATH)/include

# CUDA library path
CUDA_LIB_DIR := $(shell if [ -d $(CUDA_PATH)/lib64 ]; then echo $(CUDA_PATH)/lib64; \
                         else echo $(CUDA_PATH)/lib; fi)

# Linker flags
LIB_DIRS := -L$(HPRLP_LIB_DIR) -L$(CUDA_LIB_DIR)
LIBS := -lhprlp -lcublas -lcusolver -lcusparse -lstdc++
LDFLAGS := -Xlinker -rpath -Xlinker $(HPRLP_LIB_DIR)

# Targets
EXAMPLE_DIRECT := example_direct_lp
EXAMPLE_MPS := example_mps_file
EXAMPLE_BATCHED := example_batched_lp

all: $(EXAMPLE_DIRECT) $(EXAMPLE_MPS) $(EXAMPLE_BATCHED)

$(EXAMPLE_DIRECT): example_direct_lp.c
	@echo "Building $(EXAMPLE_DIRECT) (Pure C)..."
	@if [ ! -f $(HPRLP_LIB_DIR)/libhprlp.a ]; then \
		echo "Error: libhprlp.a not found. Please run 'make' in $(HPRLP_ROOT) first."; \
		exit 1; \
	fi
	@if [ ! -f $(HPRLP_LIB_DIR)/libhprlp.so ]; then \
		echo "Building shared library..."; \
		cd $(HPRLP_ROOT) && make shared; \
	fi
	@$(NVCC) $(NVCC_FLAGS) $(INCLUDES) -o $@ $< $(LIB_DIRS) $(LIBS) $(LDFLAGS)
	@echo "Built: $@"

$(EXAMPLE_MPS): example_mps_file.c
	@echo "Building $(EXAMPLE_MPS) (Pure C)..."
	@if [ ! -f $(HPRLP_LIB_DIR)/libhprlp.a ]; then \
		echo "Error: libhprlp.a not found. Please run 'make' in $(HPRLP_ROOT) first."; \
		exit 1; \
	fi
	@if [ ! -f $(HPRLP_LIB_DIR)/libhprlp.so ]; then \
		echo "Building shared library..."; \
		cd $(HPRLP_ROOT) && make shared; \
	fi
	@$(NVCC) $(NVCC_FLAGS) $(INCLUDES) -o $@ $< $(LIB_DIRS) $(LIBS) $(LDFLAGS)
	@echo "Built: $@"

$(EXAMPLE_BATCHED): example_batched_lp.c
	@echo "Building $(EXAMPLE_BATCHED) (Pure C)..."
	@if [ ! -f $(HPRLP_LIB_DIR)/libhprlp.a ]; then \
		echo "Error: libhprlp.a not found. Please run 'make' in $(HPRLP_ROOT) first."; \
		exit 1; \
	fi
	@if [ ! -f $(HPRLP_LIB_DIR)/libhprlp.so ]; then \
		echo "Building shared library..."; \
		cd $(HPRLP_ROOT) && make shared; \
	fi
	@$(NVCC) $(NVCC_FLAGS) $(INCLUDES) -o $@ $< $(LIB_DIRS) $(LIBS) $(LDFLAGS)
	@echo "Built: $@"

clean:
	@rm -f $(EXAMPLE_DIRECT) $(EXAMPLE_MPS) $(EXAMPLE_BATCHED)

run-direct: $(EXAMPLE_DIRECT)
	@./$(EXAMPLE_DIRECT)

run-mps: $(EXAMPLE_MPS)
	@./$(EXAMPLE_MPS)

run-batched: $(EXAMPLE_BATCHED)
	@./$(EXAMPLE_BATCHED)

run: $(EXAMPLE_DIRECT) $(EXAMPLE_MPS) $(EXAMPLE_BATCHED)
	@echo "Running example_direct_lp..."
	@./$(EXAMPLE_DIRECT)
	@echo ""
	@echo "Running example_mps_file..."
	@./$(EXAMPLE_MPS)
	@echo ""
	@echo "Running example_batched_lp..."
	@./$(EXAMPLE_BATCHED)

help:
	@echo "HPRLP Pure C Examples"
	@echo ""
	@echo "Usage:"
	@echo "  make              - Build all examples"
	@echo "  make run          - Build and run all examples"
	@echo "  make run-direct   - Build and run direct LP example"
	@echo "  make run-mps      - Build and run MPS file example"
	@echo "  make run-batched  - Build and run batched shared-A example"
	@echo "  make clean        - Remove all executables"
	@echo ""
	@echo "Targets:"
	@echo "  example_direct_lp  - Solve LP from raw arrays (Pure C)"
	@echo "  example_mps_file   - Solve LP from MPS file (Pure C)"
	@echo "  example_batched_lp - Solve a batch sharing one sparse A (Pure C)"
	@echo ""
	@echo "Note: These examples use pure C (no C++ features) to demonstrate"
	@echo "      that the HPRLP API is fully C-compatible."
	@echo ""
	@echo "Note: libhprlp.a must be built first (run 'make' in $(HPRLP_ROOT))"

.PHONY: all clean run run-direct run-mps run-batched help
