# Scheme 48 Makefile
# Documentation in files INSTALL and doc/install.txt

SHELL = /bin/sh

### Filled in by `configure' ###
srcdir = @srcdir@
VPATH = @srcdir@
CC = @CC@
DEFS = @DEFS@
LIBS = @LIBS@
CFLAGS = @CFLAGS@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@

LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@

prefix = @prefix@
exec_prefix = @exec_prefix@
### End of `configure' section###

bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
incdir = $(exec_prefix)/include
manext = 1
mandir = $(prefix)/man/man$(manext)

# HP 9000 series, if you don't have gcc
#   CC = cc
#   CFLAGS = -Aa -O +Obb1800
#   DEFS = -D_HPUX_SOURCE -Dhpux

# Ultrix
#   LDFLAGS = -N

.c.o:
	$(CC) -c $(CPPFLAGS) $(DEFS) -I$(srcdir)/c $(CFLAGS) -o $@ $<

# You might want to change RUNNABLE to "s48"
RUNNABLE = scheme48
MANPAGE = $(RUNNABLE).$(manext)
LIB = $(libdir)/$(RUNNABLE)

distdir = /tmp

# If make barfs on this include line, just comment it out.  It's only
# really needed if you want to build the linker or rebuild initial.image.
include $(srcdir)/build/filenames.make
#
#NetBSD make wants to see this instead:
#.include "$(srcdir)/build/filenames.make"


# Static linker:
#
# You only need the linker if you're going to make changes to the
# things that go into the initial.image, which in general means the
# files in rts/.  If you decide you need to use the linker, then you
# gots your choice; it can run in just about any version of Scheme 48
# or Pseudoscheme.  (It has also been made to run in Scheme->C.)  It
# doesn't matter a whole lot which Scheme you use as long as it's not
# broken or unavailable.  The two best choices are:
# 1. As below: build the linker on the scheme48vm and scheme48.image
#    that are in the current directory.
# 2. LINKER_VM = $(RUNNABLE) $(BIG_HEAP)
#    LINKER_RUNNABLE = $(RUNNABLE)
#    These settings requires you to already have a $(RUNNABLE)
#    command.  This is desirable if you are making changes to the
#    system that might break scheme48vm and/or scheme48.image.  But it
#    requires you to have squirreled away a previous working version
#    of scheme48.

BIG_HEAP = -h 5000000
LINKER_VM = ./$(VM) $(BIG_HEAP)
LINKER_RUNNABLE = $(LINKER_VM) -i $(IMAGE)
LINKER_IMAGE = build/linker.image
LINKER = $(LINKER_VM) -i $(LINKER_IMAGE)
START_LINKER = echo ',batch' && echo ',bench on'

# --------------------
# You shouldn't have to change anything below this point, except for possibly
# the external code rules.

# Targets:

IMAGE = scheme48.image
INITIAL = build/initial.image
VM = scheme48vm
UNIX_OBJS = c/unix/misc.o c/unix/io.o c/unix/fd-io.o c/unix/event.o
OBJS = c/scheme48vm.o c/scheme48heap.o c/extension.o c/external.o
FAKEHS	= c/fake/dlfcn.h c/fake/sigact.h c/fake/strerror.h \
		c/fake/sys-select.h

# Sources:

CONFIG_FILES = scheme/interfaces.scm scheme/low-packages.scm \
	       scheme/rts-packages.scm scheme/comp-packages.scm

# Rules:

# The following is the first rule and therefore the "make" command's
# default target.
enough: $(VM) $(IMAGE) go .notify

# --------------------
# External code to include in the VM
# After changing any of these you should delete `scheme48vm' and remake it.

EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS)
EXTERNAL_FLAGS = $(SOCKET_FLAGS)
EXTERNAL_INITIALIZERS = $(SOCKET_INITIALIZERS) $(LOOKUP_INITIALIZERS)

# Rules for any external code.

# Socket rules

c/unix/socket.o: c/scheme48.h c/fd-io.h c/event.h

SOCKET_OBJECTS = c/unix/socket.o
SOCKET_LD_FLAGS =
SOCKET_INITIALIZERS = 	s48_init_socket

# End of socket rules

# Lookup rules (this is just for compatibility with old code)

c/unix/dynamo.o: c/scheme48.h

LOOKUP_OBJECTS = c/unix/dynamo.o
LOOKUP_INITIALIZERS = 	s48_init_external_lookup

# End of lookup rules
# End of external rules
# --------------------

# The developers are curious to know.  Don't be concerned if this fails.
.notify: build/minor-version-number
	touch .notify
	-echo Another 0.`cat $(srcdir)/build/minor-version-number` \
		installation. \
		| mail scheme-48-notifications@martigny.ai.mit.edu

$(VM): c/main.o $(OBJS) $(UNIX_OBJS) $(LIBOBJS) $(EXTERNAL_OBJECTS)
	rm -f /tmp/s48_external_$$$$.c &&					\
	build/build-external-modules /tmp/s48_external_$$$$.c			\
		$(EXTERNAL_INITIALIZERS) &&					\
	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ c/main.o $(OBJS) $(UNIX_OBJS)		\
		/tmp/s48_external_$$$$.c					\
		$(LIBOBJS) $(LIBS)						\
		$(EXTERNAL_OBJECTS) $(EXTERNAL_LD_FLAGS) &&			\
	rm -f /tmp/s48_external_$$$$.c

c/main.o: c/main.c c/scheme48vm.h c/scheme48heap.h
	$(CC) -c $(CFLAGS) -o $@ \
		-DDEFAULT_IMAGE_NAME=\"$(LIB)/$(IMAGE)\" \
		$(CPPFLAGS) $(DEFS) c/main.c

c/scheme48vm.o: c/prescheme.h c/scheme48vm.h c/scheme48heap.h c/event.h \
			c/io.h c/fd-io.h c/scheme48vm-prelude.h
c/scheme48heap.o: c/prescheme.h c/scheme48vm.h c/scheme48heap.h c/event.h \
			c/io.h c/fd-io.h
c/extension.o: c/sysdep.h $(FAKEHS) c/scheme48.h c/scheme48vm.h
c/external.o: c/sysdep.h $(FAKEHS) c/scheme48.h
c/unix/event.o: c/sysdep.h $(FAKEHS) c/scheme48vm.h c/scheme48heap.h \
			c/event.h c/fd-io.h
c/unix/fd-io.o: c/sysdep.h $(FAKEHS) c/scheme48vm.h c/scheme48heap.h \
			c/event.h c/fd-io.h
c/unix/misc.o: c/sysdep.h $(FAKEHS)
c/unix/io.o: c/io.h
c/fake/libdl1.o: c/fake/dlfcn.h
c/fake/libdl2.o: c/fake/dlfcn.h
c/fake/strerror.o: c/fake/strerror.h

# --------------------
# Make scheme48.image from initial.image and library .scm files.
#
# For bootstrap reasons, initial.image is *not* listed as a source,
# even though it really is.

$(IMAGE): $(VM) scheme/env/init-defpackage.scm scheme/more-interfaces.scm \
		scheme/link-packages.scm scheme/more-packages.scm \
		$(usual-files) build/initial.debug build/build-usual-image
	build/build-usual-image . "`pwd`/scheme" '$(IMAGE)' './$(VM)' \
		'$(INITIAL)'

### Fake targets:  all clean install man dist

install: enough dirs inst-script inst-vm inst-misc inst-man inst-inc inst-image

inst-vm:
	$(INSTALL_PROGRAM) $(VM) $(LIB)

inst-image:
	rm -f '/tmp/$(IMAGE)' &&					\
	build/build-usual-image . '$(LIB)' '/tmp/$(IMAGE)' './$(VM)'	\
		'$(INITIAL)' &&						\
	$(INSTALL_DATA) /tmp/$(IMAGE) $(LIB) &&				\
	rm /tmp/$(IMAGE)

inst-man:
	if [ -d $(mandir) -a -w $(mandir) ]; then			   \
		sed 's=LBIN=$(bindir)=g' doc/scheme48.man |		   \
			sed 's=LLIB=$(LIB)=g' |				   \
			sed 's=LS48=$(RUNNABLE)=g' >$(MANPAGE) &&	   \
		$(INSTALL_DATA) $(MANPAGE) $(mandir) &&			   \
		rm $(MANPAGE);						   \
	else								   \
		echo "$(mandir) not writable dir, not installing man page" \
			>&2;						   \
	fi

inst-inc:
	$(INSTALL_DATA) c/scheme48.h $(incdir)

inst-misc:
	for stub in env big opt misc link; do				\
		for f in scheme/$$stub/*.scm; do			\
			$(INSTALL_DATA) $$f $(LIB)/$$stub || exit 1;	\
		done;							\
	done &&								\
	for f in scheme/rts/*num.scm scheme/rts/jar-defrecord.scm; do	\
		$(INSTALL_DATA) $$f $(LIB)/rts || exit 1;		\
	done

inst-script:
	script=$(bindir)/$(RUNNABLE) &&					\
	echo '#!/bin/sh'	>$$script &&				\
	echo			>>$$script &&				\
	echo 'lib=$(LIB)'	>>$$script &&				\
	echo 'exec $$lib/$(VM) -o $$lib/$(VM) -i $$lib/$(IMAGE) "$$@"'	\
				>>$$script &&				\
	chmod +x $$script

# Script to run scheme48 in this directory.
go:
	echo '#!/bin/sh'	>$@ &&					\
	echo			>>$@ &&					\
	echo "lib=`pwd`"	>>$@ &&					\
	echo 'exec $$lib/$(VM) -o $$lib/$(VM) -i $$lib/$(IMAGE) "$$@"'	\
				>>$@ &&					\
	chmod +x $@

dirs:
	for dir in $(libdir) $(bindir) $(incdir); do			 \
		[ -d $$dir -a -w $$dir ] || {				 \
			echo "$$dir not a writable directory" >&2;	 \
			exit 1;						 \
		};							 \
	done
	{ mkdir -p $(LIB) && [ -w $(LIB) ]; } || {			 \
		echo "$(LIB) not a writable directory" >&2;		 \
		exit 1;							 \
	}
	for dir in rts env big opt misc link; do			  \
		{ mkdir -p $(LIB)/$$dir && [ -w $(LIB)/$$dir ]; } || {	  \
			echo "$(LIB)/$$dir not a writable directory" >&2; \
			exit 1;						  \
		};							  \
	done

configure: configure.in
	autoheader && autoconf

clean:
	-rm -f $(VM) *.o c/unix/*.o c/*.o c/fake/*.o			\
		TAGS $(IMAGE)						\
		build/*.tmp $(MANPAGE) build/linker.image		\
		scheme/debug/*.image scheme/debug/*.debug config.cache	\
		scheme/vm/scheme48vm.c scheme/vm/scheme48heap.c		\
		go $(distname)

distclean: clean
	rm -f Makefile config.log config.status c/sysdep.h

check:	$(VM) $(IMAGE) scheme/debug/check.scm
	(								\
		echo ',batch';						\
		echo ',translate =scheme48 scheme';			\
		echo ',config ,load scheme/debug/test.scm';		\
		echo ',exec ,load scheme/debug/check.scm';		\
		echo ',exec (done)'					\
	) | ./$(VM) -i $(IMAGE)

# --------------------
# Rules from here on down are not essential for the basic installation
# procedure, and are not expected to work when srcdir is not the
# distribution directory.

all: vm linker
	$(MAKE) image
vm: $(VM)
linker: $(LINKER_IMAGE)
image: $(INITIAL)
	$(MAKE) $(IMAGE)

tags:
	etags scheme/vm/arch.scm scheme/rts/*.scm scheme/bcomp/*.scm \
	scheme/*.scm scheme/env/*.scm scheme/big/*.scm scheme/link/*.scm \
	scheme/opt/*.scm scheme/debug/*.scm scheme/misc/*.scm

# --------------------
# Distribution...

# DISTFILES should include all sources.
DISTFILES = README COPYING INSTALL configure				\
		acconfig.h configure.in Makefile.in install-sh		\
		doc/*.ps doc/*.txt doc/html/*.html doc/scheme48.man	\
		doc/src/*.tex doc/src/*.sty				\
		emacs/README build/*-version-number build/*.exec	\
		build/*.lisp build/build-usual-image build/filenames.make \
		build/filenames.scm build/initial.debug			\
		build/initial.image build/initial.scm			\
		build/build-external-modules				\
		c/*.[ch] c/*/*.[ch] c/scheme48.h.in			\
		emacs/*.el gdbinit					\
		scheme/*.scm scheme/*/*.scm				\
		ps-compiler						\
		c/sysdep.h.in

distname = $(RUNNABLE)-0.`cat build/minor-version-number`

dist: build/initial.image
	distname=$(distname) &&						\
	distfile=$(distdir)/$$distname.tgz &&				\
	if [ -d $(distdir) ] &&						\
	   [ -w $$distfile -o -w $(distdir) ]; then			\
		rm -f $$distname &&					\
		ln -s . $$distname &&					\
		files='' &&						\
		for i in $(DISTFILES); do				\
			if [ "$$i" != "c/sysdep.h" ]; then		\
				files="$$files $$distname/$$i";		\
			fi						\
		done &&							\
		tar -cf - $$files |					\
			gzip --best >$$distfile &&			\
		rm $$distname;						\
	else								\
		echo "Can't write $$distfile" >&2;			\
		exit 1;							\
	fi

# Increment the minor version number
inc:
	f=build/minor-version-number &&					\
	expr `cat $$f` + 1 >$$f.tmp &&					\
	mv $$f.tmp $$f &&						\
	echo '(define version-info "0.'`cat $$f`'")'			\
		>scheme/env/version-info.scm


# --------------------
# Generate build/filenames.make from *packages.scm
#
# This hack traces the module dependencies described in the
# various configuration files and converts them into dependency lists
# that "make" can use for its purposes.
#
# Since the distribution comes with a filenames.make, this rule
# shouldn't be invoked for simple installations.  But it will be used
# if you change any of the *-packages.scm files.
#
# You can actually run the forms in filenames.scm in any Scheme
# implementation that has syntax-rules and explicit-renaming low-level
# macros (e.g., most versions of Scheme 48 and Pseudoscheme).
# If there are errors running this script, and you need to debug,
# don't use the initial.image, use something that has a reasonable
# environment.
#
# If this fails and you don't feel like debugging or fixing the problem,
# try "touch filenames.make" and hope for the best.

PACKAGES=scheme/packages.scm scheme/rts-packages.scm scheme/alt-packages.scm \
	 scheme/comp-packages.scm scheme/initial-packages.scm \
	 scheme/link-packages.scm scheme/more-packages.scm \
	 build/filenames.scm

build/filenames.make: $(PACKAGES)
	$(MAKE) $(VM) PACKAGES=
	./$(VM) -i $(srcdir)/$(INITIAL) -a batch <build/filenames.scm
# or:	$(RUNNABLE) -a batch <build/filenames.scm

# --------------------
# Static linker
#
# The linker is capable of rebuilding an image from sources, even
# across an incompatible change in VM data representations.

build/linker.image: $(linker-files) scheme/alt/init-defpackage.scm
	(echo ',batch';						\
		echo ',bench on';				\
		echo ',open signals handle features';		\
		echo ',open bitwise ascii code-vectors record';	\
		echo ',load $(linker-files)';			\
		echo ',load scheme/alt/init-defpackage.scm';	\
		echo ',dump build/linker.image'			\
	) | $(LINKER_RUNNABLE)

# Or, to bootstrap from Lucid Common Lisp: (last tested with
# Pseudoscheme 2.9 and Scheme 48 version 0.19)

PSEUDODIR = ../pseudo

link/linker-in-lucid: build/lucid-script.lisp $(linker-files) \
	    scheme/alt/pseudoscheme-features.scm \
	    scheme/alt/pseudoscheme-record.scm
	(echo \(defvar pseudoscheme-directory \"$(PSEUDODIR)/\"\); \
	 cat build/lucid-script.lisp; \
	 echo \(dump-linker\) \(lcl:quit\)) \
	| lisp

# --------------------
# Initial image
#
# The initial.image is built by the static linker.  The image contains
# Scheme, the byte-code compiler, and a minimal command processor, but
# no debugging environment to speak of.

$(INITIAL): $(LINKER_IMAGE) $(CONFIG_FILES) build/initial.scm $(initial-files)
	($(START_LINKER);						\
		echo '(load-configuration "scheme/interfaces.scm")';	\
		echo '(load-configuration "scheme/packages.scm")';	\
		echo '(flatload initial-structures)';			\
		echo '(load "build/initial.scm")';			\
		echo '(link-initial-system)'				\
	) | $(LINKER)

# --------------------
# Various small images for debugging low-level changes

LOAD_DEBUG = \
	 $(START_LINKER); \
	 echo \(load-configuration \"scheme/interfaces.scm\"\); \
	 echo \(load-configuration \"scheme/packages.scm\"\); \
	 echo \(flatload debug-structures\)

scheme/debug/tiny.image: $(LINKER_IMAGE) scheme/debug/tiny-packages.scm \
		  scheme/debug/tiny.scm
	($(START_LINKER); \
	 echo \(load-configuration \"scheme/debug/tiny-packages.scm\"\); \
	 echo \(link-simple-system \'\(scheme/debug tiny\) \'start tiny-system\)) \
	| $(LINKER)

scheme/debug/low-test.image: $(LINKER_IMAGE) scheme/debug/low-test-packages.scm \
		  scheme/debug/low-test.scm
	($(START_LINKER); \
	 echo \(load-configuration \"scheme/debug/low-test-packages.scm\"\); \
	 echo \(link-simple-system \'\(scheme/debug low-test\) \'start low-test-system\)) \
	| $(LINKER)

scheme/debug/little.image: $(LINKER_IMAGE) $(CONFIG_FILES) scheme/debug-packages.scm
	($(LOAD_DEBUG); echo \(link-little-system\)) \
	| time $(LINKER)

scheme/debug/mini.image: $(LINKER_IMAGE) $(CONFIG_FILES)
	($(LOAD_DEBUG); echo \(link-mini-system\)) \
	| $(LINKER)

scheme/debug/medium.image: $(LINKER_IMAGE) $(CONFIG_FILES)
	($(LOAD_DEBUG); echo \(flatload compiler-structures\); \
	 echo \(link-medium-system\)) \
	| $(LINKER)

# The following have not been updated for the new directory organization

c/smain.o: c/main.c
	$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DSTATIC_AREAS -o $@ c/main.c

mini: mini-heap.o smain.o
	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ c/smain.o mini-heap.o $(OBJS) $(LIBS)

mini-heap.o: mini-heap.c
	$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -o $@ $(srcdir)/mini-heap.c

mini-heap.c: scheme/debug/mini1.image
	(echo ,exec ,load misc/load-static.scm; \
	 echo \(do-it 150000 \"$(srcdir)/scheme/debug/mini1.image\" \"$@\"\)) \
	| $(RUNNABLE) -h 3000000 -a batch

scheme/debug/mini1.image: $(VM) scheme/debug/mini.image
	echo "(write-image \"scheme/debug/mini1.image\" \
			   (usual-resumer (lambda (args) \
					    (command-processor #f args))) \
			   \"foo\")" \
	| ./$(VM) -i scheme/debug/mini.image -a batch


# --------------------
# Generate scheme48.h from VM sources

c/scheme48.h: c/scheme48.h.in scheme/vm/arch.scm scheme/vm/data.scm \
	    scheme/link/generate-c-header.scm
	(echo ',bench';								\
		echo ',batch';							\
		echo ',load-package big-scheme';				\
		echo ',open big-scheme';					\
		echo ',load scheme/link/generate-c-header.scm';			\
		echo "(make-c-header-file \"$@\"				\
					  \"$(srcdir)/c/scheme48.h.in\"		\
					  \"$(srcdir)/scheme/vm/arch.scm\"	\
					  \"$(srcdir)/scheme/vm/data.scm\"   	\
					  \"$(srcdir)/scheme/rts/record.scm\")"	\
	) | $(RUNNABLE)

# An old version of the above for legacy code.

c/old-scheme48.h: scheme/vm/arch.scm scheme/vm/data.scm \
	    scheme/link/generate-old-c-header.scm
	(echo ',bench';								\
		echo ',batch';							\
		echo ',load-package big-scheme';				\
		echo ',open big-scheme';					\
		echo ',load scheme/link/generate-old-c-header.scm';		\
		echo "(make-c-header-file \"$@\"				\
					  \"$(srcdir)/scheme/vm/arch.scm\"	\
					  \"$(srcdir)/scheme/vm/data.scm\")"   	\
	) | $(RUNNABLE)

# Generate vm (scheme48vm.c and scheme48heap.c) from VM sources.
# Never called automatically.  Do not use unless you are sure you
# know what you are doing.
# Afterwards, you should probably make c/scheme48.h.
i-know-what-i-am-doing:
	cd ps-compiler &&						     \
	(echo ',batch';							     \
		echo ',config ,load ../scheme/prescheme/interface.scm';	     \
		echo ',config ,load ../scheme/prescheme/package-defs.scm';   \
		echo ',exec ,load load-ps-compiler.scm';		     \
		echo ',exec ,load compile-vm-no-gc.scm';		     \
		echo ',exec ,load compile-gc.scm';			     \
		echo ',exit'						     \
	) | $(RUNNABLE) -h 8000000 &&					     \
		mv ../scheme/vm/scheme48vm.c ../scheme/vm/scheme48heap.c ../c
