#
# Mach Operating System
# Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
# All Rights Reserved.
# 
# Permission to use, copy, modify and distribute this software and its
# documentation is hereby granted, provided that both the copyright
# notice and this permission notice appear in all copies of the
# software, derivative works or modified versions, and any portions
# thereof, and that both notices appear in supporting documentation.
# 
# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
# CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
# 
# Carnegie Mellon requests users of this software to return to
# 
#  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
#  School of Computer Science
#  Carnegie Mellon University
#  Pittsburgh PA 15213-3890
# 
# any improvements or extensions that they make and grant Carnegie Mellon
# the rights to redistribute these changes.
#
#
# HISTORY
# $Log:	Makefile,v $
# Revision 2.19  92/04/08  23:19:23  rpd
# 	Fixed vers.config creation for DG Unix.
# 	[92/04/05            rpd]
# 
# Revision 2.18  92/03/05  22:46:00  rpd
# 	Fixed to remove the kernel binary after configuring.
# 	Changed to use double-colon rules for top-level targets.
# 	[92/02/27            rpd]
# 
# Revision 2.17  92/02/19  15:06:11  elf
# 	Changed to use Makefile-common, Makefile-xstrip, Makefile-subdirs,
# 	Makefile-version, and Makefile-config.
# 	[92/02/16            rpd]
# 
# Revision 2.16  92/02/18  19:06:15  elf
# 	Luna default should STD+ANY+HW_FOOTPRINT; set to be
# 	that +lineno+savearg+assert as we are currently just building
# 	 debugging kernels.
# 	[92/02/18            danner]
# 
# Revision 2.15  92/01/24  00:49:35  rpd
# 	Removed or fixed MAKEPSD uses, to fix shadowing.
# 	[92/01/23            rpd]
# 
# Revision 2.14  92/01/23  15:19:56  rpd
# 	Revised for new Makefile organization.
# 	[92/01/16            rpd]
# 

include ${MAKETOP}Makefile-common
# more definitions, for using xstrip
include ${MAKETOP}Makefile-xstrip
# more definitions, for recursive makes
include ${MAKETOP}Makefile-subdirs
# definition of VERSION
include ${MAKETOP}Makefile-version
# definition of CONFIG
include ${MAKETOP}Makefile-config

# Dependencies in this Makefile are a little strange.
# To avoid conflicting with *.d/Makedep/Makefile.internal, this
# Makefile uses *.D and MakeDep.  (It only puts a few hand-generated
# dependencies in MakeDep.)  Hence, we must override the normal
# definition of EXIT_RULE.

EXIT_RULE = -${MD} -u MakeDep -f -d *.D

# man pages that we install

MANPAGES = ddb host_info host_ipc_statistics host_kernel_version \
	host_processor_set_priv host_processor_sets host_processors \
	mach_host_self mach_msg mach_port_allocate \
	mach_port_allocate_name mach_port_deallocate mach_port_destroy \
	mach_port_extract_right mach_port_get_receive_status \
	mach_port_get_refs mach_port_get_set_status \
	mach_port_insert_right mach_port_mod_refs mach_port_move_member \
	mach_port_names mach_port_rename mach_port_request_notification \
	mach_port_set_mscount mach_port_set_qlimit mach_port_set_seqno \
	mach_port_type mach_ports mach_reply_port mach_task_self \
	mach_thread_self memory_object_copy memory_object_create \
	memory_object_data_error memory_object_data_initialize \
	memory_object_data_provided memory_object_data_request \
	memory_object_data_unavailable memory_object_data_unlock \
	memory_object_data_write memory_object_destroy \
	memory_object_get_attributes memory_object_init \
	memory_object_lock_completed memory_object_lock_request \
	memory_object_server memory_object_set_attributes \
	memory_object_terminate processor_assign processor_control \
	processor_info processor_set_create processor_set_default \
	processor_set_destroy processor_set_info \
	processor_set_max_priority processor_set_policy_enable \
	processor_set_tasks processor_set_threads task_assign \
	task_create task_info task_priority task_resume \
	task_special_ports task_suspend task_terminate task_threads \
	thread_abort thread_assign thread_create thread_info \
	thread_policy thread_priority thread_resume thread_special_ports \
	thread_state thread_suspend thread_switch thread_terminate \
	thread_wire vm_allocate vm_copy vm_deallocate vm_inherit \
	vm_machine_attribute vm_map vm_protect vm_read vm_region \
	vm_set_default_memory_manager vm_statistics vm_wire vm_write

# interesting top-level targets
#
#	Makefile		produces ${CONFIG}/Makefile.internal
#	mach.boot		produces ${CONFIG}/mach.boot
#	mach_kernel		produces ${CONFIG}/mach_kernel
#	kernel			produces ${CONFIG}/mach_kernel
#	*.o			produces ${CONFIG}/*.o
#
# The kernel uses a different object subdirectory for each configuration.
# The object subdirectory has the same name as the configuration.
# This rule creates the subdirectory if necessary and remakes in it.
#
# What makes this hairy is that there is no source subdirectory
# corresponding to the configuration subdirectory.  This means we
# have to fool make into doing the right thing, by adjusting
# make's variables.
#
# If the vers.config file does not contain the current configuration name,
# then Makefile.internal is removed, to force reconfiguration.
# (This happens if configuration FOO is made, the object directory
# is renamed to BAR, and then configuration BAR is made.)
# (The vers.config is NOT created with ${CP} /dev/null, because on some
# bizarre systems that doesn't work properly.)
#
# Inside the ${CONFIG} object subdirectory, targets are either actual real
# file names or have the suffix .internal.  The default rule for .internal
# targets recurses yet again, using the generated Makefile.internal.
# To prevent the default rule from being invoked, some other rules
# have empty ("@") rule lines.
#
# The default rule at the end of the Makefile handles the targets
# ${MACH_KERNEL}.internal and *.o.internal.  There is no dependency
# of ${MACH_KERNEL} on ${MACH_KERNEL}.internal.
# If there were, makes of (eg) mach.boot would always regenerate mach.boot,
# because make would recurse to do ${MACH_KERNEL}.internal and then
# regenerate everything above ${MACH_KERNEL}.internal in the dependency tree.
# (Even though the timestamp on ${MACH_KERNEL} didn't change.)
#
# Instead, we use a .INIT rule to check that ${MACH_KERNEL}.internal
# is up-to-date when making all, install, and make.boot.
# This way there is no direct dependency to cause spurious actions.

# pass down additional variables to the recursive make
MVARIABLES = ${MVARIABLES} CONFIG VERSION MACH_KERNEL MAKETOP MAKESUB

all install release clean mach.boot mach_kernel kernel Makefile ::
	@-[ -d ${CONFIG} ] || \
	  { echo "mkdir ${CONFIG}"; \
	    mkdir ${CONFIG}; \
	    > ${CONFIG}/vers.config; }
	@-[ "${CONFIG}" = "`cat ${CONFIG}/vers.config`" ] || \
	  ${RM} ${CONFIG}/Makefile.internal
	@MAKEDIR="/"; export MAKEDIR; \
	MAKECWD="$${MAKECWD}/${CONFIG}"; export MAKECWD; \
	MAKEPSD="`echo :$${MAKEPSD} | \
		sed -e 's;:\.\./;:../../;g' -e 's/^://'`"; export MAKEPSD; \
	echo "cd ${CONFIG}"; \
	cd ${CONFIG} && \
	${MAKE} ${MFLAGS} TARGET=$@ $@.internal

# Make doesn't seem to allow %.o in a double-colon rule.  Grrr.

%.o :
	@-[ -d ${CONFIG} ] || \
	  { echo "mkdir ${CONFIG}"; \
	    mkdir ${CONFIG}; \
	    > ${CONFIG}/vers.config; }
	@-[ "${CONFIG}" = "`cat ${CONFIG}/vers.config`" ] || \
	  ${RM} ${CONFIG}/Makefile.internal
	@MAKEDIR="/"; export MAKEDIR; \
	MAKECWD="$${MAKECWD}/${CONFIG}"; export MAKECWD; \
	MAKEPSD="`echo :$${MAKEPSD} | \
		sed -e 's;:\.\./;:../../;g' -e 's/^://'`"; export MAKEPSD; \
	echo "cd ${CONFIG}"; \
	cd ${CONFIG} && \
	${MAKE} ${MFLAGS} TARGET=$@ $@.internal

# We want the MK version & configuration to be part of these names.
# Makefile-version defined VERSION for us.
# Makefile-config defined CONFIG for us.

MACH_KERNEL = mach_kernel.${VERSION}.${CONFIG}
MACH_BOOT = mach.boot.${VERSION}.${CONFIG}
BOOTSTRAP = bootstrap.${VERSION}

TARGETS = ${MACH_KERNEL} ${MACH_BOOT}

IMANTARGETS = ${MANPAGES;.*;${INSTALLDIR}/man/man2/&.2}
ITARGETS = ${TARGETS;.*;${INSTALLDIR}/special/&} ${IMANTARGETS}

TMANTARGETS = ${MANPAGES;.*;${TRELEASEDIR}/man/man2/&.2}
TTARGETS = ${TARGETS;.*;${TRELEASEDIR}/special/&} ${TMANTARGETS}

all.internal : ${TARGETS}
	@

kernel.internal mach_kernel.internal : ${MACH_KERNEL}.internal
	@

install.internal : ${ITARGETS}
	@

release.internal : ${TTARGETS}
	@

clean.internal :
	${RM} ${ITARGETS}

all_INIT = ${MACH_KERNEL}.internal
install_INIT = ${MACH_KERNEL}.internal
mach.boot_INIT = ${MACH_KERNEL}.internal
# unlike install, release does NOT check ${MACH_KERNEL}.internal
INIT_TARGET = ${${TARGET}_INIT}

.INIT :: ${INIT_TARGET}

# installation rules

${INSTALLDIR}/special/${MACH_KERNEL} : ${MACH_KERNEL}
	${RM} $@
	${CP} $? $@
	${XSTRIP} $@
	${CHMOD_BIN} $@

${INSTALLDIR}/special/${MACH_BOOT} : ${MACH_BOOT}
	${RM} $@
	${CP} $? $@
	${CHMOD_BIN} $@

${IMANTARGETS} : $${@;.*/([^/]*)\.2;man/\1.man}
	${RM} $@
	${CP} $? $@
	${CHMOD_MAN} $@

# release rules

${TRELEASEDIR}/special/${MACH_KERNEL} : ${FRELEASEDIR}/special/${MACH_KERNEL}
	${RM} $@
	${CP} $? $@

${TRELEASEDIR}/special/${MACH_BOOT} : ${FRELEASEDIR}/special/${MACH_BOOT}
	${RM} $@
	${CP} $? $@

${TMANTARGETS} : $${@;.*/(man/man2/[^/]*\.2);${FRELEASEDIR}/\1}
	${RM} $@
	${CP} $? $@

# mach.boot is made with makeboot, which combines a kernel image
# and a bootstrap image to produce a single bootable image.
# The sh/sed mess does two things:
#	1) Finds bootstrap.  We don't have a path for special subdirectories,
#	so we make one from LPATH via sed.
#	2) Generates dependencies on makeboot and bootstrap.
#
# Just as ${MACH_KERNEL} is linked to mach_kernel,
# ${MACH_BOOT} is linked to mach.boot.
#
# NB: ${INSTALLDIR}/special/${MACH_KERNEL} is xstripped;
# ${MACH_KERNEL} is not.  We want the xstripped image.

mach.boot.internal : ${MACH_BOOT}
	@

${MACH_BOOT} : ${INSTALLDIR}/special/${MACH_KERNEL}
	@makeboot="`${WH} -q makeboot`"; \
	SPATH="`echo $${LPATH}: | sed -e 's;/lib:;/special:;g' -e 's;:$$;;'`"; \
	export SPATH; \
	bootstrap="`${WH} -q -p SPATH ${BOOTSTRAP}`"; \
	{ echo "$@: $${makeboot}"; \
	  echo "$@: $${bootstrap}"; } >> $@.D; \
	kernel="${INSTALLDIR}/special/${MACH_KERNEL}"; \
	echo "[ generating $@ from $${kernel} and $${bootstrap} ]"; \
	${RM} $@ mach.boot; \
	$${makeboot} -o $@ $${kernel} $${bootstrap} && \
	ln $@ mach.boot

# The doconf process produces a configuration file in the object subdirectory.
# The configuration file has the same name as the subdirectory, ie ${CONFIG}.
# As input it uses the various MASTER files from the conf subdirectory.

DOCONF_INPUT = conf/MASTER conf/MASTER.${cpu} \
	conf/MASTER.local conf/MASTER.${cpu}.local

${CONFIG} : ${DOCONF} ${DOCONF_INPUT}
	@echo "[ generating $@ from conf/MASTER{,.${cpu}}{,.local} ]"
	@doconf="`${WH} -q doconf`"; \
	echo "$@: $${doconf}" >> $@.D; \
	$${doconf} ${CONFIG} ${DOCONF_INPUT} > ${CONFIG}.tmp
	@-if [ -f ${CONFIG} ]; then \
	    diff ${CONFIG} ${CONFIG}.tmp; \
	    mv -f ${CONFIG} ${CONFIG}.old; \
	fi; mv -f ${CONFIG}.tmp ${CONFIG}

# The config process produces Makefile.internal in the object subdirectory.
# As input it uses the configuration file from doconf and some files
# from the conf subdirectory.
#
# We generate a dependency on config.
#
# We save the current configuration in vers.config, so that if the
# object directory is renamed we will know to reconfigure.  We remove
# the ${MACH_KERNEL} binary, to guarantee that it is at least relinked.
# (For example, the current configuration might contain a subset of
# the .o files in the previous configuration.)

CONFIG_INPUT = conf/files conf/files.${cpu} \
	conf/Makefile.template conf/Makefile.${cpu}

Makefile.internal : ${CONFIG} ${CONFIG_INPUT}
	@echo "[ configuring in ${CONFIG} ]"
	@config="`${WH} -q config`"; \
	echo "$@: $${config}" >> $@.D; \
	$${config} -c conf ${CONFIG}
	@${RM} ${MACH_KERNEL}
	@echo ${CONFIG} > vers.config

# The default rule for targets is to remake with Makefile.internal.
# The kernel includes only its own files, and with <>, so we reset CPATH.
# Because MFLAGS also sets CPATH, we rely on make taking the first definition.

%.internal : Makefile.internal
	@echo "[ making ${@:r} in ${CONFIG} ]"
	@${MAKE} -f Makefile.internal CPATH=. ${MFLAGS} ${@:r}

-include MakeDep
