# Specify these variables on Make's command line to compile different versions
DEBUGGING=
ifdef DEBUG
DEBUGGING=1
endif
MEMDEBUG=
MPI_DEBUG=
PROFILING=
GCOV=
MPI=
# turn on auto parallelisation (in icc)
PARALLEL=
# turn on OpenMP directives
OPENMP=
NOGUI=
VPROF=
#use Berkley database from Sleepycat for cacheDBM class
BDB=
# enable manual timing instrumentation
TIMER=
# use TkPhotoSurface for CairoItem, overriding platform specific optimisation
TKPHOTOSURFACE=

# enables ecolab for the MXE environment 
MXE=

# the long long data type is not part of the C++ standard, but is part of C99.
# all our list of compilers support long long, but if yours doesn't, you can 
# override long long support here.
HAVE_LONGLONG=1

# Force use of GCC. 
GCC=
# Force use of Intel compiler. 
ICC=

# On Macintosh, AQUA specifies the OS X Aqua versions of TCL/Tk
# Default is X11
AQUA=

# configuration variables generated by make configure
include $(ECOLAB_HOME)/include/Makefile.config

.SUFFIXES: .cd .d .rc $(SUFFIXES)
VPATH=$(ECOLAB_HOME)/include
PATH:=$(ECOLAB_HOME)/bin:$(PATH):$(HOME)/usr/bin
CLASSDESC=$(ECOLAB_HOME)/bin/classdesc
PKG_CONFIG_PATH:=$(HOME)/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/opt/local/lib/pkgconfig:$(PKG_CONFIG_PATH)
PKG_CONFIG=env PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config

# where to look for installed software (prefix values)
# nb Cygwin does not like /usr put here. Add it to the search command 
DIRS=$(ECOLAB_HOME) $(HOME)/usr /usr/local /opt/local /usr/X11R6
# a search mechanism to find a particular file
# use as $(call search,name)
ifdef MXE
search=$(firstword $(foreach dir,$(DIRS),$(wildcard $(dir)/$(1))))
else
search=$(firstword $(foreach dir,$(DIRS) /usr,$(wildcard $(dir)/$(1))))
endif

# where to find classdesc header files (eg pack_base.h)
CDINCLUDE=$(ECOLAB_HOME)/include

ifdef AEGIS
# unused-variable warnings fail certain RAII usages in C++
FLAGS+=-Werror -Wall -Wno-unused-variable
#-Wno-parentheses 
endif

# needed for generating .so files
ifndef MXE
FLAGS+=-fPIC
endif

# use mpicc etc by default if MPI set
ifdef MPI
HAVE_mpiCC=$(shell if which mpiCC>&/dev/null; then echo 1; fi)
CC=mpicc
ifeq ($(HAVE_mpiCC),1)
CPLUSPLUS=mpiCC
else
# newer versions of mpich use this name!!
CPLUSPLUS=mpicxx
endif
LINK=$(CPLUSPLUS)
CPP=$(CPLUSPLUS) -E

# disable inclusion of mpi++.h in the MPICH case (don't know what the problem is here)
FLAGS+=-UHAVE_MPI_CPP
else
CC=gcc
CPLUSPLUS=g++
LINK=g++
CPP=g++ -E
endif

ifdef MXE
MXE_PREFIX=i686-w64-mingw32.static
GCC=1
FLAGS+=-m32 -DSTATIC_BUILD -DNO_FWD_DECLARE_STL -DMXE
CC=$(MXE_PREFIX)-gcc
CPLUSPLUS=$(MXE_PREFIX)-g++
LINK=$(CPLUSPLUS)
CPP=$(CPLUSPLUS) -E
# rewrite ecolab home to be the mxe one
ifeq ($(ECOLAB_HOME),$(HOME)/usr/ecolab)
ECOLAB_HOME=$(HOME)/usr/mxe/ecolab
endif
DIRS=$(ECOLAB_HOME) $(HOME)/usr/mxe $(subst bin/$(CPLUSPLUS),$(MXE_PREFIX),$(shell which $(CPLUSPLUS)))
PKG_CONFIG_PATH:=$(HOME)/usr/mxe/lib/pkgconfig:$(PKG_CONFIG_PATH)
PKG_CONFIG=env PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(MXE_PREFIX)-pkg-config

# xdr on MXE is positively ancient, so just disable it here
XDR=

# rule for running the resource compiler
.rc.o:
	$(MXE_PREFIX)-windres -O coff -i $< -o $@

.rc.d:
	touch $@
endif

ifdef NOGUI
TK=
endif

ifdef TIMER
FLAGS+=-DTIMER
endif

# add an appropriate extension to allow MPI and ICC builds to coexist with GCC
ifdef MPI
ECOLIBS_EXT=_mpi
else
ifeq ($(CPLUSPLUS),icc)
ECOLIBS_EXT=_icc
else
ECOLIBS_EXT=
endif
endif

# do it this way to help Makefile dependencies work
ECOLIBS=$(ECOLAB_HOME)/lib/libecolab$(ECOLIBS_EXT).a

LIBS+=-L$(ECOLAB_HOME)/lib -lecolab$(ECOLIBS_EXT)
FLAGS+=-I. -I$(ECOLAB_HOME)/include -DHASH_TCL_hash

# The following section uses GNU Make specific syntax. If not using
# GNU Make, edit the  FLAGS, LIBS, CC,
# CPLUSPLUS, LINK and ARRAYS string.

HOST=$(shell hostname)
OS=$(shell uname)

# Detect whether this is an Altix
IS_ALTIX=$(wildcard /proc/sgi_sn)

# XDR and MPI don't work together on Altix
ifeq ($(IS_ALTIX),/proc/sgi_sn)
ifdef MPI
XDR=
endif
endif

ifeq ($(OS),Linux)
# try to detect Intel C++ compiler if GCC not set
ifdef ICC
HAVE_ICC=$(shell if which icc>/dev/null; then echo 1; fi)
ifeq ($(HAVE_ICC),1)
ifndef MPI
CC=icc
CPLUSPLUS=icpc 
# icc no longer correctly links C++ compiled object files unless -Kc++ is specified!!
LINK=icc -Kc++
endif
endif
endif
ifndef MXE
LIBS+=-ldl
endif
endif

ifdef MXE
LIBS+=-lshlwapi
endif

ifeq ($(OS),IRIX64)
ifndef GCC
ifndef MPI
CC=cc
CPLUSPLUS=CC
CPP=CC -E
LINK=CC
endif
FLAGS+=-n32 -LANG:std -ptused
LIBS+=-L/usr/lib32
else
LIBS+=-L/usr/lib32
endif
endif

ifeq ($(OS),Darwin)
XDR=
# Darwin has some very old software installed. We need to ensure
#/usr/local/include and /opt/local/include is searched before
#/usr/X11R6/include In the move to Mavericks and beyond, clang is
#used, which doesn't even support TR1, so we must deploy boost!
FLAGS+=-isystem /usr/local/include -isystem /opt/local/include -isystem /usr/X11R6/include -DBOOST_TR1 -DNO_FWD_DECLARE_STL
LIBS+=-framework Carbon -liconv -framework IOKit -lpixman-1 -lffi
ifdef AQUA
FLAGS+=-I$(HOME)/Library/Frameworks/Tcl.framework/Headers \
  -I/Library/Frameworks/Tcl.framework/Headers \
  -I$(HOME)/Library/Frameworks/Tk.framework/Headers \
  -I/Library/Frameworks/Tk.framework/Headers \
  -F$(HOME)/Library/Frameworks
BLT=
endif
endif

ifdef HAVE_LONGLONG
FLAGS+=-DHAVE_LONGLONG
endif

ifeq ($(CC),icc)
FLAGS+=-DBOOST_TR1
else
ifneq ($(OS),Darwin)
# enable the use of TR1 - good for gcc
FLAGS+=-DTR1
endif
endif

# add standard list of search paths, -L/usr/lib32 must be before this statement
LIBS+= $(DIRS:%=-L%/lib) 
FLAGS+=$(DIRS:%=-I%/include)

# canonicalise CYGWIN's OS name
ifeq ($(findstring CYGWIN,$(OS)),CYGWIN)
OS=CYGWIN
XDR=
CLASSDESC=$(ECOLAB_HOME)/bin/classdesc.exe
endif

# canonicalise MINGW's OS name
ifeq ($(findstring MINGW,$(OS)),MINGW)
OS=MINGW
XDR=
endif

ifdef MEMDEBUG
FLAGS+=-DMEMDEBUG
endif

ifdef MPI_DEBUG
FLAGS+=-DMPI_DEBUG
endif

ifdef GCOV
FLAGS+=-fprofile-arcs -ftest-coverage
endif

ifdef PROFILING
FLAGS+=-DTIMECMDS 
endif

ifdef TKPHOTOSURFACE
FLAGS+=-DTKPHOTOSURFACE
endif

ifdef TK
ifdef BLT
FLAGS+= -DBLT 
#ifeq ($(OS),CYGWIN)
#LIBS+=-lBLT24
#else
LIBS+= -lBLT
#endif
endif
endif

ifdef UNURAN
FLAGS+=-DUNURAN
LIBS+=-lunuran
ifdef PRNG
FLAGS+=-DPRNG
LIBS+=-lprng
endif
endif

ifdef GNUSL
FLAGS+=-DGNUSL
LIBS+=-lgsl
HAVE_CBLAS=$(words $(wildcard $(call search,lib/libgslcblas.*)))
ifeq ($(HAVE_CBLAS),0)
# if this is a 64 bit system, we also need to check lib64
HAVE_CBLAS=$(words $(wildcard $(call search,lib64/libgslcblas.*)))
endif
ifneq ($(HAVE_CBLAS),0)
LIBS+=-lgslcblas
endif
endif

ifdef SAUCY
FLAGS+=-DSAUCY
LIBS+=-lsaucy
endif

ifdef LAPACK
FLAGS+= -DLAPACK
LIBS+= lapack.a
endif

ifdef MPI
ifdef LAMHOME
FLAGS+=-I$(LAMHOME)/include
LIBS+=-L$(LAMHOME)/lib -lmpi -llam
endif
FLAGS+=-DMPI_SUPPORT -I/usr/local/mpi/include -L/usr/local/mpi/lib
ifdef PARMETIS
FLAGS+=-DPARMETIS
LIBS+=-lparmetis -lmetis 
endif
endif

ifdef ZLIB
FLAGS+=-DZLIB
LIBS+=-lz
endif

ifdef XDR
FLAGS+=-DXDR_PACK
endif

ifdef READLINE
FLAGS+=-DREADLINE
LIBS+=-lreadline -lncurses
endif

ifdef BDB
FLAGS+=-DBDB
LIBS+=-ldb
endif

ifdef IGRAPH
FLAGS+=-DIGRAPH
LIBS+=-ligraph -lgmp
endif

ifdef CAIRO
FLAGS+=-DCAIRO $(shell $(PKG_CONFIG) --cflags cairo)
LIBS+=$(shell $(PKG_CONFIG) --libs cairo)
ifeq ($(OS),MINGW)
LIBS+=-lgdi32 -lmsimg32
endif
endif

ifdef GDBM
FLAGS+=-DUSE_DBM
ifdef GDBM_COMPAT
LIBS+=-lgdbm_compat
endif
LIBS+=-lgdbm
endif

ifdef MAP
FLAGS+=-DMAP=$(MAP)
endif

ifndef GCOV
FLAGS+= -DCONTIGUOUS
endif
ARRAYS=c_arrays.o

ifeq ($(OS),SunOS) 
LIBS+= -lsocket -lnsl -ldl
endif

ifeq ($(OS),OSF1)
SHELL=bash
ifndef GCC
ifndef MPICC
CC=cc
CPP_FLAGS=-ptr $(ECOLAB_HOME)/cxx_repository 
CPLUSPLUS=cxx $(CPP_FLAGS)
CPP=cxx -E 
LINK=cxx $(CPP_FLAGS)
FLAGS+= -DNO_HASH -D_POSIX_SOURCE -D__STDC__ -D__USE_STD_IOSTREAM -DRUNTIME_LINK_ERROR
endif
endif
endif

ifdef TK
FLAGS+=-DTK
endif

# this conditional ensure TCL is present before doing this stuff, as
# otherwise Make hangs
ifneq ($(call search,lib*/tclConfig.sh),)

ifdef AQUA
ifdef TK
TCLLIBS=-framework Tk
endif
TCLLIBS+=-framework Tcl
else
TCLVERSION=$(shell . $(call search,lib*/tclConfig.sh); echo $$TCL_VERSION)
ifdef TK
TCLLIBS+=$(shell . $(call search,lib*/tkConfig.sh); echo $$TK_LIB_FLAG $$TK_STUB_LIB_FLAG)
FLAGS+=$(shell . $(call search,lib*/tkConfig.sh); echo $$TK_INCLUDE_SPEC)
endif
TCLLIBS+=$(shell . $(call search,lib*/tclConfig.sh); echo $$TCL_LIB_SPEC $$TCL_STUB_LIB_FLAG)
ifdef TK
TCLLIBS+=$(shell . $(call search,lib*/tkConfig.sh); echo $$TK_LIBS)
else
TCLLIBS+=$(shell . $(call search,lib*/tclConfig.sh); echo $$TCL_LIBS)
endif
FLAGS+=$(shell . $(call search,lib*/tclConfig.sh); echo $$TCL_INCLUDE_SPEC)
endif
endif

ifeq ($(OS),CYGWIN)
#The default Cygwin installation of Tcl/Tk stuffs up tcl/tkConfig.sh,
#so we must correct it
#Note that the default Cygwin installtion of Tcl/Tk does not work on Windows 7
ifeq ($(TCLLIBS),"")
#TCLLIBS=
ifdef TK
TCLLIBS+=-ltk
endif
TCLLIBS+=-ltcl
endif
endif

#ifndef MXE
#ifneq ($(OS),MINGW)
#ifdef TK
#TCLLIBS+=-lX11
#endif
#endif
#endif

# AIX defines an exception class in it's math.h header. This fixes its wagon.
ifeq ($(OS),AIX)
ifdef GCC
FLAGS+=-D_POSIX_SOURCE
else
CC=xlc
CPLUSPLUS=xlC
CPP=xlC -E
LINK=xlC
FLAGS+=-DNO_HASH -w
endif
endif

#ifeq ($(OS),CYGWIN)
#CYG_ECOLAB_LIB=$(subst \,/,$(shell cygpath -w  $(ECOLAB_HOME)/include))
#FLAGS+=-DECOLAB_LIB=\"$(CYG_ECOLAB_LIB)\"
#else
FLAGS+=-DECOLAB_LIB=\"$(ECOLAB_HOME)/include\"
#endif

ifdef DEBUGGING
OPT+=-g
else
FLAGS+= -DNDEBUG
ifeq ($(OS),OSF1)
OPT=-O4
else
OPT=-O3
endif
endif

ifdef PARALLEL
ifeq ($(CC),icc)
OPT+=-parallel
endif
endif

ifdef OPENMP
ifeq ($(CC),gcc)
OPT+=-fopenmp
endif
ifeq ($(CC),icc)
OPT+=-openmp
endif
endif

# prefer to usde -f flag if available
CHMOD=chmod -f
ifeq ($(OS),IRIX64)
CHMOD=chmod
endif

# End of GNU Make dependent section
# default flags go here
FLAGS+=-I$(ECOLAB_HOME)/include
#LIBS+= -L/usr/X11/lib -L/usr/X11R6/lib64 -L/usr/X11R6/lib $(TCLLIBS)  -lm
LIBS+= $(TCLLIBS)  -lm
LINK+=$(OPT)

# modules that need to be directly linked into ecolab model file
# we need to avoid main() being included because of icc linkage behaviour!

# In the olden days, we explicitly included the modules. But this runs
# afoul of Xcode on MacOSX since about 3.2 somthing. So now, we must
# include a specific variable which we ask for with a -u option to
# force linkage

# following lines left for historical reference for non-gcc style systems
#LIBMODS=tcl_arrays.o tclgraph.o analysis.o random.o cairo_types.o plot.o
LIBMODS=

# modules to include on the MODLINK command line
ALWAYSLINK=tcl_arrays tclgraph analysis random cairo_types plot

# for some reason, the -u option doesn't work with MXE
ifdef MXE
LIBMODS=$(ALWAYSLINK:%=%.o) ecolabResources.o
endif

MODS=tclmain.o $(LIBMODS)
MODLINK=$(MODS:%=$(ECOLAB_HOME)/lib/%)


# different OSes have different symbol naming conventions, alas!
ifeq ($(OS),Linux)
MODLINK+=$(ALWAYSLINK:%=-u ecolab_%_link)
else
MODLINK+=$(ALWAYSLINK:%=-u _ecolab_%_link)
endif

ifdef VPROF
# work out where vprof object file lives
FLAGS+=-g
ifdef MPI
MODLINK+=$(call search,lib/vmonauto_pmpi.o)
#LIBS+=-lpmpich
else
ifeq ($(CC),gcc)
MODLINK+=$(call search,lib/vmonauto_gcc.o)
else
MODLINK+=$(call search,lib/vmonauto.o)
endif
endif
#LIBS+=-lvmon -lpapi
LIBS+=-lvmon
endif

ifdef PANGO
FLAGS+=-DPANGO $(shell $(PKG_CONFIG) --cflags pangocairo)
LIBS+=$(shell $(PKG_CONFIG) --libs pangocairo)
endif

# list of actions to do classdesc on
ACTIONS=pack unpack
RPACTIONS=TCL_obj isa

.SUFFIXES: .cc .c .o .h .d .cd

.cc.o: 
	$(CPLUSPLUS) -c $(FLAGS) $(OPT) -o $@ $<

.c.o: 
	$(CC) -c $(FLAGS) $(OPT) -o $@ $<

#src/tclgraph.o: src/tclgraph.cc
#	$(CPLUSPLUS) -c $(FLAGS) -O1 -o $@ $<

#how to build a utility executable
$(UTILS): %: %.cc tokeninput.h
	$(CPLUSPLUS) -g $< -o $@

.c.d: 
	$(CC) $(FLAGS) -MM -MG  $< >$@

.cc.d: 
	$(CPLUSPLUS) $(FLAGS) -MM -MG $< >$@

.h.cd: $(CLASSDESC)
	$(CLASSDESC) -nodef -typeName -i $< >$@
	$(CLASSDESC) -nodef -onbase -I $(CDINCLUDE) -I $(ECOLAB_HOME)/include -i $< $(ACTIONS) >>$@
	$(CLASSDESC) -nodef -onbase -typeName -I $(CDINCLUDE) -I $(ECOLAB_HOME)/include -i $< \
	  -respect_private  $(RPACTIONS) >>$@
# command to remove standard built files
BASIC_CLEAN=rm -f *.o  *~ \\\#* core *.exh *.exc *.d *,D *.exe *.cd
