#-----------------------------------------------------------------------------#
# vim: ts=8 sw=8 noexpandtab ft=make
#-----------------------------------------------------------------------------#
# Copyright (C) 1995-2012 The University of Melbourne.
# Copyright (C) 2013, 2015-2025 The Mercury team.
# This file may only be copied under the terms of the GNU General
# Public Licence - see the file COPYING in the Mercury distribution.
#-----------------------------------------------------------------------------#

# Mmakefile - the top-level Mmake file for the Mercury implementation

# We need to explicitly include scripts/Mmake.vars here, even though `mmake'
# includes that file automatically, to make sure that we get the right
# version of that file. The settings in that file include values set
# by parameters to configure (e.g. --prefix), and we need to make sure
# that we pick up the values from the Mmake.vars that we are going to install,
# rather than from the old version of mmake that we are installing with,
# which may have been configured with a different --prefix.
include scripts/Mmake.vars

MAIN_TARGET=all

MERCURY_DIR=.
include Mmake.common

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

# NOTE: if you add another subdirectory here, then you may need to also update
# scripts/prepare_tmp_dir.in and the `tar' target below.
# If the directory you are adding will contain C files generated by the
# Mercury compiler when included in the source distribution, then you will
# also need to update the code in configure.ac that deletes those C files
# before reinstalling the compiler in a more efficient grade.

SUBDIRS = \
	scripts \
	util \
	boehm_gc \
	runtime \
	robdd \
	library \
	trace \
	ssdb \
	mdbcomp \
	browser \
	grade_lib \
	compiler \
	doc \
	slice \
	profiler \
	deep_profiler \
	tools \
	mfilterjavac

MMAKEFLAGS =

ifneq ($(CROSS_COMPILING),yes)
	# We include ../../mfilterjavac in this path because $(SUBDIR_MMAKE) is
	# used from the grade install directories, and we need mfilterjavac in
	# our path when executing in install_grade_dir.java/library and others.
	SUBDIR_MMAKE_PATH=../scripts:../util:../mfilterjavac:../../mfilterjavac:$$PATH
	SUBSUBDIR_MMAKE_PATH=../../scripts:../../util:../../mfilterjavac:$$PATH
else
	# When cross-compiling, exclude util and mfilterjavac from the PATH,
	# so mmake does not try to execute binaries from those directories.
	SUBDIR_MMAKE_PATH=../scripts:$$PATH
	SUBSUBDIR_MMAKE_PATH=../../scripts:$$PATH
endif

SUBDIR_MMAKE = \
	PATH=$(SUBDIR_MMAKE_PATH) \
	MMAKE_VPATH=. \
	MMAKE_DIR=../scripts \
	DESTDIR=$(DESTDIR) \
	../scripts/mmake $(MMAKEFLAGS)

SUBSUBDIR_MMAKE = \
	PATH=$(SUBSUBDIR_MMAKE_PATH) \
	MMAKE_VPATH=. \
	MMAKE_DIR=../../scripts \
	DESTDIR=$(DESTDIR) \
	../../scripts/mmake $(MMAKEFLAGS)

GENERATED_DOCS = README INSTALL WORK_IN_PROGRESS TODO

# If you change these, you will also need to change the files indicated
# in scripts/c2init.in.
RT_LIB_NAME = mer_rt
STD_LIB_NAME = mer_std
TRACE_LIB_NAME = mer_trace
EVENTSPEC_LIB_NAME = mer_eventspec
SSDB_LIB_NAME = mer_ssdb
MDBCOMP_LIB_NAME = mer_mdbcomp
BROWSER_LIB_NAME = mer_browser

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

# `mmake dep' ensures that the .dep files exist;
# `mmake depend' forces them to be remade to ensure that they are up-to-date.

.PHONY: dep
dep:	dep_library \
	dep_ssdb \
	dep_mdbcomp \
	dep_browser \
	dep_grade_lib \
	dep_compiler \
	dep_slice \
	dep_profiler \
	dep_deep_profiler \
	dep_mfilterjavac

.PHONY: dep_library
dep_library: library/$(deps_subdir)$(STD_LIB_NAME).dep

library/$(deps_subdir)$(STD_LIB_NAME).dep:
	+cd library && $(SUBDIR_MMAKE) depend

.PHONY: dep_mdbcomp
dep_mdbcomp: \
	mdbcomp/$(deps_subdir)$(MDBCOMP_LIB_NAME).dep

mdbcomp/$(deps_subdir)$(MDBCOMP_LIB_NAME).dep:
	+cd mdbcomp && $(SUBDIR_MMAKE) $(MDBCOMP_LIB_NAME).depend

.PHONY: dep_browser
dep_browser: \
	browser/$(deps_subdir)$(BROWSER_LIB_NAME).dep

.PHONY: dep_browser_aux
dep_browser_aux: \
	browser/$(deps_subdir)browse_test.dep \
	browser/$(deps_subdir)declarative_test.dep

.PHONY: dep_browser_all
dep_browser_all: \
	browser/$(deps_subdir)$(BROWSER_LIB_NAME).dep \
	browser/$(deps_subdir)browse_test.dep \
	browser/$(deps_subdir)declarative_test.dep

browser/$(deps_subdir)$(BROWSER_LIB_NAME).dep:
	+cd browser && $(SUBDIR_MMAKE) $(BROWSER_LIB_NAME).depend

browser/$(deps_subdir)browse_test.dep:
	+cd browser && $(SUBDIR_MMAKE) browse_test.depend

browser/$(deps_subdir)declarative_test.dep:
	+cd browser && $(SUBDIR_MMAKE) declarative_test.depend

.PHONY: dep_ssdb
dep_ssdb: \
	ssdb/$(deps_subdir)$(SSDB_LIB_NAME).dep

ssdb/$(deps_subdir)$(SSDB_LIB_NAME).dep:
	+cd ssdb && $(SUBDIR_MMAKE) $(SSDB_LIB_NAME).depend

.PHONY: dep_compiler
dep_compiler: compiler/$(deps_subdir)mercury_compile.dep

compiler/$(deps_subdir)mercury_compile.dep: library/$(deps_subdir)$(STD_LIB_NAME).dep
	+cd compiler && $(SUBDIR_MMAKE) depend

.PHONY: dep_grade_lib
dep_grade_lib: grade_lib/$(deps_subdir)/choose_grade.dep \
	grade_lib/$(deps_subdir)/test_grades.dep \
	grade_lib/$(deps_subdir)/try_all_grade_structs.dep

grade_lib/$(deps_subdir)/choose_grade.dep \
grade_lib/$(deps_subdir)/test_grades.dep \
grade_lib/$(deps_subdir)/try_all_grade_structs.dep:
	+cd grade_lib && $(SUBDIR_MMAKE) depend

.PHONY: dep_slice
dep_slice: slice/$(deps_subdir)mcov.dep \
	slice/$(deps_subdir)mslice.dep \
	slice/$(deps_subdir)mdice.dep \
	slice/$(deps_subdir)mtc_union.dep \
	slice/$(deps_subdir)mtc_diff.dep

slice/$(deps_subdir)mslice.dep \
slice/$(deps_subdir)mdice.dep \
slice/$(deps_subdir)mcov.dep \
slice/$(deps_subdir)mtc_union.dep \
slice/$(deps_subdir)mtc_diff.dep:
	+cd slice && $(SUBDIR_MMAKE) depend

.PHONY: dep_profiler
dep_profiler: profiler/$(deps_subdir)mercury_profile.dep

profiler/$(deps_subdir)mercury_profile.dep: \
		library/$(deps_subdir)$(STD_LIB_NAME).dep
	+cd profiler && $(SUBDIR_MMAKE) depend

.PHONY: dep_profiler_aux
dep_profiler_aux: profiler/$(deps_subdir)/demangle_test.dep

profiler/$(deps_subdir)/demangle_test.dep: \
		library/$(deps_subdir)$(STD_LIB_NAME).dep
	+cd profiler && $(SUBDIR_MMAKE) depend_aux

.PHONY: dep_deep_profiler
dep_deep_profiler: deep_profiler/$(deps_subdir)mdprof_cgi.dep \
		deep_profiler/$(deps_subdir)mdprof_test.dep \
		deep_profiler/$(deps_subdir)mdprof_dump.dep \
		deep_profiler/$(deps_subdir)mdprof_create_feedback.dep \
		deep_profiler/$(deps_subdir)mdprof_report_feedback.dep \
		deep_profiler/$(deps_subdir)mdprof_procrep.dep

deep_profiler/$(deps_subdir)mdprof_cgi.dep \
deep_profiler/$(deps_subdir)mdprof_test.dep \
deep_profiler/$(deps_subdir)mdprof_dump.dep \
deep_profiler/$(deps_subdir)mdprof_create_feedback.dep \
deep_profiler/$(deps_subdir)mdprof_report_feedback.dep \
deep_profiler/$(deps_subdir)mdprof_procrep.dep: \
		library/$(deps_subdir)$(STD_LIB_NAME).dep
	+cd deep_profiler && $(SUBDIR_MMAKE) depend

.PHONY: dep_mfilterjavac
dep_mfilterjavac: mfilterjavac/$(deps_subdir)mfilterjavac.dep

mfilterjavac/$(deps_subdir)mfilterjavac.dep: \
		library/$(deps_subdir)$(STD_LIB_NAME).dep
	+cd mfilterjavac && $(SUBDIR_MMAKE) depend

# depend_library MUST be done before depend_compiler and depend_profiler

.PHONY: depend
depend: \
	depend_library \
	depend_mdbcomp \
	depend_browser \
	depend_ssdb \
	depend_grade_lib \
	depend_compiler \
	depend_slice \
	depend_profiler \
	depend_deep_profiler \
	depend_mfilterjavac

.PHONY: depend_library
depend_library:
	+cd library && $(SUBDIR_MMAKE) depend

.PHONY: depend_mdbcomp
depend_mdbcomp:
	+cd mdbcomp && $(SUBDIR_MMAKE) depend

.PHONY: depend_browser
depend_browser:
	+cd browser && $(SUBDIR_MMAKE) depend

.PHONY: depend_ssdb
depend_ssdb:
	+cd ssdb && $(SUBDIR_MMAKE) depend

.PHONY: depend_grade_lib
depend_grade_lib:
	+cd grade_lib && $(SUBDIR_MMAKE) depend

.PHONY: depend_compiler
depend_compiler:
	+cd compiler && $(SUBDIR_MMAKE) depend

.PHONY: depend_slice
depend_slice:
	+cd slice && $(SUBDIR_MMAKE) depend

.PHONY: depend_profiler
depend_profiler:
	+cd profiler && $(SUBDIR_MMAKE) depend

.PHONY: depend_deep_profiler
depend_deep_profiler:
	+cd deep_profiler && $(SUBDIR_MMAKE) depend

.PHONY: depend_mfilterjavac
depend_mfilterjavac:
	+cd mfilterjavac && $(SUBDIR_MMAKE) depend

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

# NOTE: there are two targets that concern the util directory here. The first
# is the "util_no_rt" target (short for "util no runtime") and the second is the
# "util" target. The first target builds those programs in the util directory
# that do *not* depend on the runtime directory, at present just mfiltercc.
# The second target builds the rest. Things are arranged in this fashion
# so that when building the source distribution, we can build mfiltercc before
# it is required.

.PHONY: all
all: 	$(GENERATED_DOCS) util_no_rt $(SUBDIRS)

.PHONY: util_no_rt
util_no_rt: scripts
	+cd util && $(SUBDIR_MMAKE) mfiltercc$(EXT_FOR_EXE)

.PHONY: util
util:	scripts runtime
	+cd util && $(SUBDIR_MMAKE)

.PHONY: scripts
scripts:
	+cd scripts && $(SUBDIR_MMAKE)

.PHONY: boehm_gc
boehm_gc: scripts util_no_rt
	+gc_grade=`scripts/ml --grade $(GRADE) --print-gc-grade`; \
	cd boehm_gc && $(SUBDIR_MMAKE) GC_GRADE=$$gc_grade

.PHONY: runtime
runtime: scripts util_no_rt boehm_gc
	+cd runtime && $(SUBDIR_MMAKE)

.PHONY: robdd
robdd: 	scripts boehm_gc runtime
	cd robdd && $(SUBDIR_MMAKE)

.PHONY: library
library: dep_library scripts util boehm_gc runtime
	+cd library && $(SUBDIR_MMAKE)

.PHONY: mdbcomp
mdbcomp: dep_mdbcomp scripts util boehm_gc runtime library
	+cd mdbcomp && $(SUBDIR_MMAKE)

.PHONY: browser
browser: dep_browser scripts util boehm_gc runtime library mdbcomp
	+cd browser && $(SUBDIR_MMAKE)

.PHONY: ssdb
ssdb: dep_ssdb scripts boehm_gc runtime library mdbcomp browser
	+cd ssdb && $(SUBDIR_MMAKE)

.PHONY: runtime
trace: scripts boehm_gc runtime library mdbcomp browser
	+cd trace && $(SUBDIR_MMAKE)

.PHONY: grade_lib
grade_lib: dep_grade_lib scripts util boehm_gc runtime library \
		mdbcomp browser ssdb trace
	+cd grade_lib && $(SUBDIR_MMAKE)

.PHONY: compiler
compiler: dep_compiler scripts util boehm_gc runtime library \
		mdbcomp browser ssdb trace
	+cd compiler && $(SUBDIR_MMAKE)

.PHONY: doc
doc: scripts util compiler profiler
	+cd doc && $(SUBDIR_MMAKE)

.PHONY: slice
slice: 	dep_slice scripts util boehm_gc runtime library \
		mdbcomp browser ssdb trace
	+cd slice && $(SUBDIR_MMAKE)

.PHONY: profiler
profiler: dep_profiler scripts util boehm_gc runtime library \
		mdbcomp browser ssdb trace
	+cd profiler && $(SUBDIR_MMAKE)

.PHONY: deep_profiler
deep_profiler: dep_deep_profiler scripts util boehm_gc runtime library \
		mdbcomp browser ssdb trace
	+cd deep_profiler && $(SUBDIR_MMAKE)

.PHONY: mfilterjavac
mfilterjavac: dep_mfilterjavac scripts util boehm_gc runtime library \
		mdbcomp browser ssdb trace
	+cd mfilterjavac && $(SUBDIR_MMAKE)

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

.PHONY: tags
tags: 	\
	tags_library \
	tags_mdbcomp \
	tags_browser \
	tags_ssdb \
	tags_grade_lib \
	tags_compiler \
	tags_slice \
	tags_profiler \
	tags_deep_profiler \
	tags_runtime \
	tags_trace \
	tags_mfilterjavac

.PHONY: tags_compiler
tags_compiler:
	+cd compiler && $(SUBDIR_MMAKE) tags

.PHONY: tags_library
tags_library:
	+cd library && $(SUBDIR_MMAKE) tags

.PHONY: tags_mdbcomp
tags_mdbcomp:
	+cd mdbcomp && $(SUBDIR_MMAKE) tags

.PHONY: tags_browser
tags_browser:
	+cd browser && $(SUBDIR_MMAKE) tags

.PHONY: tags_ssdb
tags_ssdb:
	+cd ssdb && $(SUBDIR_MMAKE) tags

.PHONY: tags_grade_lib
tags_grade_lib:
	+cd grade_lib && $(SUBDIR_MMAKE) tags

.PHONY: tags_slice
tags_slice:
	+cd slice && $(SUBDIR_MMAKE) tags

.PHONY: tags_profiler
tags_profiler:
	+cd profiler && $(SUBDIR_MMAKE) tags

.PHONY: tags_deep_profiler
tags_deep_profiler:
	+cd deep_profiler && $(SUBDIR_MMAKE) tags

.PHONY: tags_runtime
tags_runtime:
	+cd runtime && $(SUBDIR_MMAKE) tags

.PHONY: tags_trace
tags_trace:
	+cd trace && $(SUBDIR_MMAKE) tags

.PHONY: tags_mfilterjavac
tags_mfilterjavac:
	+cd mfilterjavac && $(SUBDIR_MMAKE) tags

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

# Remove from each of the listed directories mmc-generated files that
# do not belong there.
cleanint:
	for dir in library mdbcomp browser ssdb grade_lib compiler \
		slice profiler deep_profiler; \
	do \
		echo Looking for inappropriate files in the $$dir directory: ; \
		( cd $$dir && ../tools/cleanint > .cleanint ) ; \
		if test -s $$dir/.cleanint ; then \
			cat $$dir/.cleanint ; \
		else \
			echo none found. ; \
		fi \
	done

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

aclocal.m4: configure.ac $(wildcard m4/*.m4)
	aclocal -I m4

configure: configure.ac aclocal.m4
	autoconf

config.status: configure VERSION
	if test -f ./config.status; then \
		./config.status --recheck; \
	else \
		echo "======> You need to run configure!"; \
		exit 1; \
	fi

Mmake.common: Mmake.common.in config.status
	./config.status --file Mmake.common

README: .README.in VERSION
	sed 's/@VERSION@/$(VERSION)/g' .README.in > README

INSTALL: .INSTALL.in VERSION
	sed 's/@VERSION@/$(VERSION)/g' .INSTALL.in > INSTALL
	chmod a+x INSTALL

ifeq ("$(LYNX)","")
HTML_TO_TEXT = cat
else
HTML_TO_TEXT = TERM=vt100 lynx -dump
endif

WORK_IN_PROGRESS: compiler/notes/work_in_progress.html
	$(HTML_TO_TEXT) compiler/notes/work_in_progress.html > WORK_IN_PROGRESS

TODO: compiler/notes/todo.html
	$(HTML_TO_TEXT) compiler/notes/todo.html > TODO

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

# Generally you should do a `mmake realclean' before doing `mmake tar'.

TAR = tar

.PHONY: tar
tar: 	$(GENERATED_DOCS)
	touch Mmake.params
	cd util && mmake
	+cd runtime && $(SUBDIR_MMAKE) all_cs $(RT_LIB_NAME).init
	+cd library && $(SUBDIR_MMAKE) depend
	+cd library && $(SUBDIR_MMAKE) all-ints all_cs $(STD_LIB_NAME).init tags
	+cd mdbcomp && $(SUBDIR_MMAKE) depend
	+cd mdbcomp && $(SUBDIR_MMAKE) all-ints all_cs \
		$(MDBCOMP_LIB_NAME).init tags
	+cd browser && $(SUBDIR_MMAKE) depend
	+cd browser && $(SUBDIR_MMAKE) all-ints all_cs \
		$(BROWSER_LIB_NAME).init tags
	+cd ssdb && $(SUBDIR_MMAKE) depend
	+cd ssdb && $(SUBDIR_MMAKE) all-ints all_cs \
		$(SSDB_LIB_NAME).init tags
	+cd trace && $(SUBDIR_MMAKE) all_cs
	+cd compiler && $(SUBDIR_MMAKE) depend
	+cd compiler && $(SUBDIR_MMAKE) all_cs tags
	+cd slice && $(SUBDIR_MMAKE) depend
	+cd slice && $(SUBDIR_MMAKE) all_cs tags
	+cd profiler && $(SUBDIR_MMAKE) depend
	+cd profiler && $(SUBDIR_MMAKE) all_cs tags
	+cd deep_profiler && $(SUBDIR_MMAKE) depend
	+cd deep_profiler && $(SUBDIR_MMAKE) all_cs tags
	+cd mfilterjavac && $(SUBDIR_MMAKE) depend
	+cd mfilterjavac && $(SUBDIR_MMAKE) all_cs tags
	+cd grade_lib && $(SUBDIR_MMAKE) depend
	+cd grade_lib && $(SUBDIR_MMAKE) all_cs tags
	+cd doc && $(SUBDIR_MMAKE) info html dvi mdb_doc BUILD_SRCDIST=yes
	# the following commands might fail on Windows?
	-cd bindist && $(SUBDIR_MMAKE) bindist.Makefile
	-cd bindist && $(SUBDIR_MMAKE) bindist.INSTALL
	+cd extras/dynamic_linking && $(SUBSUBDIR_MMAKE) sources
	# clean up
	cd scripts && mmake realclean
	cd scripts && mmake canonical_grade
	cd util && mmake realclean
	cd doc && mmake distclean
	-rm -f errs errs2 update.log
	-rm -f config.status config.cache config.log configure.log a.out
	-rm -f scripts/config.log
	-rm -f runtime/mercury_conf.h boehm_gc/mercury_boehm_gc_conf.h
	-rm -f Mmake.common
	-rm -f extras/Mmake.params
	-rm -rf autom4te.cache
	-rm -rf bytecode
	-rm -rf extras/quickcheck
	-rm -rf .git
	-rm -f .gitignore
	-rm -f boehm_gc/.git boehm_gc/.gitignore boehm_gc/.gitattributes
	-rm -f boehm_gc/.gitmodules
	-rm -f boehm_gc/libatomic_ops/.git
	-rm -f boehm_gc/libatomic_ops/.gitignore
	-rm -f boehm_gc/libatomic_ops/.gitattributes
	chmod -R a+r *
	# Our invoker should have passed to us in ${SRCDIST_NAME}
	# the name of the current directory in its parent directory.
	# This name should have the form mercury-srcdist-$(VERSION),
	# which matters, because it will also be the name of the directory
	# that the tar file we are creating here will unpack into.
	#
	# Our invoker should also have put into ${TAR_FILE_NAME}
	# the pathname of the .tar file we are creating.
	# This should be an absolute pathname, and it must be
	# outside the directory we are packing up.
	cd .. && (							\
		$(TAR) --dereference 					\
			-cf ${TAR_FILE_NAME} ${SRCDIST_NAME} 		\
	)

.PHONY: version
version:
	@echo $(VERSION)

.PHONY: fullarch
fullarch:
	@echo $(FULLARCH)

.PHONY: echo_libgrades
echo_libgrades:
	@echo $(LIBGRADES)

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

# The code of the install rule is duplicated in bindist/bindist.Makefile.in.

.PHONY: install
install: install_main install_grades
	@echo
	@echo "-- Installation complete."
	@echo
	@if test -n "$(DESTDIR)"; then \
		echo "-- The installation was placed in $(DESTDIR)."; \
		echo "-- to complete installation copy the contents of"; \
		echo "-- $(DESTDIR) to the root directory of your system(s)."; \
		echo; \
	fi
	@echo "-- Don't forget to add $(FINAL_INSTALL_BINDIR) to your PATH,"
	@echo "-- $(FINAL_INSTALL_MAN_DIR) to your MANPATH,"
	@echo "-- and $(FINAL_INSTALL_INFO_DIR) to your INFOPATH,"
	@if test $(ENABLE_DEEP_PROFILER) != yes || \
		cmp -s deep_profiler/mdprof_cgi \
			$(INSTALL_CGI_DIR)/mdprof_cgi; \
	then true ; else \
		echo "-- to copy deep_profiler/mdprof_cgi" \
			"to $(FINAL_INSTALL_CGI_DIR),"; \
	fi
	@echo "-- and to add the following lines to the \`.emacs' file"
	@echo "-- in your home directory:"
	@echo "	(add-to-list 'load-path "
	@echo "		\"$(FINAL_INSTALL_ELISP_DIR)\")"
	@echo "	(autoload 'mdb \"gud\" \"Invoke the Mercury debugger\" t)"

.PHONY: install_main
install_main: all \
	install_scripts \
	install_util \
	install_runtime \
	install_boehm_gc \
	install_library \
	install_mdbcomp \
	install_browser \
	install_ssdb \
	install_trace \
	install_compiler \
	install_mfilterjavac \
	install_slice \
	install_profiler \
	install_deep_profiler \
	install_doc \
	install_config

.PHONY: install_scripts
install_scripts: scripts
	+cd scripts && $(SUBDIR_MMAKE) install

.PHONY: install_util
install_util: util
	+cd util && $(SUBDIR_MMAKE) install

.PHONY: install_config
install_config:
	test -d $(INSTALL_RECONF_DIR) || mkdir -p $(INSTALL_RECONF_DIR)
	cp VERSION aclocal.m4 configure configure.ac config.guess \
		config.sub install-sh $(INSTALL_RECONF_DIR)

.PHONY: install_runtime
install_runtime: runtime
	+cd runtime && $(SUBDIR_MMAKE) install

.PHONY: install_trace
install_trace: trace
	+cd trace && $(SUBDIR_MMAKE) install

# When building the compiler in a non-C grade, the header files for
# the Boehm GC system still need to be installed, because otherwise,
# an installed non-C grade compiler will not be able to compile anything
# in .gc grades.
.PHONY: install_boehm_gc
ifeq ("$(filter csharp% java%,$(GRADE))","")
install_boehm_gc: boehm_gc
	+gc_grade=`scripts/ml --grade $(GRADE) --print-gc-grade`; \
	cd boehm_gc && $(SUBDIR_MMAKE) install GC_GRADE=$$gc_grade
else
install_boehm_gc: boehm_gc
	cd boehm_gc && $(SUBDIR_MMAKE) install_headers GC_GRADE=gc
endif

.PHONY: install_library
install_library: dep_library library
	+cd library && $(SUBDIR_MMAKE) install

.PHONY: install_mdbcomp
install_mdbcomp: dep_mdbcomp mdbcomp
	+cd mdbcomp && $(SUBDIR_MMAKE) install

.PHONY: install_browser
install_browser: dep_browser browser
	+cd browser && $(SUBDIR_MMAKE) install

.PHONY: install_ssdb
install_ssdb: dep_ssdb ssdb
	+cd ssdb && $(SUBDIR_MMAKE) install

.PHONY: install_compiler
install_compiler: dep_compiler compiler
	+cd compiler && $(SUBDIR_MMAKE) install

.PHONY: install_mfilterjavac
install_mfilterjavac: dep_mfilterjavac mfilterjavac
	+cd mfilterjavac && $(SUBDIR_MMAKE) install

.PHONY: install_doc
install_doc: doc
	+cd doc && $(SUBDIR_MMAKE) install

.PHONY: install_slice
install_slice: slice
	+cd slice && $(SUBDIR_MMAKE) install

.PHONY: install_profiler
install_profiler: profiler
	+cd profiler && $(SUBDIR_MMAKE) install

.PHONY: install_deep_profiler
install_deep_profiler: deep_profiler
	+cd deep_profiler && $(SUBDIR_MMAKE) install

# LIBGRADE_SUFFIXES = .m .int3 .date3 .int2 .int .date .opt .optdate \
#	.trans_opt .trans_opt_date .d .mh .mih .c_date .c .o .pic_o

ifeq ($(CROSS_COMPILING),yes)
OVERRIDE_MC_FOR_LIBGRADE =
else
	# We must override the paths in the mmc script in case the compiler
	# was installed to a temporary location, using DESTDIR.
OVERRIDE_MC_FOR_LIBGRADE = MC=mmc \
	MERCURY_COMPILER=$(INSTALL_BINDIR)/mercury_compile \
	MERCURY_CONFIG_DIR=$(INSTALL_LIBDIR)
endif

.PHONY: install_grades
install_grades: install_main
	# Use the newly installed compiler to build the libraries in various
	# different grades. Except when cross-compiling, we override MC=mmc so
	# that we use the mmc from the scripts directory, which runs the newly
	# installed compiler, rather than using the bootstrap compiler.
	#
	# Compile different grades in different directories, so that we can
	# optionally preserve all the directories, and include them in
	# a distribution.
	#
	# Force mmc --make for grades which require it.
	+for grade in x $(LIBGRADES); do                                      \
	    if test "$${grade}" = "x" -o "$${grade}" = "$(GRADE)"; then       \
		continue;                                                     \
	    fi;                                                               \
	    gc_grade=`scripts/ml --grade $${grade} --print-gc-grade`;         \
	    IWS=`/bin/pwd`/install_grade_dir.$${grade};                       \
	    (                                                                 \
		case $${grade} in                                             \
			csharp*|java*) MMAKE_USE_MMC_MAKE=yes;		      \
		esac;                                                         \
		scripts/prepare_install_dir $${IWS} &&                        \
		( cd $${IWS}/boehm_gc &&                                      \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			GC_GRADE=$${gc_grade} install_lib ) &&                \
		( cd $${IWS}/runtime &&                                       \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			install_lib ) &&                                      \
		( cd $${IWS}/library &&                                       \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			depend &&                                             \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			install_library ) &&                                  \
		( cd $${IWS}/mdbcomp &&                                       \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			depend &&                                             \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			install_library ) &&                                  \
		( cd $${IWS}/browser &&                                       \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			depend &&                                             \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			install_library ) &&                                  \
		( cd $${IWS}/ssdb &&                                          \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			depend &&                                             \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			install_library ) &&                                  \
		( cd $${IWS}/trace &&                                         \
		  $(SUBDIR_MMAKE) $(OVERRIDE_MC_FOR_LIBGRADE)                 \
			GRADE=$${grade} WORKSPACE=$${IWS}                     \
			install_lib ) &&                                      \
		true                                                          \
	    ) ||                                                              \
	    { echo "To clean up from failed install, remove $${IWS}";         \
	      exit 1; };                                                      \
	    if test ! -f .leave_tmp_dir; then rm -fr $${IWS}; fi;             \
	done;

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

.PHONY: uninstall
uninstall:
	+cd compiler; $(SUBDIR_MMAKE) uninstall
	+cd deep_profiler; $(SUBDIR_MMAKE) uninstall
	+cd doc; $(SUBDIR_MMAKE) uninstall
	+cd mfilterjavac; $(SUBDIR_MMAKE) uninstall
	+cd profiler; $(SUBDIR_MMAKE) uninstall
	+cd scripts; $(SUBDIR_MMAKE) uninstall
	+cd slice; $(SUBDIR_MMAKE) uninstall
	+cd util; $(SUBDIR_MMAKE) uninstall
	-rm -r $(INSTALL_LIBDIR)

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

.PHONY: bindist
bindist: WORK_IN_PROGRESS TODO
	cd bindist; \
		PATH="$(INSTALL_PREFIX)/bin:$$PATH" \
		MMAKE_DIR="$(INSTALL_MMAKE_DIR)" \
		mmake -v binary_distribution

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

clean: clean_tests clean_subdirs clean_extras

.PHONY: clean_subdirs
clean_subdirs:
	+for dir in $(SUBDIRS); do \
		if test "$$dir" = scripts; then continue; fi; \
		(cd $$dir; $(SUBDIR_MMAKE) clean) \
	done

.PHONY: clean_tests
clean_tests:
	+if test -d tests; then \
		(cd tests; $(MMAKE) $(MMAKEFLAGS) clean) \
	fi

realclean: realclean_tests realclean_subdirs realclean_local
	+cd scripts; $(SUBDIR_MMAKE) realclean

.PHONY: clean_extras
clean_extras:
	+if test -d extras; then \
		(cd extras; $(MMAKE) $(MMAKEFLAGS) clean) \
	fi

.PHONY: realclean_local
realclean_local: realclean_config realclean_docs realclean_extras

.PHONY: realclean_subdirs
realclean_subdirs: clean_subdirs
	rm -rf stage[1-3] stage[1-3].*
	rm -rf tests/PASSED_TC_DIR tests/FAILED_TC_DIR
	+for dir in $(SUBDIRS); do \
		if test "$$dir" = scripts; then continue; fi; \
		(cd $$dir; $(SUBDIR_MMAKE) realclean) \
	done

.PHONY: realclean_docs
realclean_docs:
	rm -f $(GENERATED_DOCS)

.PHONY: realclean_config
realclean_config:
	rm -f config.cache config.status config.log configure.log configure.help

.PHONY: realclean_tests
realclean_tests:
	+if test -d tests; then \
		(cd tests; $(MMAKE) $(MMAKEFLAGS) realclean) \
	fi

.PHONY: realclean_extras
realclean_extras:
	+if test -d extras; then \
		(cd extras; $(MMAKE) $(MMAKEFLAGS) realclean) \
	fi

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