# SPICE OPUS make file

# This file must be included in every other Makefile at the top. 
# The include must be relative to the location of the Makefile. 

######## Edit option defaults

# If SPICETREE is defined, it is used as the directory where the source 
# resides in src/spiceopus. . 
# If OPUSHOME is used the cmpp from OPUSHOME/bin is used, otherwise
# the cmpp that is built with the source is used. 

# Debian etch
# GCC   = gcc-3.3
# GCCPP = g++-3.3

# Debian lenny, before Qt4
# GCC   = gcc-4.2
# GCCPP = g++-4.2

# Debian lenny, Qt4
GCC   = gcc
GCCPP = g++


# release
GCCOPTS = -O1 -fPIC -pipe -DQT3_SUPPORT -DNO_DEBUG -DCM_LINUX -DLINUX -Dlnxqt -DIPC_DEBUG_VIA_STDIO -D_REENTRANT -I$(BUILDTREE)/include -I$(BUILDTREE)/lib/qtfte -I$(QTDIR)/include
LINKFLAGS = 
CRYPTOPPLIB = $(CRYPTOPPDIR)/libcryptopp.a
QTLIB = $(QTDIR)/lib/libQt3Support.a $(QTDIR)/lib/libQtGui.a $(QTDIR)/lib/libQtWebKit.a $(QTDIR)/lib/libQtCore.a 
# debug
# GCCOPTS = -g -fPIC -pipe -DQT3_SUPPORT -DCM_LINUX -DLINUX -Dlnxqt -DIPC_DEBUG_VIA_STDIO -D_REENTRANT -I$(BUILDTREE)/include -I$(BUILDTREE)/lib/qtfte -I$(QTDIR)/include
# LINKFLAGS = -g
# CRYPTOPPLIB = $(CRYPTOPPDIR)/libcryptoppd.a
# QTLIB = $(QTDIR)/lib/libQt3Support.a $(QTDIR)/lib/libQtGui.a $(QTDIR)/lib/libQtWebKit.a $(QTDIR)/lib/libQtCore.a 

CMPP = $(CMPPDIR)/cmpp.bin

MOC = $(QTDIR)/bin/moc

FLEX = flex

BISON = bison

AR = ar

RANLIB = ranlib

DEFAULT_TARGET_TYPE = staticlib

######## No editing beyond this point

# Determine architecture
ifndef HOSTTYPE
	HOSTTYPE := $(shell echo $$HOSTTYPE)
endif

# Static libc++ link (Debian etch)
#SYSLIBS = /usr/lib/gcc-lib/i486-linux-gnu/3.3.6/libstdc++.a \
#	/usr/lib/gcc-lib/i486-linux-gnu/3.3.6/libgcc.a \
#	/usr/lib/gcc-lib/i486-linux-gnu/3.3.6/libgcc_eh.a

# Static libc++ link (Debian lenny), before Qt4
# ifeq ($(HOSTTYPE),x86_64)
# 	SYSLIBS = /usr/lib/gcc/x86_64-linux-gnu/4.2.4/libstdc++.a \
# 		/usr/lib/gcc/x86_64-linux-gnu/4.2.4/libgcc.a \
# 		/usr/lib/gcc/x86_64-linux-gnu/4.2.4/libgcc_eh.a
# else
# 	SYSLIBS = /usr/lib/gcc/i486-linux-gnu/4.2.4/libstdc++.a \
# 		/usr/lib/gcc/i486-linux-gnu/4.2.4/libgcc.a \
# 		/usr/lib/gcc/i486-linux-gnu/4.2.4/libgcc_eh.a
# endif

# Static libc++ link (Debian lenny), Qt4
ifeq ($(HOSTTYPE),x86_64)
	SYSLIBS = /usr/lib/gcc/x86_64-linux-gnu/4.3.2/libstdc++.a \
		/usr/lib/gcc/x86_64-linux-gnu/4.3.2/libgcc.a \
		/usr/lib/gcc/x86_64-linux-gnu/4.3.2/libgcc_eh.a
else
	SYSLIBS = /usr/lib/gcc/i486-linux-gnu/4.3.2/libstdc++.a \
		/usr/lib/gcc/i486-linux-gnu/4.3.2/libgcc.a \
		/usr/lib/gcc/i486-linux-gnu/4.3.2/libgcc_eh.a
endif


# Full dynamic link
# SYSLIBS = -lstdc++

# Full static link
# SYSLIBS = -lstdc++ -static

# Use SPICETREE environmental variable; if not defined, use OPUSHOME. If 
# OPUSHOME is also not defined, report an error. 
ifdef SPICETREE
  CMPPDIR=$(SPICETREE)/src/spiceopus/cmpp
else ifdef OPUSHOME
  $(info Using OPUSHOME environmental variable as SPICETREE ...)
  SPICETREE=$(OPUSHOME)
  CMPPDIR=$(OPUSHOME)/bin
else
  $(error Define either SPICETREE or OPUSHOME environmental variable to compile...)
endif

# This is the source tree
BUILDTREE = $(SPICETREE)/src/spiceopus

# Build object list from sources
OBJS =	$(patsubst %.c,%.o,$(wildcard *.c)) \
	$(patsubst %.ifs,%_ifstmp.o,$(wildcard *.ifs)) \
	$(patsubst %.mod,%_modtmp.o,$(wildcard *.mod)) \
	$(patsubst %.l,%.o,$(wildcard *.l)) \
	$(patsubst %.y,%.o,$(wildcard *.y)) \
	$(patsubst %.h,%_moc.o,$(MOC_SOURCES)) \
	$(patsubst %.cpp,%.o,$(wildcard *.cpp))

# CM and UDN list targets
CMLISTS = cminfo.h cmextrn.h 
UDNLISTS = udninfo.h udnextrn.h

# Default target type if it is not specified
ifdef TARGET_TYPE
else
  # If TARGET is defined, the default is taken from DEFAULT_TARGET_TYPE, 
  # otherwise it is empty. 
  ifdef TARGET
    TARGET_TYPE=$(DEFAULT_TARGET_TYPE)
    $(info Using default target type $(TARGET_TYPE))
  else
    TARGET_TYPE=empty
  endif
endif
$(info Target type is $(TARGET_TYPE))

# all, subdirs, and actual subdirs are phony targets
.PHONY: all subdirs $(SUBDIRS)

# Default target
all: makeall

# Handling all subdirs involves handling actual subdirs
subdirs: $(SUBDIRS)

# Handle one subdir, enter into it and run make
ifdef SUBDIRS
$(SUBDIRS):
	$(MAKE) -C $@
endif

# All binary and shared library targets depend on subdirs. 
# Static libraries can be assembled only of the objects in the directory,
# but not in the subdirectories. Therefore Static libraries do not depend
# on the subdirectories.
ifeq ($(TARGET_TYPE),binary)
# Ordinary binary targets, link OBJS, LIBS, user-specified SYSLIBS and SYSLIBS
makeall: $(TARGET)

$(TARGET): $(OBJS) $(LIBS)
	$(GCC) -o $@ $(LINKFLAGS) $(LOCAL_LINKFLAGS) $(OBJS) $(LIBS) $(LOCAL_SYSLIBS) $(SYSLIBS) 
else ifeq ($(TARGET_TYPE),sharedlib)
# Shared library targets, do not link with SYSLIBS, link only with user-specified SYSLIBS 
makeall: $(TARGET)

$(TARGET): subdirs $(OBJS) $(LIBS)
	$(GCC) -o $@ -shared $(LINKFLAGS) $(LOCAL_LINKFLAGS) $(OBJS) $(LIBS) $(LOCAL_SYSLIBS)
else ifeq ($(TARGET_TYPE),staticlib)
# Static library targets, assemble .o files
makeall: subdirs $(TARGET)

$(TARGET): $(OBJS)
	$(AR) rc $@ $?
	$(RANLIB) $@
else
# No target specified, just go through subdirs. 
makeall: subdirs

endif

# Keep these intermediate files around - all object files are precious, even if they are intermediate
.PRECIOUS: %.o 
# %_yacc.c %_tok.h 
# %_lex.c 
# %_modtmp.c %_ifstmp.c
# %_moc.cpp

# Rule for compiling C sources to object files
%.o: %.c
	$(GCC) $(GCCOPTS) $(LOCAL_GCCOPTS) -c $<

# Rule for compiling C++ sources to object files
%.o: %.cpp
	$(GCCPP) $(GCCOPTS) $(LOCAL_GCCOPTS) -c $<

# Rule for building moc C++ files from QT headers
%_moc.cpp: %.h
	$(MOC) -o $@ $<

# Rule for compiling .mod description of a CM to a C source file
%_modtmp.c: %.mod %.ifs
	$(CMPP) -mod $*.mod $*.ifs $*_modtmp.c

# Rule for compiling .ifs description of a CM to a C source file
%_ifstmp.c: %.ifs
	$(CMPP) -ifs $*.ifs $*_ifstmp.c

# Turn off built-in rule for .l files (lexer, flex)
%.c: %.l

# Rule for compiling flex (.l) files to C source files
%_lex.c:%_lex.l %_yacc.c
	$(FLEX) -Pyy_$(patsubst %_lex.l,%,$<)_ -t $< > $@

# Rule for compiling bison (.y) files to C source files
%_yacc.c %_tok.h: %_yacc.y
	$(BISON) -t -p yy_$(patsubst %_yacc.y,%,$<)_ -y -d $<
	mv y.tab.c $(patsubst %_yacc.y,%,$<)_yacc.c
	mv y.tab.h $(patsubst %_yacc.y,%,$<)_tok.h

# Rule for building CM lists
$(CMLISTS): modpath.lst
	$(CMPP) -lst

# Rule for building UDN lists
$(UDNLISTS): udnpath.lst
	$(CMPP) -lst

# Additional dependencied for dlmain.o (causes CM and UDN list to be built)
# dlmain.o depends on cm and udn lists being available
# This is a more specific rule than the general .c to .o rule. 
dlmain.o: dlmain.c $(CMLISTS) $(UDNLISTS)

# Clean targets are phony
.PHONY: clean cleansubs

# Clean subdirectories
cleansubs:
	@for dir in $(SUBDIRS); do \
		$(MAKE) -C $$dir clean; \
	done

# Clean contents of a directory, causes the subdirectories to be cleaned first
clean: cleansubs
	rm -f $(CMLISTS) $(UDNLISTS) *.o *_ifstmp.c *_modtmp.c *_yacc.c *_tok.h *_lex.c $(TARGET) *_moc.cpp *.a

# Install targets are phony
.PHONY: install installsubs

# Install in all subdirectories
installsubs:
	@for dir in $(SUBDIRS); do \
		$(MAKE) -C $$dir install; \
	done

# Define install for a directory if there is anything to install
ifdef INSTALL_DESTINATION
# Install from a directory, handle subdirectories first, build TARGET
install: installsubs $(TARGET)
	@echo Installing $(TARGET) to $(INSTALL_DESTINATION)
	cp $(TARGET) $(INSTALL_DESTINATION)
else
# Say we have nothing to install
install: installsubs
	@echo Nothing to install in $(shell pwd)
endif
