######################################################################################################
# Variables
######################################################################################################

# this nice line comes from the linux kernel makefile
BASE_ARCH:=$(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc/ -e s/sparc64/sparc/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/alpha/axp/)

BUILDDIR=build
BINDIR=release

DEPENDFILE_CLIENT=$(BUILDDIR)/client/Makefile.d
DEPENDFILE_DED=$(BUILDDIR)/ded/Makefile.d
DEPENDFILE_CGAME=$(BUILDDIR)/cgame/Makefile.d
DEPENDFILE_GAME=$(BUILDDIR)/game/Makefile.d
DEPENDFILE_UI=$(BUILDDIR)/ui/Makefile.d

BUILDDIRS=$(BUILDDIR)/client $(BUILDDIR)/ded $(BUILDDIR)/cgame $(BUILDDIR)/game $(BUILDDIR)/ui

CC?=gcc

CFLAGS_COMMON=$(CFLAGS) -I. -I$(LOCALBASE)/include -I$(X11BASE)/include -D__linux__ -Wall
CFLAGS_RELEASE=-O2 -fno-strict-aliasing -ffast-math -funroll-loops
CFLAGS_DEBUG=-O0 -ggdb -DDEBUG
CFLAGS_COMMON+=$(CFLAGS_RELEASE)

CFLAGS_DED=-DDEDICATED_ONLY -DC_ONLY
CFLAGS_MODULE=-fPIC

LDFLAGS_COMMON=-L/usr/local/lib -ldl -lm

ifeq ($(ARCH),x86_64)
LIB=lib64
else
LIB=lib
endif

LDFLAGS_CLIENT=-ljpeg -lz -L$(X11BASE)/$(LIB) -lX11 -lXext -lXxf86dga -lXxf86vm -lcurl
LDFLAGS_DED=-lz
LDFLAGS_MODULE=-shared

ifeq ($(OS),FreeBSD)
SDL_CONFIG?=sdl11-config
else
SDL_CONFIG?=sdl-config
endif

CFLAGS_SDL=$(shell $(SDL_CONFIG) --cflags)
LDFLAGS_SDL=$(shell $(SDL_CONFIG) --libs)

ifeq ($(OS),FreeBSD)
ARCH=freebsd_$(BASE_ARCH)
else
ARCH=$(BASE_ARCH)
endif

SERVER_EXE=wsw_server.$(ARCH)
CLIENT_EXE=warsow.$(ARCH)

######################################################################################################
# Helper functions
######################################################################################################
DO_CC=echo "  > Compiling $<" && \
	$(CC) $(CFLAGS_COMMON) -c $< -o $@

DO_CC_DED=$(DO_CC) $(CFLAGS_DED)
DO_CC_MODULE=$(DO_CC) $(CFLAGS_MODULE)


######################################################################################################
# Files
######################################################################################################
#########
# CLIENT
#########
CFILES_CLIENT  = $(wildcard qcommon/*.c)
CFILES_CLIENT += $(wildcard server/*.c)
CFILES_CLIENT += $(wildcard client/*.c)
CFILES_CLIENT += $(wildcard ref_gl/*.c)
CFILES_CLIENT += $(wildcard linux/*.c)
CFILES_CLIENT += $(wildcard game/q_*.c)

CFILES_CLIENT_WITHOUT_PATH= $(notdir  $(CFILES_CLIENT))
OFILES_CLIENT=$(CFILES_CLIENT_WITHOUT_PATH:.c=.o)
OBJS_CLIENT = $(addprefix $(BUILDDIR)/client/, $(OFILES_CLIENT) )

#########
# DED
#########
CFILES_DED  = qcommon/cm_main.c qcommon/patch.c qcommon/common.c qcommon/files.c qcommon/cmd.c qcommon/cm_trace.c qcommon/mem.c qcommon/net_chan.c qcommon/huff.c qcommon/msg.c qcommon/cvar.c qcommon/md5.c
CFILES_DED += $(wildcard server/*.c)
CFILES_DED += null/cl_null.c
CFILES_DED += linux/glob.c linux/net_udp.c linux/sys_linux.c linux/sv_battleye_linux.c
CFILES_DED += $(wildcard game/q_*.c)

CFILES_DED_WITHOUT_PATH= $(notdir  $(CFILES_DED))
OFILES_DED=$(CFILES_DED_WITHOUT_PATH:.c=.o)
OBJS_DED = $(addprefix $(BUILDDIR)/ded/, $(OFILES_DED) )

#########
# CGAME
#########
CFILES_CGAME  = $(wildcard cgame/*.c)
CFILES_CGAME += $(wildcard gameshared/*.c)
CFILES_CGAME += $(wildcard game/q_*.c)

CFILES_CGAME_WITHOUT_PATH= $(notdir  $(CFILES_CGAME))
OFILES_CGAME=$(CFILES_CGAME_WITHOUT_PATH:.c=.o)
OBJS_CGAME = $(addprefix $(BUILDDIR)/cgame/, $(OFILES_CGAME) )

#########
# GAME
#########
CFILES_GAME  = $(wildcard game/*.c)
CFILES_GAME += $(wildcard game/ai/*.c)
CFILES_GAME += $(wildcard gameshared/*.c)

CFILES_GAME_WITHOUT_PATH= $(notdir  $(CFILES_GAME))
OFILES_GAME=$(CFILES_GAME_WITHOUT_PATH:.c=.o)
OBJS_GAME = $(addprefix $(BUILDDIR)/game/, $(OFILES_GAME) )

#########
# UI
#########
CFILES_UI  = $(wildcard ui/*.c)
CFILES_UI += $(wildcard game/q_*.c)

CFILES_UI_WITHOUT_PATH= $(notdir  $(CFILES_UI))
OFILES_UI=$(CFILES_UI_WITHOUT_PATH:.c=.o)
OBJS_UI = $(addprefix $(BUILDDIR)/ui/, $(OFILES_UI) )


######################################################################################################
# Building Rules
######################################################################################################
.PHONY: all \
	client message-client compile-client link-client \
	ded message-ded compile-ded link-ded  \
	game message-game compile-game link-game  \
	cgame message-cgame compile-cgame link-cgame  \
	ui message-ui compile-ui link-ui  \
	clean clean-depend clean-client clean-ded clean-cgame clean-game clean-ui \
	compile compile-client compile-ded compile-cgame compile-game compile-ui

all: client ded cgame game ui

client: $(BUILDDIRS) message-client compile-client link-client
ded: $(BUILDDIRS) message-ded compile-ded link-ded
cgame: $(BUILDDIRS) message-cgame compile-cgame link-cgame
game: $(BUILDDIRS) message-game compile-game link-game
ui: $(BUILDDIRS) message-ui compile-ui link-ui

clean: clean-msg clean-depend clean-client clean-ded clean-cgame clean-game clean-ui

clean-msg:
	@echo "> *********************************************************"
	@echo "> * Cleaning build files"
	@echo "> *********************************************************"
clean-depend:
	@echo "  > Removing depend files" && \
	$(RM) $(DEPENDFILE_CLIENT) $(DEPENDFILE_DED) $(DEPENDFILE_CGAME) $(DEPENDFILE_GAME) $(DEPENDFILE_UI)
clean-client:
	@echo "  > Removing client objects" && \
	$(RM) $(OBJS_CLIENT)
clean-ded:
	@echo "  > Removing dedicated server objects" && \
	$(RM) $(OBJS_DED)
clean-cgame:
	@echo "  > Removing cgame objects" && \
	$(RM) $(OBJS_CGAME)
clean-game:
	@echo "  > Removing game objects" && \
	$(RM) $(OBJS_GAME)
clean-ui:
	@echo "  > Removing ui objects" && \
	$(RM) $(OBJS_UI)

$(BUILDDIRS) $(BINDIR) $(BINDIR)/basewsw:
	@mkdir -p $@

message-client:
	@echo "> *********************************************************"
	@echo "> * Building client"
	@echo "> *********************************************************"
compile-client: $(OBJS_CLIENT)
link-client: $(BINDIR) $(BINDIR)/$(CLIENT_EXE)

message-ded:
	@echo "> *********************************************************"
	@echo "> * Building dedicated server"
	@echo "> *********************************************************"
compile-ded: $(OBJS_DED)
link-ded: $(BINDIR) $(BINDIR)/$(SERVER_EXE)

message-cgame:
	@echo "> *********************************************************"
	@echo "> * Building cgame"
	@echo "> *********************************************************"
compile-cgame: $(OBJS_CGAME)
link-cgame: $(BINDIR)/basewsw $(BINDIR)/basewsw/cgame_$(ARCH).so

message-game:
	@echo "> *********************************************************"
	@echo "> * Building game"
	@echo "> *********************************************************"
compile-game: $(OBJS_GAME)
link-game: $(BINDIR)/basewsw $(BINDIR)/basewsw/game_$(ARCH).so

message-ui:
	@echo "> *********************************************************"
	@echo "> * Building ui"
	@echo "> *********************************************************"
compile-ui: $(OBJS_UI)
link-ui: $(BINDIR)/basewsw $(BINDIR)/basewsw/ui_$(ARCH).so


######################################################################################################
# Linking Rules
######################################################################################################
########
# DED
########
$(BINDIR)/$(SERVER_EXE): $(OBJS_DED)
	@echo "  > Linking $@" && \
	$(CC) -o $@ $^ $(LDFLAGS_COMMON) $(LDFLAGS_DED)

#########
# CLIENT
#########
$(BINDIR)/$(CLIENT_EXE): $(OBJS_CLIENT)
	@echo "  > Linking $@" && \
	$(CC) -o $@ $(OBJS_CLIENT) $(LDFLAGS_COMMON) $(LDFLAGS_CLIENT) $(LDFLAGS_SDL)

########
# .SO
########
$(BINDIR)/basewsw/cgame_$(ARCH).so: $(OBJS_CGAME)
	@echo "  > Linking $@" && \
	$(CC) -o $@ $^ $(LDFLAGS_COMMON) $(LDFLAGS_MODULE)

$(BINDIR)/basewsw/game_$(ARCH).so: $(OBJS_GAME)
	@echo "  > Linking $@" && \
	$(CC) -o $@ $^ $(LDFLAGS_COMMON) $(LDFLAGS_MODULE)

$(BINDIR)/basewsw/ui_$(ARCH).so: $(OBJS_UI)
	@echo "  > Linking $@" && \
	$(CC) -o $@ $^ $(LDFLAGS_COMMON) $(LDFLAGS_MODULE)


######################################################################################################
# Meta Rules
######################################################################################################
########
# CLIENT
########
$(BUILDDIR)/client/%.o: qcommon/%.c
	@$(DO_CC)

$(BUILDDIR)/client/%.o: server/%.c
	@$(DO_CC)

$(BUILDDIR)/client/%.o: client/%.c
	@$(DO_CC)

$(BUILDDIR)/client/%.o: ref_gl/%.c
	@$(DO_CC)

$(BUILDDIR)/client/%.o: linux/%.c
	@$(DO_CC)

$(BUILDDIR)/client/snd_sdl.o: linux/snd_sdl.c
	@$(DO_CC) $(CFLAGS_SDL)

$(BUILDDIR)/client/%.o: game/%.c
	@$(DO_CC)

########
# DED
########
$(BUILDDIR)/ded/%.o: qcommon/%.c 
	@$(DO_CC_DED)

$(BUILDDIR)/ded/%.o: server/%.c
	@$(DO_CC_DED)

$(BUILDDIR)/ded/%.o: linux/%.c
	@$(DO_CC_DED)

$(BUILDDIR)/ded/%.o: null/%.c
	@$(DO_CC_DED)

$(BUILDDIR)/ded/%.o: game/%.c
	@$(DO_CC_DED)

########
# CGAME
########
$(BUILDDIR)/cgame/%.o: cgame/%.c
	@$(DO_CC_MODULE)

$(BUILDDIR)/cgame/%.o: gameshared/%.c
	@$(DO_CC_MODULE)

$(BUILDDIR)/cgame/%.o: game/%.c
	@$(DO_CC_MODULE)

########
# GAME
########
$(BUILDDIR)/game/%.o: game/%.c
	@$(DO_CC_MODULE)

$(BUILDDIR)/game/%.o: game/ai/%.c
	@$(DO_CC_MODULE)

$(BUILDDIR)/game/%.o: gameshared/%.c
	@$(DO_CC_MODULE)

########
# UI
########
$(BUILDDIR)/ui/%.o: game/%.c
	@$(DO_CC_MODULE)

$(BUILDDIR)/ui/%.o: ui/%.c
	@$(DO_CC_MODULE)


######################################################################################################
# Depends
######################################################################################################

$(DEPENDFILE_CLIENT): $(BUILDDIRS) $(CFILES_CLIENT)
	@makedepend -f - -- $(CFLAGS_COMMON) $(CFLAGS_SDL) -- $(CFILES_CLIENT) 2> /dev/null | \
	awk '{ sub(/^([a-zA-Z]*\/)+/, "$(BUILDDIR)/client/"); print $0; \
	       sub(/^.*\:/, "$(DEPENDFILE_CLIENT):"); print $0 }' > $(DEPENDFILE_CLIENT)

$(DEPENDFILE_DED): $(BUILDDIRS) $(CFILES_DED)
	@makedepend -f - -- $(CFLAGS_COMMON) $(CFLAGS_DED) -- $(CFILES_DED) 2> /dev/null | \
	awk '{ sub(/^([a-zA-Z]*\/)+/, "$(BUILDDIR)/ded/"); print $0; \
	       sub(/^.*\:/, "$(DEPENDFILE_DED):"); print $0 }' > $(DEPENDFILE_DED)

$(DEPENDFILE_CGAME): $(BUILDDIRS) $(CFILES_CGAME)
	@makedepend -f - -- $(CFLAGS_COMMON) $(CFLAGS_MODULES) -- $(CFILES_CGAME) 2> /dev/null | \
	awk '{ sub(/^([a-zA-Z]*\/)+/, "$(BUILDDIR)/cgame/"); print $0; \
	       sub(/^.*\:/, "$(DEPENDFILE_CGAME):"); print $0 }' > $(DEPENDFILE_CGAME)

$(DEPENDFILE_GAME): $(BUILDDIRS) $(CFILES_GAME)
	@makedepend -f - -- $(CFLAGS_COMMON) $(CFLAGS_MODULES) -- $(CFILES_GAME) 2> /dev/null | \
	awk '{ sub(/^([a-zA-Z]*\/)+/, "$(BUILDDIR)/game/"); print $0; \
	       sub(/^.*\:/, "$(DEPENDFILE_GAME):"); print $0 }' > $(DEPENDFILE_GAME)

$(DEPENDFILE_UI): $(BUILDDIRS) $(CFILES_UI)
	@makedepend -f - -- $(CFLAGS_COMMON) $(CFLAGS_MODULES) -- $(CFILES_UI) 2> /dev/null | \
	awk '{ sub(/^([a-zA-Z]*\/)+/, "$(BUILDDIR)/ui/"); print $0; \
	       sub(/^.*\:/, "$(DEPENDFILE_UI):"); print $0 }' > $(DEPENDFILE_UI)

-include $(DEPENDFILE_CLIENT)
-include $(DEPENDFILE_DED)
-include $(DEPENDFILE_CGAME)
-include $(DEPENDFILE_GAME)
-include $(DEPENDFILE_UI)
