#
# Quake3 Unix Makefile
#
# Currently build for the following:
#	Linux i386 (full client)
#	Linux Alpha (dedicated server only) (TTimo: dropped)
#	FreeBSD i386 (dedicated server only) (TTimo: maybe worth updating)
#	SGI IRIX (full client) (TTimo: who's in charge - dropped otherwise)
#   Linux PPC (full client) (TTimo: dropped)
#
# Nov '98 by Zoid <zoid@idsoftware.com>
#
# Loki Hacking by Bernd Kreimeier 
#  and a little more by Ryan C. Gordon.
#  and a little more by Rafael Barrero
#
# GNU Make required
#

PLATFORM=$(shell uname|tr A-Z a-z)
PLATFORM_RELEASE=$(shell uname -r)
SHARED=no

# RELEASE = {debug|release}
RELEASE=release

###
### These paths are where you probably want to change things
###

# Where we are building from (where the source code should be!)
MOUNT_DIR=.

# where Merc and Colyseus are, respectively
MERC_DIR = ../../../Merc
COLY_DIR = ../../../Colyseus

#############################################################################
##
## You shouldn't have to touch anything below here
##
#############################################################################

CDIR=$(MOUNT_DIR)/client
SDIR=$(MOUNT_DIR)/server
RDIR=$(MOUNT_DIR)/renderer
CMDIR=$(MOUNT_DIR)/qcommon
UDIR=$(MOUNT_DIR)/unix
GDIR=$(MOUNT_DIR)/game

IDIR_SUF=extractors/output
IDIR=$(MOUNT_DIR)/$(IDIR_SUF)

CGDIR=$(MOUNT_DIR)/cgame
BAIDIR=$(GDIR)
BLIBDIR=$(MOUNT_DIR)/botlib
NDIR=$(MOUNT_DIR)/null
UIDIR=$(MOUNT_DIR)/ui
Q3UIDIR=$(MOUNT_DIR)/q3_ui
FTDIR=$(MOUNT_DIR)/ft2
JPDIR=$(MOUNT_DIR)/jpeg-6
SPLNDIR=$(MOUNT_DIR)/splines

## Defaults
DLL_ONLY=false

PWD := $(shell pwd)
INCLUDES := -I$(PWD)/botlib -I$(PWD)/server -I$(PWD)/game -I$(PWD)/qcommon -I$(PWD)/unix -I$(PWD)/null -I$(MERC_DIR) -I$(COLY_DIR)

ifeq ($(PLATFORM),linux)
 include makefile.linux
else 
 ifeq ($(PLATFORM),freebsd)
  include makefile.freebsd
 else 
  ifeq ($(PLATFORM),irix)
   include makefile.irix
  else 
   include makefile.generic
  endif #irix
 endif #freebsd
endif #linux

# Ashwin: changed CC to CPP at many places
DO_CC=$(CPP) $(CFLAGS) -o $@ -c $<

DO_CPP=$(CPP) $(CFLAGS) -o $@ -c $<
DO_SMP_CC=$(CC) $(CFLAGS) -DSMP -o $@ -c $<

DO_BOT_CC=$(CPP) $(CFLAGS) -DBOTLIB  -o $@ -c $<   # $(SHLIBCFLAGS) # bk001212

DO_DEBUG_CC=$(CPP) $(DEBUG_CFLAGS) -o $@ -c $<

DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
DO_NASM=nasm -f elf -o $@  $<

DO_DED_CC=$(CPP) -DDEDICATED -DC_ONLY $(CFLAGS) -o $@ -c $<

ifeq ($(strip $(RELEASE)),debug)
  B=debug$(ARCH)
  CFLAGS=$(DEBUG_CFLAGS)
else
  B=release$(ARCH)
  CFLAGS=$(RELEASE_CFLAGS)
endif

ifeq ($(SHARED),yes)
  DO_SHLIB_CC=$(CPP) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
else
  CFLAGS += -DGAME_HARD_LINKED -DC_ONLY -DDEDICATED -DBOTLIB
  DO_SHLIB_CC = $(CPP) $(CFLAGS) -o $@ -c $<
  DO_DED_CC = $(CPP) $(CFLAGS) -o $@ -c $<  
endif

list_dirs := $(B)/qcommon \
                $(B)/server \
                $(B)/unix \
                $(B)/game \
                $(B)/botlib \
                $(B)/null \
		$(B)/$(IDIR_SUF)

Q3LIB = libq3ded.$(LIBEXT)
I_Q3LIB = libiq3ded.$(LIBEXT)

TARGETS = $(Q3LIB)

all: makedirs $(TARGETS)
	
instrumented: 
	$(MAKE) TARGETS=$(I_Q3LIB)

debug:
	$(MAKE) RELEASE=debug $(MAKECMDGOALS)
release:
	$(MAKE) RELEASE=release $(MAKECMDGOALS)

makedirs:
	@mkdir -p $(B);


#############################################################################
# DEPENDENCIES
#############################################################################

ALL_INC = -include colyseus_exports.h

DFLAGS = -x c++ $(INCLUDES) $(CFLAGS) -Wno-deprecated -Wno-reorder $(ALL_INC) -DARCH=\""$(ARCH)"\" -MM 
CCFLAGS = $(INCLUDES) $(CFLAGS) -Wno-unused -Wno-deprecated -Wno-reorder $(ALL_INC) -DARCH=\""$(ARCH)"\"

#### rules for the instrumented quake dll ###################################

RECORD_INC = extractors/record.h

# This is all majorly hacky...

CIL_CCFLAGS = $(INCLUDES) $(CFLAGS) -Wno-unused -Wno-deprecated -Wno-reorder  -DARCH=\""$(ARCH)"\"

## XXX make sure docil.pl is atomic w.r.t. SIGINT, SIGHUP, etc.

$(IDIR_SUF)/%.cil.c: $(GDIR)/%.c
	@echo "+ Cillyfying $<"
	@cd extractors && ./docil.pl $(CIL_CCFLAGS) --doinstrument --docanonicalize --save-temps=../$(IDIR_SUF) ../$<
	@cp $@ tmp.c 
	@cat tmp.c | perl ../scripts/FieldMapper.pl -f ../scripts/.extracted-ds > $@
	@rm -f $(IDIR_SUF)/*.i tmp.c

# If there are multiple pattern-rules applicable, it appears as if 
# the first rule is the one used by make.
# 
$(B)/$(IDIR_SUF)/%.d: $(IDIR_SUF)/%.c $(RECORD_INC)
	@echo "+ Generating deps for $<"
	@$(CPP) $(DFLAGS) -I. -include $(RECORD_INC) $< -MT "$(B)/$(<:.c=.o)" > $@

$(B)/$(IDIR_SUF)/%.o: $(IDIR_SUF)/%.c $(B)/$(IDIR_SUF)/%.d
	@echo "* Compiling $<"
	@rm -f $(B)/$<.cpp
	@ln -s $(shell pwd)/$< $(B)/$<.cpp
	@$(CPP) $(CCFLAGS) -I. -Wno-pointer-arith -include $(RECORD_INC) -o $@ -c $(B)/$<.cpp

#### #########################################################################

$(B)/%.d: %.cpp
	@echo "+ Generating deps for $<"
	@$(CPP) $(DFLAGS) $< -MT "$(B)/$(<:.cpp=.o)" > $@

$(B)/%.d: %.c
	@echo "+ Generating deps for $<"
	@$(CPP) $(DFLAGS) $< -MT "$(B)/$(<:.c=.o)" > $@

$(B)/%.o: %.cpp $(B)/%.d
	@echo "* Compiling $<"; 
	@$(CPP) $(CCFLAGS) -o $@ -c $<

$(B)/%.o: %.c $(B)/%.d
	@echo "* Compiling $<"
	@rm -f $(B)/$<.cpp
	@ln -s $(shell pwd)/$< $(B)/$<.cpp
	@$(CPP) $(CCFLAGS) -o $@ -c $(B)/$<.cpp

#############################################################################
# DEDICATED SERVER                        
#############################################################################

SERVER_SRC = \
	$(SDIR)/sv_bot.c \
	$(SDIR)/sv_client.c \
	$(SDIR)/sv_ccmds.c \
	$(SDIR)/sv_game.c \
	$(SDIR)/sv_init.c \
	$(SDIR)/sv_main.c \
	$(SDIR)/sv_net_chan.c \
	$(SDIR)/sv_snapshot.c \
	$(SDIR)/sv_world.c 

COMMON_SRC = \
	$(CMDIR)/cm_load.c \
	$(CMDIR)/cm_patch.c \
	$(CMDIR)/cm_polylib.c \
	$(CMDIR)/cm_test.c \
	$(CMDIR)/cm_trace.c \
	$(CMDIR)/cmd.c \
	$(CMDIR)/common.c \
	$(CMDIR)/cvar.c \
	$(CMDIR)/files.c \
	$(CMDIR)/md4.c \
	$(CMDIR)/msg.c \
	$(CMDIR)/net_chan.c \
	$(CMDIR)/huffman.c \
	\
	$(GDIR)/q_math.c \
	$(GDIR)/q_shared.c \
	\
	$(CMDIR)/unzip.c \
	$(CMDIR)/vm.c \
	$(CMDIR)/vm_interpreted.c \

BOTLIB_SRC = \
	$(BLIBDIR)/be_aas_bspq3.c \
	$(BLIBDIR)/be_aas_cluster.c \
	$(BLIBDIR)/be_aas_debug.c \
	$(BLIBDIR)/be_aas_entity.c \
	$(BLIBDIR)/be_aas_file.c \
	$(BLIBDIR)/be_aas_main.c \
	$(BLIBDIR)/be_aas_move.c \
	$(BLIBDIR)/be_aas_optimize.c \
	$(BLIBDIR)/be_aas_reach.c \
	$(BLIBDIR)/be_aas_route.c \
	$(BLIBDIR)/be_aas_routealt.c \
	$(BLIBDIR)/be_aas_sample.c \
	$(BLIBDIR)/be_ai_char.c \
	$(BLIBDIR)/be_ai_chat.c \
	$(BLIBDIR)/be_ai_gen.c \
	$(BLIBDIR)/be_ai_goal.c \
	$(BLIBDIR)/be_ai_move.c \
	$(BLIBDIR)/be_ai_weap.c \
	$(BLIBDIR)/be_ai_weight.c \
	$(BLIBDIR)/be_ea.c \
	$(BLIBDIR)/be_interface.c \
	$(BLIBDIR)/l_crc.c \
	$(BLIBDIR)/l_libvar.c \
	$(BLIBDIR)/l_log.c \
	$(BLIBDIR)/l_memory.c \
	$(BLIBDIR)/l_precomp.c \
	$(BLIBDIR)/l_script.c \
	$(BLIBDIR)/l_struct.c \

PLATFORM_SRC = 	\
	$(UDIR)/linux_common.c \
	$(UDIR)/linux_signals.c \
	$(UDIR)/unix_main.c \
	$(UDIR)/unix_net.c \
	$(UDIR)/unix_shared.c \
	\
	$(NDIR)/null_client.c \
	$(NDIR)/null_input.c \
	$(NDIR)/null_snddma.c

MODULE_SRC_1 = \
	ai_chat.c \
	ai_cmd.c \
	ai_dmnet.c \
	ai_dmq3.c \
	ai_main.c \
	ai_team.c \
	ai_vcmd.c \
	bg_misc.c \
	bg_pmove.c \
	bg_slidemove.c \
	g_active.c \
	g_arenas.c \
	g_bot.c \
	g_client.c \
	g_cmds.c \
	g_combat.c \
	g_items.c \
	g_main.c \
	g_mem.c \
	g_misc.c \
	g_missile.c \
	g_mover.c \
	g_session.c \
	g_spawn.c \
	g_svcmds.c \
	g_syscalls.c \
	g_target.c \
	g_team.c \
	g_trigger.c \
	g_utils.c \
	g_weapon.c 

ifeq ($(TARGETS),$(I_Q3LIB))
MODULE_SRC = $(patsubst %.c,$(IDIR)/%.cil.c,$(MODULE_SRC_1))
MODULE_SRC += extractors/record.cpp
else
MODULE_SRC = $(patsubst %,$(GDIR)/%,$(MODULE_SRC_1))
endif

# HACK: eliminate the ./ in-front of (some) of the source files...
GAME_SRC_PREF = $(SERVER_SRC) $(COMMON_SRC) $(BOTLIB_SRC) $(PLATFORM_SRC) $(MODULE_SRC)

GAME_SRC = $(patsubst ./%,%,$(GAME_SRC_PREF))


# HACK: there must be a better way to do patsubst for {c,cpp} here...
GAME_OBJS_C = $(patsubst %.c,$(B)/%.o,$(GAME_SRC))
GAME_OBJS   = $(patsubst %.cpp,$(B)/%.o,$(GAME_OBJS_C))
GAME_DEPS_C = $(patsubst %.c,$(B)/%.d,$(GAME_SRC))
GAME_DEPS   = $(patsubst %.cpp,$(B)/%.d,$(GAME_DEPS_C))

ifeq ($(ARCH),i386)
  GAME_OBJS += $(B)/ftol.o $(B)/snapvector.o
endif

ifeq ($(ARCH),i386)
$(B)/vm_x86.o : $(CMDIR)/vm_x86.c; $(DO_DED_CC) 
$(B)/ftol.o : $(UDIR)/ftol.nasm; $(DO_NASM)
$(B)/snapvector.o : $(UDIR)/snapvector.nasm; $(DO_NASM) 
endif

ifneq ($(findstring clean,$(MAKECMDGOALS)),clean)
$(shell mkdir -p $(list_dirs))
-include $(GAME_DEPS)
endif

############################################################################
## libq3ded.a
############################################################################

$(I_Q3LIB) $(Q3LIB): $(GAME_OBJS)
	$(AR) rc $@ $(GAME_OBJS)
	$(RANLIB) $@


#############################################################################
## MISSIONPACK GAME
#############################################################################

MPGOBJ = \
	$(B)/missionpack/game/ai_chat.o \
	$(B)/missionpack/game/ai_cmd.o \
	$(B)/missionpack/game/ai_dmnet.o \
	$(B)/missionpack/game/ai_dmq3.o \
	$(B)/missionpack/game/ai_main.o \
	$(B)/missionpack/game/ai_team.o \
	$(B)/missionpack/game/ai_vcmd.o \
	$(B)/missionpack/game/bg_misc.o \
	$(B)/missionpack/game/bg_pmove.o \
	$(B)/missionpack/game/bg_slidemove.o \
	$(B)/missionpack/game/g_active.o \
	$(B)/missionpack/game/g_arenas.o \
	$(B)/missionpack/game/g_bot.o \
	$(B)/missionpack/game/g_client.o \
	$(B)/missionpack/game/g_cmds.o \
	$(B)/missionpack/game/g_combat.o \
	$(B)/missionpack/game/g_items.o \
	$(B)/missionpack/game/g_main.o \
	$(B)/missionpack/game/g_mem.o \
	$(B)/missionpack/game/g_misc.o \
	$(B)/missionpack/game/g_missile.o \
	$(B)/missionpack/game/g_mover.o \
	$(B)/missionpack/game/g_session.o \
	$(B)/missionpack/game/g_spawn.o \
	$(B)/missionpack/game/g_svcmds.o \
	$(B)/missionpack/game/g_syscalls.o \
	$(B)/missionpack/game/g_target.o \
	$(B)/missionpack/game/g_team.o \
	$(B)/missionpack/game/g_trigger.o \
	$(B)/missionpack/game/g_utils.o \
	$(B)/missionpack/game/g_weapon.o \
	\
	$(B)/missionpack/game/q_math.o \
	$(B)/missionpack/game/q_shared.o

$(B)/missionpack/qagame$(ARCH).$(SHLIBEXT) : $(MPGOBJ)
	$(CC) $(SHLIBLDFLAGS) -o $@ $(MPGOBJ)

$(B)/missionpack/game/ai_chat.o : $(GDIR)/ai_chat.c; $(DO_SHLIB_CC)    -DMISSIONPACK 
$(B)/missionpack/game/ai_cmd.o : $(GDIR)/ai_cmd.c; $(DO_SHLIB_CC)      -DMISSIONPACK 
$(B)/missionpack/game/ai_dmnet.o : $(GDIR)/ai_dmnet.c; $(DO_SHLIB_CC)  -DMISSIONPACK 
$(B)/missionpack/game/ai_dmq3.o : $(GDIR)/ai_dmq3.c; $(DO_SHLIB_CC)    -DMISSIONPACK   
$(B)/missionpack/game/ai_main.o : $(GDIR)/ai_main.c; $(DO_SHLIB_CC)    -DMISSIONPACK  
$(B)/missionpack/game/ai_team.o : $(GDIR)/ai_team.c; $(DO_SHLIB_CC)    -DMISSIONPACK 
$(B)/missionpack/game/ai_vcmd.o : $(GDIR)/ai_vcmd.c; $(DO_SHLIB_CC)    -DMISSIONPACK 
$(B)/missionpack/game/bg_misc.o : $(GDIR)/bg_misc.c; $(DO_SHLIB_CC)    -DMISSIONPACK 
$(B)/missionpack/game/bg_pmove.o : $(GDIR)/bg_pmove.c; $(DO_SHLIB_CC)    -DMISSIONPACK 
$(B)/missionpack/game/bg_slidemove.o : $(GDIR)/bg_slidemove.c; $(DO_SHLIB_CC)  -DMISSIONPACK  
$(B)/missionpack/game/g_active.o : $(GDIR)/g_active.c; $(DO_SHLIB_CC)      -DMISSIONPACK 
$(B)/missionpack/game/g_arenas.o : $(GDIR)/g_arenas.c; $(DO_SHLIB_CC)      -DMISSIONPACK 
$(B)/missionpack/game/g_bot.o : $(GDIR)/g_bot.c; $(DO_SHLIB_CC)           -DMISSIONPACK 
$(B)/missionpack/game/g_client.o : $(GDIR)/g_client.c; $(DO_SHLIB_CC)     -DMISSIONPACK 
$(B)/missionpack/game/g_cmds.o : $(GDIR)/g_cmds.c; $(DO_SHLIB_CC)         -DMISSIONPACK 
$(B)/missionpack/game/g_combat.o : $(GDIR)/g_combat.c; $(DO_SHLIB_CC)      -DMISSIONPACK 
$(B)/missionpack/game/g_items.o : $(GDIR)/g_items.c; $(DO_SHLIB_CC)         -DMISSIONPACK 
$(B)/missionpack/game/g_main.o : $(GDIR)/g_main.c; $(DO_SHLIB_CC)          -DMISSIONPACK  
$(B)/missionpack/game/g_mem.o : $(GDIR)/g_mem.c; $(DO_SHLIB_CC)             -DMISSIONPACK  
$(B)/missionpack/game/g_misc.o : $(GDIR)/g_misc.c; $(DO_SHLIB_CC)            -DMISSIONPACK 
$(B)/missionpack/game/g_missile.o : $(GDIR)/g_missile.c; $(DO_SHLIB_CC)      -DMISSIONPACK  
$(B)/missionpack/game/g_mover.o : $(GDIR)/g_mover.c; $(DO_SHLIB_CC)        -DMISSIONPACK  
$(B)/missionpack/game/g_session.o : $(GDIR)/g_session.c; $(DO_SHLIB_CC)     -DMISSIONPACK  
$(B)/missionpack/game/g_spawn.o : $(GDIR)/g_spawn.c; $(DO_SHLIB_CC)         -DMISSIONPACK 
$(B)/missionpack/game/g_svcmds.o : $(GDIR)/g_svcmds.c; $(DO_SHLIB_CC)       -DMISSIONPACK  
$(B)/missionpack/game/g_syscalls.o : $(GDIR)/g_syscalls.c; $(DO_SHLIB_CC)   -DMISSIONPACK 
$(B)/missionpack/game/g_target.o : $(GDIR)/g_target.c; $(DO_SHLIB_CC)       -DMISSIONPACK 
$(B)/missionpack/game/g_team.o : $(GDIR)/g_team.c; $(DO_SHLIB_CC)         -DMISSIONPACK  
$(B)/missionpack/game/g_trigger.o : $(GDIR)/g_trigger.c; $(DO_SHLIB_CC)    -DMISSIONPACK   
$(B)/missionpack/game/g_utils.o : $(GDIR)/g_utils.c; $(DO_SHLIB_CC)        -DMISSIONPACK  
$(B)/missionpack/game/g_weapon.o : $(GDIR)/g_weapon.c; $(DO_SHLIB_CC)      -DMISSIONPACK 
$(B)/missionpack/game/q_math.o : $(GDIR)/q_math.c; $(DO_SHLIB_CC)          -DMISSIONPACK  
$(B)/missionpack/game/q_shared.o : $(GDIR)/q_shared.c; $(DO_SHLIB_CC)      -DMISSIONPACK 



#############################################################################
# MISC
#############################################################################

clean: clean-debug clean-release

clean2: clean-bins
	rm -f $(GAME_OBJS) $(GAME_DEPS)
	rm -f $(CGDIR)/vm/*.asm
	rm -f $(GDIR)/vm/*.asm
	rm -f $(UIDIR)/vm/*.asm
	rm -f $(Q3UIDIR)/vm/*.asm
	rm -f $(IDIR_SUF)/*.cil.c
	rm -f $(B)/$(IDIR_SUF)/*.[od]

# TTimo: linuxq3ded linuxquake3 linuxquake3-smp .. hardcoded the names .. maybe not such a good thing
# FIXME: also, removing the *.so is crappy .. I just want to avoid rm -rf debugi386-glibc to save the symlinks to pk3's for testing
clean-bins:
	if [ -d $(B) ];then (find $(B) -name '*.so' -exec rm {} \;)fi
	rm -f libq3ded.$(LIBEXT) libiq3ded.$(LIBEXT)
	rm -f $(B)/linuxq3ded
	rm -f $(B)/linuxquake3
	rm -f $(B)/linuxquake3-smp
	rm -f $(B)/baseq3/vm/cgame.qvm
	rm -f $(B)/baseq3/vm/ui.qvm
	rm -f $(B)/baseq3/vm/qagame.qvm
	rm -f $(B)/missionpack/vm/cgame.qvm
	rm -f $(B)/missionpack/vm/qagame.qvm
	rm -f $(B)/missionpack/vm/ui.qvm

clean-debug:
	$(MAKE) clean2 B=debug$(ARCH) 

clean-release:
	$(MAKE) clean2 B=release$(ARCH) 
