ifndef PLATFORM
PLATFORM = linux
endif

ifeq ($(PLATFORM),linux)
LINUX = 1
else ifeq ($(PLATFORM),w32)
WINDOWS = 1
CXX = i686-w64-mingw32-g++
else ifeq ($(PLATFORM),w64)
WINDOWS = 1
CXX = x86_64-w64-mingw32-g++
else
$(error Unknown platform '$(PLATFORM)')
endif

ifdef LINUX
CXXFLAGS += -pthread
LDFLAGS += -pthread
LDLIBS_GRAPHICS += -lX11
endif

ifdef WINDOWS
CXXFLAGS += -D_WIN32_WINNT=0x0600
LDFLAGS += -static
LDLIBS_GRAPHICS += -lgdi32
LDLIBS_NET += -lws2_32
EXE = .exe
endif

# C++ standard
CXXFLAGS += -std=gnu++20

# Warnings
CXXFLAGS += -Wall -Wextra -Wno-unused-parameter
ifdef WINDOWS
CXXFLAGS += -Wno-format
endif

# Optimize
CXXFLAGS += -O3

# Debug
CXXFLAGS += -g3

# Profile
#CXXFLAGS += -pg
#LDFLAGS += -pg

# Address sanitizer
#CXXFLAGS += -fsanitize=address
#LDFLAGS += -fsanitize=address

# Undefined behavior sanitizer
#CXXFLAGS += -fsanitize=undefined
#LDFLAGS += -fsanitize=undefined

# curl
LDLIBS_CURL += -lcurl
ifdef WINDOWS
BLANK_OR_64 = $(BLANK_OR_64_$(PLATFORM))
BLANK_OR_64_w64 = 64
CXXFLAGS += -pthread -I/home/jeremys/$(PLATFORM)/curl/include -DCURL_STATICLIB
LDFLAGS += -pthread -L/home/jeremys/$(PLATFORM)/curl/lib -L/home/jeremys/$(PLATFORM)/openssl/lib$(BLANK_OR_64) -L/home/jeremys/$(PLATFORM)/zlib/lib
LDLIBS_CURL += -lssl -lcrypto -lwldap32 -lcrypt32 -lz -lws2_32
endif

# Dependencies
CPPFLAGS += -MMD -MF $(patsubst %.o,%.d,$@) -MT $@ -MP

# Parallel make
MAKEFLAGS += $(MAKEFLAGS_PARALLEL)

# Architecture
ifdef LINUX
CXXFLAGS += -march=native -mtune=native
endif
ifdef WINDOWS
#CXXFLAGS += -march=alderlake -mtune=alderlake # Desktop
#CXXFLAGS += -march=skylake -mtune=skylake # Laptop
endif

%$(EXE): %.o
	$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

%.o: %.cpp
	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<

LDLIBS =
LDLIBS += $(LDLIBS_$(PLATFORM))
LDLIBS += $(LDLIBS_$(patsubst %$(EXE),%,$@))
LDLIBS += $(LDLIBS_$(PLATFORM)_$(patsubst %$(EXE),%,$@))
LDLIBS_linux +=
LDLIBS_test += $(LDLIBS_CURL)
LDLIBS_linux_test +=
LDLIBS_getproblems += $(LDLIBS_CURL)
LDLIBS_getleaderboard += $(LDLIBS_CURL)
LDLIBS_register += $(LDLIBS_CURL)
LDLIBS_lightning1 += $(LDLIBS_CURL)
LDLIBS_lightning2 += $(LDLIBS_CURL)
LDLIBS_lightning3 += $(LDLIBS_CURL)
LDLIBS_anneal += $(LDLIBS_CURL)
LDLIBS_sat += $(LDLIBS_CURL) -lminisat
LDLIBS_manual += $(LDLIBS_CURL)
STDOBJS = StringUtils.o FileUtils.o ParseUtils.o TimeUtils.o ProcessId.o
PROTOCOLOBJS = Protocol.o Http.o
ALLPROGS = test getproblems getleaderboard register lightning1 lightning2 lightning3 anneal sat manual
ALLPROGS += $(ALLPROGS_$(PLATFORM))
ALLPROGS_linux +=

ALLPROGS_EXE = $(patsubst %,%$(EXE),$(ALLPROGS))

.PHONY: all
all: $(ALLPROGS_EXE)

test$(EXE): test.o $(STDOBJS) $(PROTOCOLOBJS)
getproblems$(EXE): getproblems.o $(STDOBJS) $(PROTOCOLOBJS)
getleaderboard$(EXE): getleaderboard.o $(STDOBJS) $(PROTOCOLOBJS)
register$(EXE): register.o $(STDOBJS) $(PROTOCOLOBJS)
lightning1$(EXE): lightning1.o $(STDOBJS) $(PROTOCOLOBJS)
lightning2$(EXE): lightning2.o $(STDOBJS) $(PROTOCOLOBJS)
lightning3$(EXE): lightning3.o $(STDOBJS) $(PROTOCOLOBJS)
anneal$(EXE): anneal.o $(STDOBJS) $(PROTOCOLOBJS)
sat$(EXE): sat.o $(STDOBJS) $(PROTOCOLOBJS)
manual$(EXE): manual.o $(STDOBJS) $(PROTOCOLOBJS)

.PHONY: clean
clean:
	rm -f *.o *.d $(ALLPROGS_EXE)

ifneq ($(MAKECMDGOALS),clean)
include $(patsubst %.o,%.d,$(wildcard *.o))
endif
