#-----------------------------------------------------------------------------#
# Copyright (C) 1998-2001 The University of Melbourne.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#-----------------------------------------------------------------------------#

# Mmake - Mmake file for the Mercury runtime library

MAIN_TARGET=runtime

MERCURY_DIR=..
include $(MERCURY_DIR)/Mmake.common
-include Mmake.runtime.params

#-----------------------------------------------------------------------------#

CFLAGS		= -g $(DLL_CFLAGS)
MGNUC		= MERCURY_ALL_C_INCL_DIRS=" \
			-I$(RUNTIME_DIR) \
			-I$(BOEHM_GC_DIR) \
			-I$(BOEHM_GC_DIR)/include \
			" \
		  $(SCRIPTS_DIR)/mgnuc 
MGNUCFLAGS	= --no-ansi
MOD2C		= $(SCRIPTS_DIR)/mod2c

#-----------------------------------------------------------------------------#

# All the headers in $(HDRS) should be syntactically well-formed
# header files, unlike the headers in $(BODY_HDRS).
# All the headers in $(HDRS) must also be in C (not C++).

#		  keep this list in alphabetical order, please
HDRS		=	\
			mercury.h		\
			mercury_accurate_gc.h	\
			mercury_agc_debug.h	\
			mercury_array_macros.h	\
			mercury_bootstrap.h	\
			mercury_calls.h		\
			mercury_conf.h		\
			mercury_conf_param.h	\
			mercury_context.h	\
			mercury_debug.h		\
			mercury_deep_copy.h	\
			mercury_dummy.h		\
			mercury_dlist.h		\
		  	mercury_engine.h	\
			mercury_file.h		\
			mercury_float.h		\
			mercury_getopt.h	\
			mercury_goto.h		\
			mercury_grade.h		\
			mercury_hash_table.h	\
			mercury_heap.h		\
			mercury_heap_profile.h	\
			mercury_ho_call.h	\
			mercury_imp.h		\
			mercury_init.h		\
			mercury_label.h		\
			mercury_layout_util.h	\
			mercury_library_types.h	\
			mercury_memory.h	\
			mercury_memory_zones.h	\
			mercury_memory_handlers.h	\
			mercury_misc.h		\
			mercury_overflow.h	\
			mercury_prof.h		\
			mercury_prof_mem.h	\
			mercury_reg_workarounds.h	\
			mercury_regorder.h	\
			mercury_regs.h		\
			mercury_signal.h	\
			mercury_std.h		\
			mercury_stack_layout.h	\
			mercury_stack_trace.h	\
			mercury_stacks.h	\
			mercury_string.h	\
			mercury_tabling.h	\
			mercury_tabling_macros.h	\
			mercury_tags.h		\
			mercury_thread.h	\
			mercury_timing.h	\
			mercury_trace_base.h	\
			mercury_trail.h		\
			mercury_types.h		\
			mercury_type_info.h	\
			mercury_type_tables.h	\
			mercury_wrapper.h	\
			$(LIB_DLL_H)

# The headers in $(BODY_HDRS) contain code schemes included multiple times
# in one source file each. Their dependencies must be explicitly listed.
# They do not have to be syntactically well-formed.

BODY_HDRS	=	\
			mercury_deep_copy_body.h \
			mercury_make_type_info_body.h	\
			mercury_unify_compare_body.h

# Note that $(LIB_GLOBALS_H) cannot be part of $(HDRS), since it depends on
# lib$(RT_LIB_NAME)$(DLL_DEF_LIB).$A, and $(OBJ) : $(HDRS) would create a
# circular dependency.

MACHHDRS	= 	machdeps/no_regs.h	\
			machdeps/i386_regs.h	\
			machdeps/mips_regs.h	\
			machdeps/sparc_regs.h	\
			machdeps/alpha_regs.h	\
			machdeps/pa_regs.h	\
			machdeps/rs6000_regs.h

# MCPP_HDRS are header files in Microsoft's Managed extensions for C++

MCPP_HDRS	=	mercury_mcpp.h		

#		  keep this list in alphabetical order, please
CFILES		= 	\
			mercury.c		\
			mercury_accurate_gc.c	\
			mercury_agc_debug.c	\
			mercury_bootstrap.c	\
			mercury_context.c	\
			mercury_debug.c		\
			mercury_deep_copy.c	\
			mercury_dlist.c		\
			mercury_dummy.c		\
			mercury_engine.c	\
			mercury_file.c		\
			mercury_float.c		\
			mercury_getopt.c	\
			mercury_getopt1.c	\
			mercury_grade.c		\
			mercury_hash_table.c	\
			mercury_heap_profile.c	\
			mercury_ho_call.c	\
			mercury_label.c		\
			mercury_layout_util.c	\
			mercury_memory.c	\
			mercury_memory_zones.c	\
			mercury_memory_handlers.c	\
			mercury_misc.c		\
			mercury_prof.c		\
			mercury_prof_mem.c	\
			mercury_reg_workarounds.c	\
			mercury_regs.c		\
			mercury_signal.c	\
			mercury_stack_trace.c	\
			mercury_stacks.c	\
			mercury_string.c	\
			mercury_tabling.c	\
			mercury_thread.c	\
			mercury_timing.c	\
			mercury_trace_base.c	\
			mercury_trail.c 	\
			mercury_type_info.c	\
			mercury_type_tables.c	\
			mercury_wrapper.c

OBJS		= $(CFILES:.c=.$O)
PIC_OBJS	= $(CFILES:.c=.$(EXT_FOR_PIC_OBJECTS))

LDFLAGS		= -L$(BOEHM_GC_DIR)
LDLIBS		= \
		` case "$(GRADE)" in 					\
		    *.par*.gc*.prof*)	echo "-lpar_gc_prof" ;;		\
		    *.par*.gc*)		echo "-lpar_gc" ;;		\
		    *.gc*.prof*)	echo "-lgc_prof" ;;		\
		    *.gc*)		echo "-lgc" ;;			\
		  esac							\
		`
THREADLIBS	= \
		` case "$(GRADE)" in					\
		    *.par*) echo "-lpthread" ;;				\
		  esac							\
		`

HDR_CHECK_CS = $(HDRS:.h=_check.c)
HDR_CHECK_OBJS = $(HDRS:.h=_check.$O)
HDR_CHECK_MACROS = $(HDRS:.h=_check.macros)
OBJ_CHECKS = $(OBJS:%=%.obj_check)

#-----------------------------------------------------------------------------#

# Stuff for Windows DLLs

ifeq ($(USE_DLLS),yes)

DLL_CFLAGS	= -Dlib$(RT_LIB_NAME)_DEFINE_DLL

# the following header files are created automatically by Makefile.DLLs
LIB_DLL_H     = lib$(RT_LIB_NAME)_dll.h
LIB_GLOBALS_H = lib$(RT_LIB_NAME)_globals.h

include $(MERCURY_DIR)/Makefile.DLLs

else

DLL_CFLAGS =
LIB_DLL_H =
LIB_GLOBALS_H =
DLL_DEF_LIB =

endif

#-----------------------------------------------------------------------------#

$(OBJS) $(PIC_OBJS): $(HDRS) $(MACHHDRS)

mercury_deep_copy.o:	mercury_deep_copy_body.h
mercury_type_info.o:	mercury_make_type_info_body.h
mercury_ho_call.o:	mercury_unify_compare_body.h

#-----------------------------------------------------------------------------#

ifeq ($(findstring il,$(GRADE)),il)        

# Managed C++ files compiled in this directory should not be put in an
# assembly of their own.  We put the runtime and library dlls into a single
# assembly called `mercury'
MS_CL_NOASM=:noAssembly

# We need to build the following DLLs for the .NET runtime
DOTNET_DLLS=mercury_il.dll mercury_mcpp.dll
 
runtime: $(DOTNET_DLLS)

mercury_mcpp.dll: mercury_il.dll
 
else

.PHONY: runtime
runtime: lib$(RT_LIB_NAME).$A lib$(RT_LIB_NAME).$(EXT_FOR_SHARED_LIB)
runtime: $(RT_LIB_NAME).init
runtime: $(LIB_DLL_H) $(LIB_GLOBALS_H)

lib$(RT_LIB_NAME)$(DLL_DEF_LIB).$A: $(OBJS)
	rm -f lib$(RT_LIB_NAME)$(DLL_DEF_LIB).$A
	$(AR) $(ALL_ARFLAGS) \
		$(AR_LIBFILE_OPT)lib$(RT_LIB_NAME)$(DLL_DEF_LIB).$A $(OBJS)
	$(RANLIB) lib$(RT_LIB_NAME)$(DLL_DEF_LIB).$A

lib$(RT_LIB_NAME).so: $(PIC_OBJS)
	$(LINK_SHARED_OBJ) $(ERROR_UNDEFINED)				\
		-o lib$(RT_LIB_NAME).so $(PIC_OBJS)			\
		$(SHLIB_RPATH_OPT)$(FINAL_INSTALL_MERC_GC_LIB_DIR)	\
		$(LDFLAGS) $(LDLIBS) $(THREADLIBS)			\
		$(SHARED_LIBS)

endif

$(RT_LIB_NAME).init: $(CFILES)
	cat `vpath_find $(CFILES)` | grep '^INIT ' > $(RT_LIB_NAME).init

mercury_conf.h.date: $(MERCURY_DIR)/config.status mercury_conf.h.in
	CONFIG_FILES= CONFIG_HEADERS=mercury_conf.h $(MERCURY_DIR)/config.status
	echo datestamp > mercury_conf.h.date

mercury_conf.h: mercury_conf.h.date
	@true

.PHONY: cs
cs: $(CFILES)

tags: $(CFILES) $(HDRS) $(BODY_HDRS)
	ctags $(CFILES) $(HDRS) $(BODY_HDRS)

#-----------------------------------------------------------------------------#
#
# `mmake check_namespace' performs various checks on the header files
# and object files to make sure that they conform with our coding standards.
#

HEADER_CLEAN_FILTER = \
	grep -v -e '^MR_' -e '^GC_' -e '^MERCURY_' | \
	fgrep -v -x -f RESERVED_MACRO_NAMES

.PHONY: check_headers_self_contained
check_headers_self_contained: $(HDR_CHECK_OBJS)

.PHONY: check_headers_macros
check_headers_macros: $(HDR_CHECK_MACROS)

.PHONY: check_headers
check_headers: check_headers_self_contained check_headers_macros

.PHONY: check_objs
check_objs: $(OBJ_CHECKS)

.PHONY: check_namespace
check_namespace: check_headers check_objs

#-----------------------------------------------------------------------------#

# installation rules

.PHONY: install
install: install_headers install_init install_lib

.PHONY: install_dirs
install_dirs:
	-[ -d $(INSTALL_INC_DIR)/machdeps ] || \
		mkdir -p $(INSTALL_INC_DIR)/machdeps
	-[ -d $(INSTALL_MODULE_DIR) ] || mkdir -p $(INSTALL_MODULE_DIR)
	-[ -d $(INSTALL_MERC_LIB_DIR) ] || mkdir -p $(INSTALL_MERC_LIB_DIR)

ifeq ($(findstring il,$(GRADE)),il)        

.PHONY: install_headers 
install_headers: $(MCPP_HDRS) install_dirs
	cp `vpath_find $(MCPP_HDRS)` $(INSTALL_INC_DIR)

.PHONY: install_init
install_init: 

.PHONY: install_lib 
install_lib: $(DOTNET_DLLS) install_dirs
	cp `vpath_find $(DOTNET_DLLS)` $(INSTALL_MERC_LIB_DIR)

else

.PHONY: install_headers
install_headers: $(HDRS) $(BODY_HDRS) $(MACHHDRS) $(LIB_GLOBALS_H) install_dirs
	cp `vpath_find $(HDRS) $(BODY_HDRS) $(LIB_GLOBALS_H)` $(INSTALL_INC_DIR)
	-chmod u+w $(INSTALL_INC_DIR)/mercury_conf.h
	cp `vpath_find $(MACHHDRS)` $(INSTALL_INC_DIR)/machdeps

.PHONY: install_init
install_init: $(RT_LIB_NAME).init install_dirs
	cp `vpath_find $(RT_LIB_NAME).init` $(INSTALL_MODULE_DIR)
	# "$(RT_LIB_NAME).init" used to be called "runtime.init".
	# If there is still a version with an old name lying around,
	# then delete it; otherwise the initialization would get done twice.
	rm -f $(INSTALL_MODULE_DIR)/runtime.init

.PHONY: install_lib install_dirs
install_lib: lib$(RT_LIB_NAME).$A lib$(RT_LIB_NAME).$(EXT_FOR_SHARED_LIB) \
		install_dirs
	cp `vpath_find lib$(RT_LIB_NAME).$A \
		lib$(RT_LIB_NAME).$(EXT_FOR_SHARED_LIB)` \
		$(INSTALL_MERC_LIB_DIR)

endif


#-----------------------------------------------------------------------------#

# prevent Mmake from removing C files
RM_C=:

#-----------------------------------------------------------------------------#

clean_local: clean_o clean_check

.PHONY: clean_o
clean_o:
	rm -f $(OBJS) $(PIC_OBJS)

.PHONY: clean_check
clean_check:
	rm -f $(HDR_CHECK_OBJS) $(HDR_CHECK_CS) $(HDR_CHECK_MACROS)
	rm -f $(OBJ_CHECKS)

.PHONY: realclean_local
realclean_local:
	rm -f lib$(RT_LIB_NAME).$A lib$(RT_LIB_NAME).so $(RT_LIB_NAME).init
	rm -f mercury_conf.h mercury_conf.h.date

#-----------------------------------------------------------------------------#
