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

# This is the Mmakefile for building the Mercury deep profiler.

MERCURY_DIR=..
LINK_STATIC=yes
include $(MERCURY_DIR)/Mmake.common

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

# Override some settings from ../Mmake.workspace so that in debugging grades
# we do not include mer_mdbcomp.init when creating the _init.c files in
# this directory. We copy the mdbcomp modules into this directory so if we
# do include mer_mdbcomp.init we will end up with duplicate entries in the
# _init.c files.

C2INITFLAGS = --trace-init-file $(BROWSER_DIR)/$(BROWSER_LIB_NAME).init

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

-include Mmake.deep.params

# Override the default rule in `mmake --use-mmc-make' that asks `mmc' to
# create a missing optional params file.
Mmake.deep.params:

# Module-specific options should go in Mercury.options so they
# can be found by `mmc --make'.
include Mercury.options

MAIN_TARGET = all

ALL_DEEP_MODULES = \
	mdprof_cgi \
	mdprof_test \
	mdprof_dump \
	mdprof_create_feedback \
	mdprof_report_feedback \
	mdprof_procrep

# Always compile the deep profiler, even if it is not enabled.
# 
MAIN_TARGET=all
MERCURY_MAIN_MODULES=$(ALL_DEEP_MODULES)
DEPEND=$(patsubst %,%.depend,$(ALL_DEEP_MODULES))
PDBS=$(patsubst %,%.pdb,$(ALL_DEEP_MODULES))

ifeq ("$(ENABLE_DEEP_PROFILER)","yes")
	INSTALL=install_cgi_progs
else
	INSTALL=nothing
endif

VPATH = $(LIBRARY_DIR) $(SSDB_DIR)

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

MDBCOMP_MODULES = \
	feedback.automatic_parallelism.m \
	feedback.m \
	mdbcomp.m \
	mdbcomp.goal_path.m \
	prim_data.m \
	program_representation.m \
	rtti_access.m \
	shared_utilities.m \
	slice_and_dice.m \
	trace_counts.m

MDBCOMP_ORIG_MODULES = $(patsubst %,$(MDBCOMP_DIR)/%,$(MDBCOMP_MODULES))

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

MLFLAGS += --shared
MCFLAGS += --flags DEEP_FLAGS $(CONFIG_OVERRIDE)

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

# Tell the C# compiler where the stdlib assembly is.
#
ifneq ("$(filter csharp%,$(GRADE))","")
CSCFLAGS=-lib:../library -r:mer_std.dll
endif

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

ifneq ("$(filter il% csharp% java% erlang%,$(GRADE))","")
MLOBJS =
endif

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

# The deep profiler contains quite a lot of C code for which there are
# currently not C#, IL, Java or Erlang implementations.  We need to pass
# `--allow-stubs' in order to compile it.
#
ifneq ("$(filter il% csharp% java% erlang%,$(GRADE))","")
MCFLAGS += --allow-stubs --no-warn-stubs
endif

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

.PHONY: nothing
nothing:

.PHONY: depend
depend:	$(MDBCOMP_MODULES) $(DEPEND)

$(DEPEND): DEEP_FLAGS $(MDBCOMP_MODULES) Mercury.modules

# This directory contains source files for which the module
# name doesn't match the file name, so smart recompilation
# won't work without the Mercury.modules file.
.PHONY: Mercury.modules
Mercury.modules: DEEP_FLAGS
	$(MC) $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) -f *.m

.PHONY: all
all:	$(MDBCOMP_MODULES) $(ALL_DEEP_MODULES) $(TAGS_FILE_EXISTS)

# We use the sentinel file .mdbcomp_modules to avoid the race condition that
# exists because the rule would normally be invoked for each of the mdbcomp
# modules.  Note that a .PHONY target does not work.  However, we also need
# to use the no-op action '@' to allow make to see that the timestamps on
# the $(MDBCOMP_MODULES) have changed and that other things may need
# rebuilding.
$(MDBCOMP_MODULES): .mdbcomp_modules
	@

# We need to start by turning write permission on for each copied file
# in case some exist, but we need to ignore errors in case some don't exist.
# The exit 0 is to prevent make itself from printing a message about the
# (ignored) failure of an action.
#
# We could modify the action here to copy only the changed files.
.mdbcomp_modules : $(MDBCOMP_ORIG_MODULES)
	-@chmod a+w $(MDBCOMP_MODULES) > /dev/null 2>&1; exit 0
	cp $(MDBCOMP_ORIG_MODULES) .
	@chmod a-w $(MDBCOMP_MODULES)
	touch $@

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

# Add some additional dependencies, so that Mmake knows to remake the
# profiler if one of the libraries changes.

ifeq ("$(filter il% csharp% java% erlang%,$(GRADE))","")
mdprof_cgi:		$(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
mdprof_cgi:		$(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
mdprof_test:		$(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
mdprof_test:		$(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
mdprof_dump:		$(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
mdprof_dump:		$(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
mdprof_create_feedback:	$(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
mdprof_create_feedback:	$(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
mdprof_report_feedback:	$(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
mdprof_report_feedback:	$(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
mdprof_procrep:		$(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
mdprof_procrep:		$(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
# XXX Should also depend on $(BOEHM_GC_DIR)/libgc(_prof).$A, but only
# if in .gc(.prof) grade.
endif

$(cs_subdir)mdprof_cgi_init.c:			$(UTIL_DIR)/mkinit$(EXT_FOR_EXE)
$(cs_subdir)mdprof_test_init.c:			$(UTIL_DIR)/mkinit$(EXT_FOR_EXE)
$(cs_subdir)mdprof_dump_init.c:			$(UTIL_DIR)/mkinit$(EXT_FOR_EXE)
$(cs_subdir)mdprof_create_feedback_init.c: 	$(UTIL_DIR)/mkinit$(EXT_FOR_EXE)
$(cs_subdir)mdprof_report_feedback_init.c: 	$(UTIL_DIR)/mkinit$(EXT_FOR_EXE)
$(cs_subdir)mdprof_procrep_init.c:		$(UTIL_DIR)/mkinit$(EXT_FOR_EXE)

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

.PHONY: check
check:	DEPEND=$(patsubst %,%.check,$(ALL_DEEP_MODULES))

.PHONY: ints 
ints:	DEPEND=$(patsubst %,%.ints,$(ALL_DEEP_MODULES))

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

# We need the shenanigans with .deep_tags to avoid situations in which an
# "mmake tags" in this directory does nothing even in the absence of a tags
# file in this directory, because mmake uses VPATH to find ../library/tags
# and believes it to be the tags file we are asking for.

.PHONY: tags
tags:	.deep_tags

DEEP_MS = \
	$(mdprof_cgi.ms) \
	$(mdprof_test.ms) \
	$(mdprof_dump.ms) \
	$(mdprof_create_feedback.ms) \
	$(mdprof_report_feedback.ms) \
	$(mdprof_procrep.ms)

.deep_tags: $(MTAGS) $(DEEP_MS) \
		$(wildcard $(MDBCOMP_DIR)/*.m) \
		$(wildcard $(LIBRARY_DIR)/*.m)
	$(MTAGS) $(DEEP_MS) $(MDBCOMP_DIR)/*.m $(LIBRARY_DIR)/*.m
	@touch .deep_tags

.PHONY: tags_file_exists
tags_file_exists:
	@if test ! -f tags; then echo making tags; \
	$(MTAGS) $(DEEP_MS) $(MDBCOMP_DIR)/*.m $(LIBRARY_DIR)/*.m; \
	touch .deep_tags; \
	fi

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

.PHONY: dates
dates:
	touch 	$(mdprof_cgi.dates) \
		$(mdprof_test.dates) \
		$(mdprof_dump.dates) \
		$(mdprof_create_feedback.dates) \
		$(mdprof_report_feedback.dates) \
		$(mdprof_procrep.dates)

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

.PHONY: os cs
os: $(mdprof_cgi.os) $(os_subdir)mdprof_cgi_init.o
os: $(mdprof_test.os) $(os_subdir)mdprof_test_init.o
os: $(mdprof_dump.os) $(os_subdir)mdprof_dump_init.o
os: $(mdprof_create_feedback.os) $(os_subdir)mdprof_create_feedback_init.o
os: $(mdprof_report_feedback.os) $(os_subdir)mdprof_report_feedback_init.o
os: $(mdprof_procrep.os) $(os_subdir)mdprof_procrep_init.o
cs: $(mdprof_cgi.cs) $(cs_subdir)mdprof_cgi_init.c
cs: $(mdprof_test.cs) $(cs_subdir)mdprof_test_init.c
cs: $(mdprof_dump.cs) $(cs_subdir)mdprof_dump_init.c
cs: $(mdprof_create_feedback.cs) $(cs_subdir)mdprof_create_feedback_init.c
cs: $(mdprof_report_feedback.cs) $(cs_subdir)mdprof_report_feedback_init.c
cs: $(mdprof_procrep.cs) $(cs_subdir)mdprof_procrep_init.c

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

realclean_local:
	rm -f .deep_tags tags DEEP_FLAGS DEEP_FLAGS.date \
		.mdbcomp_modules $(MDBCOMP_MODULES) mdbcomp.*.err
	rm -f $(PDBS) vc*.pdb

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

# Installation targets

.PHONY: install
install: $(INSTALL)

# We don't install mdprof_test, since it is not for users.

# The code of the install_cgi_progs target is duplicated in
# bindist/bindist.Makefile.in, though the two rules refer to mdprof_cgi
# by different paths.

.PHONY: install_cgi_progs
install_cgi_progs: mdprof_cgi mdprof_dump mdprof_test \
	mdprof_create_feedback mdprof_report_feedback
	# $(INSTALL_CGI_DIR) is likely to be writeable only by root or
	# the www system administrator, which is why we don't consider a
	# failure of this action to be an error. If the command fails,
	# the install action in ../Mmakefile will remind the user to do
	# the copy later.
	#
	# The mv before the cp is there in case the executable is being
	# executed when we do the install. The mv is of course expected to
	# fail during a first-time installation. The rm is before the move
	# in case this is the third or later installation.
	-if test $(ENABLE_DEEP_PROFILER) = yes ; then \
		if test -w $(INSTALL_CGI_DIR) ; then \
			rm -f $(INSTALL_CGI_DIR)/mdprof_cgi.was ; \
			mv -f $(INSTALL_CGI_DIR)/mdprof_cgi \
				$(INSTALL_CGI_DIR)/mdprof_cgi.was ; \
			cp mdprof_cgi $(INSTALL_CGI_DIR) ; \
		else \
			echo "cannot install mdprof_cgi: " \
				"$(INSTALL_CGI_DIR) is not writeable"; \
		fi \
	fi
	# We also install mdprof_cgi in $(INSTALL_MERC_BIN_DIR).
	# This is done just so that it can easily get put in the binary
	# distribution (even if the step above failed). It is useful for
	# mdprof_test and mdprof_dump to be available when debugging problems
	# with the deep profiler, so we install them as well.
	-[ -d $(INSTALL_MERC_BIN_DIR) ] || mkdir -p $(INSTALL_MERC_BIN_DIR)
	cp `vpath_find mdprof_cgi$(EXT_FOR_EXE)` \
		$(INSTALL_MERC_BIN_DIR)/mdprof_cgi
	cp `vpath_find mdprof_test$(EXT_FOR_EXE)` \
		$(INSTALL_MERC_BIN_DIR)/mdprof_test
	cp `vpath_find mdprof_dump$(EXT_FOR_EXE)` \
		$(INSTALL_MERC_BIN_DIR)/mdprof_dump
	cp `vpath_find mdprof_create_feedback$(EXT_FOR_EXE)` \
		$(INSTALL_MERC_BIN_DIR)/mdprof_create_feedback
	cp `vpath_find mdprof_report_feedback$(EXT_FOR_EXE)` \
		$(INSTALL_MERC_BIN_DIR)/mdprof_report_feedback

uninstall:
	# We try to uninstall mdprof_cgi, but failure to do so is not an
	# error for two reasons: because we may simply lack permission to
	# update the directory, and because the deep profiler installation
	# may not have been enabled in the first place. (Looking at the current
	# value of $(ENABLE_DEEP_PROFILER) to check for the latter wouldn't
	# necessarily do any good, since its setting may have changed since
	# the original install.)
	-rm -f $(INSTALL_CGI_DIR)/mdprof_cgi

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