# vi: set ts=4 sw=4 :
# vim: set tw=75 :

# MetaMOD makefile
# by Will Day, based on the Valve SDK 2.1 Makefile as well as the Makefile
# in adminmod by Alfred Reynolds

#! Half-Life StandardSDK 2.0 mp_i386.so Makefile for i386 Linux
#
#! April 2000 by Leon Hartwig (jehannum@planethalflife.com)
#
# From SDK 2.1 dlls/Makefile

# NOTE: This is a generic Makefile for metamod and the bundled plugins, and
# is symlinked into each subdir.  Per-module config statements are in
# Config.mak in each subdir.

ifdef COMSPEC
	OS=windows
else
	OS=linux
endif


#############################################################################
# CONFIGURATION
#############################################################################

# set paths for your environment
ifeq "$(OS)" "linux"
	PATH_WIN=/usr/local/cross-tools/i386-mingw32msvc/bin
	SDKTOP=$(HOME)/src/hl/hlsdk-2.1
	INST_DIR=$(HOME)/half-life/cstrike/dlls
	TEST_DIR=$(HOME)/test/cstrike/dlls
	TST_DIR=$(HOME)/tmp
else	## windows
	PATH_WIN=/gcc-2.95.2-msvcrt/bin
	SDKTOP=/hlsdk2.1
	INST_DIR=/hlserver/tfc/dlls
	TEST_DIR=/hlserver/tfc/dlls
endif

SDKSRC=$(SDKTOP)/SourceCode
METADIR=../metamod


#############################################################################
# OS DEPENDENCIES
#############################################################################

ifeq "$(OS)" "linux"
	INSTALL=install -m 644
	LD_WINDLL= PATH=$(PATH_WIN) $(PATH_WIN)/dllwrap
	TARGET=linux
	LIBFILE=$(LIBFILE_LINUX)
	TARGET_FILE=$(TARGET_LINUX)
	OBJDIR=$(OBJDIR_LINUX)
else	## windows
	INSTALL=cp
	LD_WINDLL= $(PATH_WIN)/dllwrap
	TARGET=win32
	LIBFILE=$(LIBFILE_WIN)
	TARGET_FILE=$(TARGET_WIN)
	OBJDIR=$(OBJDIR_WIN)
endif

CC_WIN=$(PATH_WIN)/gcc
RES_WIN=$(PATH_WIN)/windres
OBJDIR_LINUX=obj.linux
OBJDIR_WIN=obj.win32


#############################################################################
# COMPILE OPTIONS
#############################################################################

# original safe optimization, from valve Makefile
#CCOPT = -O2 -ffast-math -funroll-loops \
#	-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
#	-malign-jumps=2 -malign-functions=2

# safe optimization, adapted from adminmod Makefile
#CCOPT = -m486 -O6 -ffast-math -funroll-loops \
# -fexpensive-optimizations -malign-loops=2  -malign-jumps=2 \
# -malign-functions=2 -Wall

# full optimization, adapted from adminmod Makefile
# "WONT WORK WITH omit-frame-pointer"?
#CCOPT = -m486 -O6 -ffast-math -funroll-loops \
#	-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
#	-malign-jumps=2 -malign-functions=2 -s

# debugging 
CCOPT+= -ggdb3


#############################################################################
# COMPILE SETUP
#############################################################################

include Config.mak

CC=gcc

SRCDIR=.
INCLUDEDIRS=-I$(SRCDIR) -I$(METADIR) -I$(SDKSRC)/engine -I$(SDKSRC)/common -I$(SDKSRC)/pm_shared -I$(SDKSRC)/dlls -I$(SDKSRC)
FILES_ALL = *.cpp *.h [A-Z]* *.rc

#CFLAGS=-Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -Dstrcmpi=strcasecmp \
#	-march=i686 -Wall -Wno-unknown-pragmas 
CFLAGS=-march=i686 -Wall -Wno-unknown-pragmas 
	
# extra warnings
CFLAGS+=-W -Wundef \
	-Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align \
	-Wconversion -Wsign-compare \
	-Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \
	-Wmissing-noreturn -Wnested-externs -Winline \
	-Wlong-long 
# extra C++ warnings
CFLAGS+=-Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Woverloaded-virtual \
	-Wsign-promo -Wsynth -Weffc++
# halt on warnings
CFLAGS+=-Werror
# undesired warnings
#CFLAGS+=-pedantic -Waggregate-return -Wredundant-decls -Wtraditional 
CFLAGS += $(CCOPT)

# any local CFLAGS from Config.mak
CFLAGS += $(EXTRA_CFLAGS)

default: all

#############################################################################
# BUILDING LINUX SO
#############################################################################

# linux .so compile commands
DO_CC_LINUX=$(CC) $(CFLAGS) -fPIC $(INCLUDEDIRS) -o $@ -c $<
LINK_LINUX=$(CC) $(CFLAGS) -shared -ldl -lm $(OBJ_LINUX) -o $@

# sort by date
ifeq "$(OS)" "linux"
SRCFILES := $(shell ls -t $(SRCFILES))
endif
# linux object files
OBJ_LINUX := $(SRCFILES:%.cpp=$(OBJDIR_LINUX)/%.o)

# compiling linux object files
$(OBJDIR_LINUX)/%.o: $(SRCDIR)/%.cpp
	$(DO_CC_LINUX)

# make sure to recompile vdate.c for each link
$(OBJDIR_LINUX)/vdate.o: $(SRCFILES) *.h

# linux .so target file
LIBFILE_LINUX = $(MODNAME)_i386.so
TARGET_LINUX = $(OBJDIR_LINUX)/$(LIBFILE_LINUX)


#############################################################################
# BUILDING WINDOWS DLL
#############################################################################

# windows .dll compile commands
DO_CC_WIN=$(CC_WIN) $(CFLAGS) $(INCLUDEDIRS) -o $@ -c $<
DO_RES_WIN=$(RES_WIN) -i $< -O coff -o $@
#LINK_WIN=$(LD_WINDLL) -k -mwindows --add-stdcall-alias --def metamod.def -o $@ $(OBJ_WIN)
#LINK_WIN=$(LD_WINDLL) -A -k -mwindows --export-all-symbols -o $@ $(OBJ_WIN)
LINK_WIN=$(LD_WINDLL) -mwindows --add-stdcall-alias $(OBJ_WIN) $(RES_OBJ_WIN) -o $@

# windows object files
OBJ_WIN := $(SRCFILES:%.cpp=$(OBJDIR_WIN)/%.o)
RES_OBJ_WIN := $(RESFILE:%.rc=$(OBJDIR_WIN)/%.o)

# compiling windows object files
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.cpp
	$(DO_CC_WIN)

# compiling windows resource file
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.rc
	$(DO_RES_WIN)

# make sure to recompile vdate.c for each link
$(OBJDIR_LINUX)/vdate.o: $(SRCFILES) *.h

# windows .dll target file
LIBFILE_WIN = $(MODNAME).dll
TARGET_WIN = $(OBJDIR_WIN)/$(LIBFILE_WIN)


#############################################################################
# BUILD RULES
#############################################################################

all: $(TARGET_FILE)

linux: $(TARGET_LINUX)
win32: $(TARGET_WIN)

$(TARGET_LINUX): .tags .htags msgs/debug msgs/log msgs/error $(OBJDIR_LINUX) $(OBJ_LINUX)
	$(LINK_LINUX)

$(TARGET_WIN): $(OBJDIR_WIN) $(OBJ_WIN) $(RES_OBJ_WIN)
	$(LINK_WIN)

$(OBJDIR_LINUX) $(OBJDIR_WIN) msgs:
	mkdir $@

domsgs: msgs/debug msgs/log msgs/error

msgs/debug: $(SRCFILES) *.h msgs
	egrep "DEBUG\([0-9]" $(SRCFILES) *.h | sed "s/:[ 	]*/	/" | sort -k2,2 > $@

msgs/log: $(SRCFILES) *.h msgs
	egrep "META_LOG\(" $(SRCFILES) *.h | sed "s/:[ 	]*/	/" | sort > $@

msgs/error: $(SRCFILES) *.h msgs
	egrep "META_ERROR\(" $(SRCFILES) *.h | sed "s/:[ 	]*/	/" | sort > $@

tags:	.tags .htags
ctags:	.tags
htags:	.htags

.tags: $(SRCFILES) *.h
	-ctags -a $?

.htags: *.h
	-htags $?

retags:
	-rm -f .tags .htags
	ctags -f .tags `find $(SDKSRC) -name '*.h'`
	ctags -f .tags -a `find $(METADIR) -name old -prune -o -name '*.h' -print`
	ctags -f .tags -a $(SRCFILES)
	htags -R $(SDKSRC)
	htags `find $(METADIR) -name old -prune -o -name '*.h' -print`
	htags *.h

clean: clean_$(TARGET)

clean_linux:
	@test -n "$(OBJDIR_LINUX)"
	-rm -f $(OBJDIR_LINUX)/*

clean_win32:
	@test -n "$(OBJDIR_WIN)"
	-rm -f $(OBJDIR_WIN)/*

cleanall: clean_linux clean_win32

spotless: cleanall
	-rmdir $(OBJDIR_LINUX) $(OBJDIR_WIN)
	-rm -f .snap

distclean:	spotless

install: $(INST_DIR)/$(LIBFILE)
test: $(TEST_DIR)/$(LIBFILE)

$(INST_DIR)/$(LIBFILE) $(TEST_DIR)/$(LIBFILE): $(TARGET_FILE)
	$(INSTALL) $< $@

tst: $(TST_DIR)/$(LIBFILE_WIN)

$(TST_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
	cp $< $@

snap:	.snap

.snap: $(FILES_ALL)
	mkdir -p snapshots
	tar zcvf snapshots/`date '+%m%d-%H%M'`.tgz $(FILES_ALL)
	touch .snap
	
depend: Rules.depend

ifeq "$(OS)" "linux"
Rules.depend: $(SRCFILES)
	$(CC) -MM $(INCLUDEDIRS) $(SRCFILES) | sed "s;\(^[^ 	]*\):\(.*\);$(OBJDIR_LINUX)/\1 $(OBJDIR_WIN)/\1: \2;" > $@
endif

include Rules.depend
