#* *********************************************************************
#  | The Q language - A C++ extension for programming quantum machines |
#  | Copyright (C) 2000 2001 2002 2003 Stefano Bettelli                |
#  | <bettelli@irsamc.ups-tlse.fr>                                     |
#  | See the COPYING and LICENSE files for license terms.              |
#  ********************************************************************* */

APPNAME		= test
LQUANTUM	= quantum
LQPRIM		= qprimitives
LQLIB		= qstdlib
VER1		= 0
VER2		= 7.2
PTHREADS	= no
#--------------------------------------------------------#
SHELL		= /bin/bash
CXX		= g++
LD		= ld
NICE		= nice
STRIP		= strip
OPTIMISE        = -O9
CXXWARNINGS	= -Wall -W -Wpointer-arith -Wwrite-strings -Wcast-align      \
		  -Wmissing-prototypes -Wcast-align -Wconversion -Wcast-qual \
		  -Wstrict-prototypes -Wredundant-decls -Woverloaded-virtual \
		  -Wold-style-cast -pedantic -std=c++98
CXXFLAGS	= -L. $(OPTIMISE) -felide-constructors -fno-rtti
LIBS		= -lm
ifeq ($(PTHREADS),yes)
CXXFLAGS	+= -DQINTERFACE_USES_PTHREADS -pthread #-D_REENTRANT
LIBS		+= -pthread #-lpthread
endif
OBJ_DIR		= .Objects
DEP_DIR		= .Dependencies
QUANTUM_OBJ	= qsegment.o qsummary.o qlist.o qlist_map.o qbitset.o      \
		  qinterface_base.o qmanager_base.o qop_slice_basegate.o   \
		  qop_slice.o qop_summary.o qop_slicelist.o qop_simplify.o \
		  qoperator_control.o qregister.o qoperator.o
QPRIM_OBJ	= qop_basegates.o qop_phase_like.o qop_primitives.o        \
		  qop_builders.o qmanager.o qprimitives.o qinterface.o     \
		  qinterface_runev.o qsimulator.o
QLIB_OBJ	= qntlib_bigint.o qntlib_expower.o
LIB_OBJ		= $(QUANTUM_OBJ) $(QPRIM_OBJ) $(QLIB_OBJ)
TEST_OBJ	= test.o
OBJ		= $(LIB_OBJ) $(TEST_OBJ)
DEP		= $(OBJ:.o=.dep)
LIB_OBJECTS	= $(addprefix $(OBJ_DIR)/,$(LIB_OBJ))
TEST_OBJECTS	= $(addprefix $(OBJ_DIR)/,$(TEST_OBJ))
OBJECTS		= $(LIB_OBJECTS) $(TEST_OBJECTS)
DEPENDENCIES	= $(addprefix $(DEP_DIR)/,$(DEP))
LALL		= $(LQUANTUM) $(LQPRIM) $(LQLIB)
VER		= $(VER1).$(VER2)
libname		= lib$(1).so.$(VER)
linkname	= lib$(1).so.$(VER1)
libtolink	= $(subst $(VER),$(VER1),$(1))
ALL_LIBS	= $(foreach n,$(LALL),$(call libname,$n))
ALL_LINKS	= $(foreach n,$(LALL),$(call linkname,$n))

# sed will build dependencies' dependencies for us on the fly
SEDTRANS	= | sed 's/\(.*\)\.o:/$(OBJ_DIR)\/\1.o $(DEP_DIR)\/\1.dep :/'

.PHONY: all clean flags

all     : flags $(APPNAME) $(ALL_LIBS)

# how to build the main executable
$(APPNAME) : $(ALL_LIBS) $(TEST_OBJECTS)
	@echo "====== Creating the test executable ======"
	@$(NICE) $(CXX) $(OPTIMISE) $(TEST_OBJECTS) \
		 $(LIBS) $(ALL_LIBS) -o $(APPNAME)
	$(STRIP) $(APPNAME)

# Dependencies for shared libraries
$(call libname,$(LQUANTUM)) : $(addprefix $(OBJ_DIR)/,$(QUANTUM_OBJ))
$(call libname,$(LQPRIM))   : $(addprefix $(OBJ_DIR)/,$(QPRIM_OBJ))
$(call libname,$(LQLIB))    : $(addprefix $(OBJ_DIR)/,$(QLIB_OBJ))

# How to build a shared library (need deps)
$(ALL_LIBS) :
	@echo "=====> Creating library" $@
	@$(NICE) $(CXX) $(OPTIMISE) -shared \
		 -Wl,-soname,$(call libtolink,$@) -o $@ $^
	@$(NICE) ln -sf $@ $(call libtolink,$@)
	$(STRIP) $@

# object file creation from generic C++ sources
$(OBJECTS) :
	@if [ ! -d $(OBJ_DIR) ]; then mkdir $(OBJ_DIR); fi
	@echo Compiling $@
	@$(NICE) $(CXX) $(CXXFLAGS) $(CXXWARNINGS) -o $@ -c $<

# How to build a dependency file. "sed" creates dependencies' dependencies!
$(DEPENDENCIES) : $(DEP_DIR)/%.dep : %.cc
	@if [ ! -d $(DEP_DIR) ]; then mkdir $(DEP_DIR); fi
	@echo "Creating dependency " $@
	@$(NICE) $(SHELL) -c "$(CXX) $(CXXFLAGS) -M -w $< $(SEDTRANS)" > $@

# include dependencies (build them if absent)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPENDENCIES)
endif

# show compilation flags
flags 	: 
	@echo C++ compiler version is `$(CXX) --version | head -n1`;
	@#echo Warning flags are $(CXXWARNINGS);
	@echo Compilation flags are $(CXXFLAGS);

# remove everything which can be rebuilt
clean   :
	rm -f *~ core gmon.out $(APPNAME);
	rm -f $(ALL_LIBS);
	rm -f $(ALL_LINKS)
	rm -rf $(DEP_DIR) $(OBJ_DIR);

