# ===== Compilers (override from env if you like) =====
CC      ?= gcc
CXX     ?= g++
# OpenCilk typically needs clang++; override if different
CILK_CXX ?= clang++

# ===== Optimization / Debug flags =====
CFLAGS   ?= -O2 -g -std=c11
CXXFLAGS ?= -O2 -g -std=c++17

# ===== Per-framework flags =====
# OpenMP: works with GCC out of the box; with Clang you need libomp installed
OMP_FLAGS   ?= -fopenmp

# Pthreads
PTHREAD_FLAGS ?= -pthread

# OpenCilk
CILK_FLAGS ?= -fopencilk -Wno-pass-failed

# TBB: try pkg-config; fall back to -ltbb
TBB_CFLAGS  := $(shell pkg-config --cflags tbb 2>/dev/null)
TBB_LDFLAGS := $(shell pkg-config --libs   tbb 2>/dev/null)
ifeq ($(strip $(TBB_LDFLAGS)),)
  TBB_LDFLAGS := -ltbb
endif

# ===== Targets =====
BIN_SEQ   := fib-seq
BIN_OMP   := fib-omp
BIN_PTH   := fib-pth
BIN_CILK  := fib-cilk
BIN_TBB   := fib-tbb
BIN_CFOR  := for-cilk
BIN_CFOR2 := for-cilk2

ALL_BINS := $(BIN_SEQ) $(BIN_OMP) $(BIN_PTH) $(BIN_CILK) $(BIN_TBB) $(BIN_CFOR) $(BIN_CFOR2)

.PHONY: all clean help
all: $(ALL_BINS)

help:
	@echo "Targets:"
	@echo "  all        - build all"
	@echo "  clean      - remove binaries and intermediates"
	@echo "Binaries:"
	@printf "  %-10s <- fib-seq.c\n"   "$(BIN_SEQ)"
	@printf "  %-10s <- fib-omp.c (OpenMP)\n" "$(BIN_OMP)"
	@printf "  %-10s <- fib-pth.c (pthread)\n" "$(BIN_PTH)"
	@printf "  %-10s <- fib-cilk.cpp (OpenCilk)\n" "$(BIN_CILK)"
	@printf "  %-10s <- fib-tbb.cpp (oneTBB)\n" "$(BIN_TBB)"
	@printf "  %-10s <- for-cilk.cpp (OpenCilk)\n" "$(BIN_CFOR)"
	@printf "  %-10s <- for-cilk2.cpp (OpenCilk, reducer)\n" "$(BIN_CFOR2)"
	@echo ""
	@echo "Override compilers/flags, e.g.:"
	@echo "  make CXX=clang++ CC=gcc CILK_CXX=clang++"
	@echo "  make TBB_CFLAGS='...' TBB_LDFLAGS='...'"

# ===== Build rules =====

# fib-seq (plain C)
$(BIN_SEQ): fib-seq.c
	$(CC) $(CFLAGS) -o $@ $<

# fib-omp (OpenMP)
$(BIN_OMP): fib-omp.c
	$(CC) $(CFLAGS) $(OMP_FLAGS) -o $@ $<

# fib-pth (pthread)
$(BIN_PTH): fib-pth.c
	$(CC) $(CFLAGS) $(PTHREAD_FLAGS) -o $@ $<

# fib-cilk (OpenCilk C++)
$(BIN_CILK): fib-cilk.cpp
	$(CILK_CXX) $(CXXFLAGS) $(CILK_FLAGS) -o $@ $<

# for-cilk (OpenCilk C++)
$(BIN_CFOR): for-cilk.cpp
	$(CILK_CXX) $(CXXFLAGS) $(CILK_FLAGS) -o $@ $<

# for-cilk2 (OpenCilk C++)
$(BIN_CFOR2): for-cilk2.cpp
	$(CILK_CXX) $(CXXFLAGS) $(CILK_FLAGS) -o $@ $<

# fib-tbb (oneTBB C++)
$(BIN_TBB): fib-tbb.cpp
	$(CXX) $(CXXFLAGS) $(TBB_CFLAGS) -o $@ $< $(TBB_LDFLAGS)

clean:
	$(RM) $(ALL_BINS) *.o *.obj
