MAKEFILE = Makefile

UNAME=$(shell uname -s)
REDHAT_RELEASE = $(if $(wildcard /etc/redhat-release), -DREDHAT_RELEASE)
MAIN_DIR=$(shell pwd)
top_srcdir = ../..
BUILD_TARGET = orp

PLATFORM = $(top_srcdir)/os/$(UNAME)/platform_sticky_flag

CXX = g++
LINKER = g++
CC = gcc
IS_GCC = YES

NON_ORP_NATIVE_LIBS = #-DNON_ORP_NATIVE_LIBS
OLD_VERSION_CLASSPATH = #-DOLD_VERSION_CLASSPATH
LINUX_TLS_OPT = -DLINUX_TLS_OPT
ZIP_JAR_ARCHIVE = -DZIP_JAR_ARCHIVE 
USE_SEGMENT = #-DUSE_SEGMENT #see os/$(UNAME)/include/platform.h for TSD detail
MONITOR_STO = #-DMONITOR_STO
OLV2 = -DOBJECT_LOCK_V2
LAZY_LOCK = -DLAZY_LOCK
CONCURRENCY_ANALYSIS = #-DCONCURRENCY_ANALYSIS

GC = V2	 #use GC=V1 or GC=V2 to overide it for `make'
ifeq ($(GC), V1)
    GC_MODULE = gc
else
    GC_OPTIONS = -DGC_REWORK
    GC_MODULE = gc_v2
endif


CPP_DEFINES = -DORP_POSIX -D_REENTRANT -D__SMP__ \
	$(OLV2)	$(LAZY_LOCK)\
	$(CONCURRENCY_ANALYSIS) \
	$(ZIP_JAR_ARCHIVE) \
	$(REDHAT_RELEASE) \
	$(LINUX_TLS_OPT) $(USE_SEGMENT) \
	$(MONITOR_STO) \
	$(OLD_VERSION_CLASSPATH) \
	$(GC_OPTIONS) \
    $(NON_ORP_NATIVE_LIBS)

CPPFLAGS =  $(CPP_DEFINES) $(INCLUDES)


CXXFLAGS = 
DBG_CPPFLAGS = -D_DEBUG -DORP_STATS -DSIGNAL_DEBUG
DBG_CXXFLAGS = -g -O0
OPT_CPPFLAGS = -DNDEBUG
OPT_CXXFLAGS = -O 

INCLUDES = -I$(top_srcdir)/mains/orp \
 -I$(top_srcdir)/os/$(UNAME)/include \
 -I$(top_srcdir)/common/include \
 -I$(top_srcdir)/interface \
 -I$(top_srcdir)/base_natives/common \
 -I$(top_srcdir)/base_natives/common_olv2 \
 -I$(top_srcdir)/arch/ia32/ia32_o1_jit \
 -I$(top_srcdir)/arch/ia32/ia32_o3_jit \
 -I$(top_srcdir)/arch/ia32/dump/include \
 -I$(top_srcdir)/arch/ia32/debugger/include


COMMON_BASE_DIR = $(top_srcdir)/common/base
JAR_ZIP_UTILS_DIR = $(top_srcdir)/jar_zip_utils
ARCH_IA32_BASE_DIR = $(top_srcdir)/arch/ia32/base
ARCH_IA32_BASE_NATIVES_DIR = $(top_srcdir)/arch/ia32/base_natives
ARCH_IA32_O1_JIT_DIR = $(top_srcdir)/arch/ia32/ia32_o1_jit
ARCH_IA32_O3_JIT_DIR = $(top_srcdir)/arch/ia32/ia32_o3_jit
ARCH_IA32_X86_DIR = $(top_srcdir)/arch/ia32/x86
ARCH_IA32_DUMP_DIR = $(top_srcdir)/arch/ia32/dump
ARCH_IA32_DEBUGGER_DIR = $(top_srcdir)/arch/ia32/debugger
COMMON_JIT_UTILS_DIR = $(top_srcdir)/common/jit_utils
COMMON_CLASS_LOADER_DIR = $(top_srcdir)/common/class_loader
COMMON_GC_DIR = $(top_srcdir)/common/$(GC_MODULE)
BASE_NATIVES_COMMON_DIR = $(top_srcdir)/base_natives/common
BASE_NATIVES_COMMON_OLV2_DIR = $(top_srcdir)/base_natives/common_olv2
BASE_NATIVES_GNU_DIR = $(top_srcdir)/base_natives/gnu_classpath
OS_DIR = $(top_srcdir)/os/$(UNAME)

MODULES = \
 $(ARCH_IA32_O1_JIT_DIR) \
 $(ARCH_IA32_O3_JIT_DIR) \
 $(ARCH_IA32_DUMP_DIR) \
 $(ARCH_IA32_DEBUGGER_DIR) \
 $(COMMON_JIT_UTILS_DIR) \
 $(COMMON_CLASS_LOADER_DIR) \
 $(ARCH_IA32_BASE_DIR) \
 $(BASE_NATIVES_COMMON_DIR) \
 $(BASE_NATIVES_COMMON_OLV2_DIR) \
 $(ARCH_IA32_BASE_NATIVES_DIR) \
 $(COMMON_GC_DIR) \
 $(COMMON_BASE_DIR) \
 $(ARCH_IA32_X86_DIR) \
 $(BASE_NATIVES_GNU_DIR) \
 $(JAR_ZIP_UTILS_DIR) \
 $(OS_DIR) 

GENERIC_LIB_NAME = libvm.a
DBG_ARCHIVES := $(addsuffix /$(UNAME)/dbg/$(GENERIC_LIB_NAME), $(MODULES))
OPT_ARCHIVES := $(addsuffix /$(UNAME)/opt/$(GENERIC_LIB_NAME), $(MODULES))

ifeq ($(UNAME), FreeBSD)
  LINKER_FLAGS = -L/usr/local/lib -lpthread -lglib -lm -lgthread
else
  LINKER_FLAGS = -lglib -ldl -lm 
  ifdef USE_SEGMENT
    DBG_ARCHIVES := $(DBG_ARCHIVES) -lgthread
    OPT_ARCHIVES := $(OPT_ARCHIVES) -lgthread
  else
    DBG_ARCHIVES := $(DBG_ARCHIVES) /usr/lib/libpthread.a
    OPT_ARCHIVES := $(OPT_ARCHIVES) /usr/lib/libpthread.a
  endif
endif

LINKER_ENTRY =
LINKER_ARGS = $(LINKER_ENTRY) $(LINKER_FLAGS)



SOURCES = main.cpp stubs.cpp properties.cpp

DBGOBJ := $(SOURCES:%.cpp=$(UNAME)/dbg/%.o)
OPTOBJ := $(SOURCES:%.cpp=$(UNAME)/opt/%.o)
DBGDEP := $(SOURCES:%.cpp=$(UNAME)/dbg/dep/%.d)
OPTDEP := $(SOURCES:%.cpp=$(UNAME)/opt/dep/%.d)
DBG_READY_DEPS := $(wildcard $(DBGDEP))
OPT_READY_DEPS := $(wildcard $(OPTDEP))
DBG_MISSED_DEPS := $(filter-out $(DBG_READY_DEPS), $(DBGDEP))
OPT_MISSED_DEPS := $(filter-out $(OPT_READY_DEPS), $(OPTDEP))

BUILD_DBG_TARGET = $(UNAME)/dbg/$(BUILD_TARGET)
BUILD_OPT_TARGET = $(UNAME)/opt/$(BUILD_TARGET)

.PHONY: all opt dbg clean force platform
all:
	$(MAKE) dbg -f $(MAKEFILE)
	$(MAKE) opt -f $(MAKEFILE)

dbg: $(BUILD_DBG_TARGET)
opt: $(BUILD_OPT_TARGET)

%/$(UNAME)/dbg/$(GENERIC_LIB_NAME) : force
	@test -x $(@D) || mkdir -p $(@D)
	cd $(@D)/../.. ; $(MAKE) dbg -f $(MAKEFILE) 

%/$(UNAME)/opt/$(GENERIC_LIB_NAME) : force
	@test -x $(@D) || mkdir -p $(@D)
	cd $(@D)/../.. ; $(MAKE) opt -f $(MAKEFILE)

$(UNAME)/dbg/dep/%.d : %.cpp $(PLATFORM)
	@test -x $(UNAME)/dbg || mkdir -p $(UNAME)/dbg
	@test -x $(UNAME)/dbg/dep || mkdir -p $(UNAME)/dbg/dep
	!(test -e $@) || rm -f $@
	$(CXX) -MM $(CPPFLAGS) $(DBG_CPPFLAGS) $< \
	| sed 's|$*\.o[ :]*|$@ $(UNAME)/dbg/$*.o : |g' > $@

$(UNAME)/opt/dep/%.d : %.cpp $(PLATFORM)
	@test -x $(UNAME)/opt || mkdir -p $(UNAME)/opt
	@test -x $(UNAME)/opt/dep || mkdir -p $(UNAME)/opt/dep
	!(test -e $@) || rm -f $@
	$(CXX) -MM $(CPPFLAGS) $(OPT_CPPFLAGS) $< \
	| sed 's|$*\.o[ :]*|$@ $(UNAME)/opt/$*.o : |g' > $@

$(UNAME)/dbg/%.o : %.cpp $(PLATFORM)
	@test -x $(UNAME)/dbg || mkdir -p $(UNAME)/dbg
	$(CXX) -c $(CXXFLAGS) $(DBG_CXXFLAGS) $(DBG_CPPFLAGS) $(CPPFLAGS) $< -o $@

$(UNAME)/opt/%.o : %.cpp $(PLATFORM)
	@test -x $(UNAME)/opt || mkdir -p $(UNAME)/opt
	$(CXX) -c $(CXXFLAGS) $(OPT_CXXFLAGS) $(OPT_CPPFLAGS) $(CPPFLAGS) $< -o $@

$(BUILD_DBG_TARGET): $(DBG_MISSED_DEPS) $(DBG_ARCHIVES) $(DBGOBJ)
	@test -x $(UNAME)/dbg || mkdir -p $(UNAME)/dbg
	@test -x $(UNAME)/dbg/dep || mkdir -p $(UNAME)/dbg/dep
	$(LINKER) -o $(BUILD_DBG_TARGET) $(LINKER_ARGS) $(DBGOBJ) $(DBG_ARCHIVES)

$(BUILD_OPT_TARGET): $(OPT_MISSED_DEPS) $(OPT_ARCHIVES) $(OPTOBJ)
	@test -x $(UNAME)/opt || mkdir -p $(UNAME)/opt
	@test -x $(UNAME)/opt/dep || mkdir -p $(UNAME)/opt/dep
	$(LINKER) -o $(BUILD_OPT_TARGET) $(LINKER_ARGS) $(OPTOBJ) $(OPT_ARCHIVES) 

clean:
	@(!(test -e $(UNAME))&&(echo Already cleaned.)) || ( rm -fr $(UNAME); echo rm -rf $(UNAME))
	cd $(JAR_ZIP_UTILS_DIR);          $(MAKE) clean -f $(MAKEFILE)
	cd $(COMMON_BASE_DIR);            $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_BASE_DIR);         $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_BASE_NATIVES_DIR); $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_DUMP_DIR);      	  $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_DEBUGGER_DIR);     $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_O1_JIT_DIR);       $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_O3_JIT_DIR);       $(MAKE) clean -f $(MAKEFILE)
	cd $(ARCH_IA32_X86_DIR);          $(MAKE) clean -f $(MAKEFILE)
	cd $(COMMON_CLASS_LOADER_DIR);    $(MAKE) clean -f $(MAKEFILE)
	cd $(COMMON_GC_DIR);              $(MAKE) clean -f $(MAKEFILE)
	cd $(COMMON_JIT_UTILS_DIR);       $(MAKE) clean -f $(MAKEFILE)
	cd $(BASE_NATIVES_COMMON_DIR);    $(MAKE) clean -f $(MAKEFILE)
	cd $(BASE_NATIVES_COMMON_OLV2_DIR);$(MAKE) clean -f $(MAKEFILE)
	cd $(BASE_NATIVES_GNU_DIR);       $(MAKE) clean -f $(MAKEFILE)
	!(test -L $(OS_DIR)) || ( cd $(OS_DIR); $(MAKE) clean -f $(MAKEFILE))

ifeq ($(MAKECMDGOALS), dbg)
-include $(DBGDEP)
else
ifeq ($(MAKECMDGOALS), opt)
-include $(OPTDEP)
endif
endif

$(PLATFORM):
	if [ $(UNAME) = "Linux" ]; then \
		test -L $(top_srcdir)/os/Linux || ln -sfn linux $(top_srcdir)/os/Linux;\
        touch $(top_srcdir)/os/Linux/platform_sticky_flag; \
	elif echo $(UNAME) | grep -qi bsd; then \
		test -L $(top_srcdir)/os/$(UNAME) || ln -sfn bsd $(top_srcdir)/os/$(UNAME);\
        touch $(top_srcdir)/os/$(UNAME)/platform_sticky_flag; \
	fi
