## $Id: make_wizard.pattern 49 2003-12-30 09:48:02Z gerd $
## ----------------------------------------------------------------------
##

## This is the pattern for the Makefile. It consists of several sections,
## every section begins with [name] on a single line, and ends where the
## next section starts. Inside the sections, variables are written as 
## [name], too.
## Comments that must not be copied to the output file begin with two
## hash marks.

[intro]
# ----------------------------------------------------------------------
# How to build the package [name]:
# ----------------------------------------------------------------------
# 
# make:                Same as "make all"
# make all:            Normally "make byte", but can also be set to "make opt"
# make byte:           Makes the bytecode archive and the bytecode executables
# make opt:            Makes the native archive and the native executable
# make install:        Install all installable files as package
# make uninstall:      Uninstall the package
# make clean:          Delete all files that can be remade
#
# The usual order of invocation is:
# - make byte
# - (optionally) make opt
# - make install
# - make clean
#
# You may want to give the -s option if you do not want to see the details
# of the build process (e.g. make -s all).
#
# ----------------------------------------------------------------------
# Important for developers
# ----------------------------------------------------------------------
# 
# This Makefile writes a copy of itself with appended dependencies.
# The copy is usually stored in the file .make-wizard.[makefile_name].
# If you want to invoke "make" for targets where the dependencies are
# involved, you have to specify -f .make-wizard.[makefile_name] on
# the command line, e.g.
#
# make -f .make-wizard.[makefile_name] sample.cmo
#
# Otherwise, the dependencies are ignored, and you get errors that are
# hard to explain.
#
# If you want to modify this Makefile, it is a good idea to put the
# modifications into a second file, and to enable the local Makefile
# extension in the wizard. This effects that the modifications are appended
# to this Makefile, so you can add rules and override variables without
# coming into conflict with the wizard.

[def_general]
# ----------------------------------------------------------------------
# Definitions
# ----------------------------------------------------------------------

NAME = [name]
# The name of the package. 

MFNAME = [makefile_name]
# The name of this Makefile. (You must change this definition if you rename
# the Makefile!)

MF2NAME = .make-wizard.$(MFNAME)
# The name of the generated Makefile (a copy of this Makefile plus the
# dependencies)

TEMPNAME = .make-wizard.temps
# The name of a file containing the names of temporary files

VERSION = [version]
# The version of this package

DESCRIPTION = [description]
# The description of this package

GENERATOR_EXTS = .mll .mly
# These suffixes indicate that a generator must be called for them

MAKE_META = _meta
# Make the META file by this rule. (An empty definition turns META generation
# off.)

INSTALL = _findlib_install
# Which rule to use for installation

UNINSTALL = _findlib_uninstall
# Which rule to use for deinstallation

MAKEMAKE_HOOK =
# Set this to the name of a rule to add your own definitions to $(MF2NAME)


## The def_byte_archive section is only included if the byte archive is
## enabled:

[def_byte_archive]
BYTE_ARCHIVE = $(NAME).cma
# The name of the resulting bytecode archive.

BYTE_OBJECTS = [byte_objects]
# The cmo objects that are linked together, and are put into the byte archive.

BYTE_FILES = $(BYTE_OBJECTS) $(BYTE_OBJECTS:.cmo=.cmi) $(BYTE_ARCHIVE)
# The files that are generated in order to make the byte archive. Note
# that .ml and .mli files are missing that are generated from 
# .mly and .mll files. 

BYTE_INST = $(BYTE_OBJECTS:cmo=cmi) $(BYTE_OBJECTS:.cmo=.mli) $(BYTE_ARCHIVE)
# The files that will be installed after the byte archive is made. Not
# every file exists.


## The def_native_archive section is only included if the native archive is
## enabled:

[def_native_archive]
NAT_ARCHIVE = $(NAME).cmxa
# The name of the resulting native archive.

NAT_OBJECTS = [nat_objects]
# The cmx objects that are linked together, and are put into the native archive.

NAT_FILES = $(NAT_OBJECTS) $(NAT_OBJECTS:.cmx=.o) $(NAT_OBJECTS:.cmo=.cmi) \
    $(NAT_ARCHIVE) $(NAT_ARCHIVE:.cmxa=.a)
# The files that are generated in order to make the native archive. Note
# that .ml and .mli files are missing that are generated from 
# .mly and .mll files. 

NAT_INST = $(NAT_OBJECTS:.cmo=.cmi) $(NAT_OBJECTS:.cmo=.mli) $(NAT_ARCHIVE) \
    $(NAT_ARCHIVE:.cmxa=.a)
# The files that will be installed after the native archive is made. Not
# every file exists.


[def_byte_exec]
BYTE_EXEC_TARGETS = [byte_executables]
# The list of bytecode executables.

BYTE_EXEC_OBJECTS = [byte_exec_objects]
# The list of cmo modules that are linked into bytecode executables

BYTE_EXEC_FILES = $(BYTE_EXEC_OBJECTS) $(BYTE_EXEC_OBJECTS:.cmo=.cmi) \
    $(BYTE_EXEC_TARGETS)
# The list of files that are generated in order to make the bytecode
# executables. Note that .ml and .mli files are missing that are generated 
# from .mly and .mll files. 

BYTE_EXEC_INST = $(BYTE_EXEC_TARGETS)
# The files to install as bytecode executables.


[def_nat_exec]
NAT_EXEC_TARGETS = [nat_executables]
# The list of native executables.

NAT_EXEC_OBJECTS = [nat_exec_objects]
# The list of cmx modules that are linked into native executables

NAT_EXEC_FILES = $(NAT_EXEC_OBJECTS) $(NAT_EXEC_OBJECTS:.cmx=.cmi) \
    $(NAT_EXEC_OBJECTS:.cmx=.o) $(NAT_EXEC_TARGETS)
# The list of files that are generated in order to make the native
# executables. Note that .ml and .mli files are missing that are generated 
# from .mly and .mll files. 

NAT_EXEC_INST = $(NAT_EXEC_TARGETS)
# The files to install as native executables.


[def_props]
PREREQUISITES = [prereqs]
# The required packages.

PPOPTS = [ppopts]
# Preprocessor options.

MTOPTS = [mtopts]
# Multi-threading options

INCOPTS = 
# -I options (currently unused, but this may change in the future)

OTHER_INST = META
# Files to install that are not mentioned in the other XXX_INST variables

#TASKBYTELINKOPTS = -custom
# Uncomment this line to create stand-alone executables

[def_tools]
# Tools and tasks: "Tools" are the commands to call, and "tasks" are the tools
# to use for certain situations.

OCAMLFIND = ocamlfind
OCAMLLEX  = ocamllex
OCAMLYACC = ocamlyacc
OCAMLDEP  = $(OCAMLFIND) ocamldep
OCAMLC    = $(OCAMLFIND) ocamlc
OCAMLCP   = $(OCAMLFIND) ocamlcp
OCAMLOPT  = $(OCAMLFIND) ocamlopt
#
# These are the tools.

TASKLEX      = $(OCAMLLEX) $(TASKLEXOPTS)
TASKYACC     = $(OCAMLYACC) $(TASKYACCOPTS)
TASKDEP      = $(OCAMLDEP) $(INCOPTS) $(PPOPTS) -package "$(PREREQUISITES)" $(TASKDEPOPTS)
TASKCI       = $(OCAMLC) $(INCOPTS) $(PPOPTS) -package "$(PREREQUISITES)" -c $(TASKCIOPTS)
TASKBYTECO   = $(OCAMLC) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -c -g $(TASKBYTECOOPTS)
TASKBYTELINK = $(OCAMLC) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -linkpkg $(TASKBYTELINKOPTS)
TASKBYTEAR   = $(OCAMLC) -a $(TASKBYTEAROPTS)
TASKNATCO    = $(OCAMLOPT) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -c $(TASKNATCOOPTS)
TASKNATLINK  = $(OCAMLOPT) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -linkpkg $(TASKNATLINKOPTS)
TASKNATAR    = $(OCAMLOPT) -a $(TASKNATAROPTS)
TASKINSTALL  = $(OCAMLFIND) install $(NAME) $(TASKINSTALLOPTS)
TASKREMOVE   = $(OCAMLFIND) remove $(NAME) $(TASKREMOVEOPTS)
#
# These are the tasks. The names mean the following:
#                   TASKLEX: Used to create a lexer
#                  TASKYACC: Used to create a parser
#                   TASKDEP: Used to analyze the dependencies
#                    TASKCI: Used to compile interface files
#     TASKBYTECO, TASKNATCO: Used to compile implementation files
# TASKBYTELINK, TASKNATLINK: Used to create executables
#     TASKBYTEAR, TASKNATAR: Used to create archives
#               TASKINSTALL: Used to install the package
#                TASKREMOVE: Used to remove the package
#                   INCOPTS: -I options
#                    PPOPTS: Options to specify the preprocessor
#                    MTOPTS: -thread (if necessary)
#                   NATONLY: -native (if necessary)
# For every task <T>, there is a variable for task-specific options <T>OPTS.


[rules]
# ----------------------------------------------------------------------
# Rules
# ----------------------------------------------------------------------


[default_target]
.PHONY: all
all: [default_target]


[suffix_rules]
# The suffix rules: They specify how to make a file ending in suffix X from
# a source file ending in suffix Y. For every suffix rule, there is a task
# defining what to do.

.SUFFIXES: .ml .mli .cmo .cmx .cmi .mll .mly

.mli.cmi:
	@echo "<Making $@>"
	$(TASKCI) $<

.ml.cmo:
	@echo "<Making $@>"
	$(TASKBYTECO) $<

.ml.cmx:
	@echo "<Making $@>"
	$(TASKNATCO) $<

# The generator rules record the generated files: The "grep" checks whether
# the filename already occurs in $(TEMPNAME), and the "echo" appends the
# filename when missing.

.mll.ml:
	@echo "<Making $@>"
	$(TASKLEX) $<
	touch $(TEMPNAME)
	grep -F -x -q -e "$@" $(TEMPNAME) || echo "$@" >>$(TEMPNAME)

.mly.ml:
	@echo "<Making $@>"
	$(TASKYACC) $<
	touch $(TEMPNAME)
	grep -F -x -q -e "$@" $(TEMPNAME) || echo "$@" >>$(TEMPNAME)

# The _dummy rule does nothing:

_dummy:
	:

[generate]
# The following rule checks which lex and yacc targets exist, and calls
# MAKE recursively.

.PHONY: _meta
_meta:
	@echo "<Updating META>"
	echo "name = \"$(NAME)\"" >META
	echo "version = \"$(VERSION)\"" >>META
	echo "description = \"$(DESCRIPTION)\"" >>META
	echo "requires = \"$(PREREQUISITES)\"" >>META
	test -z "$(BYTE_ARCHIVE)" || \
	    echo "archive(byte) = \"$(BYTE_ARCHIVE)\"" >>META
	test -z "$(NAT_ARCHIVE)" || \
	    echo "archive(native) = \"$(NAT_ARCHIVE)\"" >>META

.PHONY: _generator
_generator: $(MAKE_META)
	@echo "<Checking for generator targets>"
	targets=$$( \
	    { \
		for obj in _dummy $(BYTE_OBJECTS) $(BYTE_EXEC_OBJECTS); do \
		    test "_dummy" != "$$obj" || continue; \
		    for ext in $(GENERATOR_EXTS); do \
		    	if [ -f "$${obj%.cmo}$$ext" ]; then \
				echo "$${obj%.cmo}.ml"; \
		    	fi; \
	            done; \
		done && \
		for obj in _dummy $(NAT_OBJECTS) $(NAT_EXEC_OBJECTS); do \
		    test "_dummy" != "$$obj" || continue; \
		    for ext in $(GENERATOR_EXTS); do \
		    	if [ -f "$${obj%.cmx}$$ext" ]; then \
				echo "$${obj%.cmx}.ml"; \
		    	fi; \
	            done; \
		done; \
	    } | sort | uniq \
        ) && \
        { test -z "$$targets" || $(MAKE) -f $(MFNAME) $$targets; }

# The following rule calls ocamldep for the right files, and creates 
# a file that consists of the contents of this Makefile, and of the output
# of ocamldep.

.PHONY: _makemake
_makemake: _generator
	@echo "<Analyzing dependencies and creating $(MF2NAME)>"
	cat $(MFNAME) >$(MF2NAME)
	test -z "$(MAKEMAKE_HOOK)" || $(MAKE) -f $(MFNAME) $(MAKEMAKE_HOOK)
	echo "# ---------------------------------------- dependencies:" >>$(MF2NAME)
	targets=$$( \
	    { \
		nat=-native-filter && \
		byte=-bytecode-filter && \
		for obj in _dummy $(BYTE_OBJECTS); do \
		    test "_dummy" != "$$obj" || continue; \
		    echo "$${obj%.cmo}.ml"; \
		    echo "$${obj%.cmo}.mli"; \
		    nat=""; \
		done && \
		for obj in _dummy $(NAT_OBJECTS); do \
		    test "_dummy" != "$$obj" || continue; \
		    echo "$${obj%.cmx}.ml"; \
		    echo "$${obj%.cmx}.mli"; \
		    byte=""; \
		done; \
		echo "$$byte $$nat"; \
	    } | sort | uniq \
        ) && \
	$(TASKDEP) $$targets >>$(MF2NAME)
## The following section is appended to _makemake for every executable:
[makemake_exec]
	echo "# --- dependencies for [execname]:" >>$(MF2NAME)
	$(TASKDEP) [switches] [deptargets] >>$(MF2NAME)
## Begin next section immediately to avoid empty lines:
[dummy]

[byte]


.PHONY: byte
byte: _byte

.PHONY: _byte
_byte: _makemake
	@echo "<Starting with bytecode targets>"
	if [ -n "$(BYTE_ARCHIVE)" ]; then \
	    $(MAKE) -f $(MF2NAME) $(BYTE_ARCHIVE); \
	fi
	if [ -n "$(BYTE_EXEC_TARGETS)" ]; then \
	    $(MAKE) -f $(MF2NAME) $(BYTE_EXEC_TARGETS); \
	fi
	@echo "<Done bytecode targets>"


[opt]
.PHONY: opt
opt: _opt

.PHONY: _opt
_opt: _makemake
	@echo "<Starting with native targets>"
	if [ -n "$(NAT_ARCHIVE)" ]; then \
	    $(MAKE) -f $(MF2NAME) $(NAT_ARCHIVE); \
	fi
	if [ -n "$(NAT_EXEC_TARGETS)" ]; then \
	    $(MAKE) -f $(MF2NAME) $(NAT_EXEC_TARGETS); \
	fi
	@echo "<Done native targets>"


[byte_archive]
$(BYTE_ARCHIVE): $(BYTE_OBJECTS)
	@echo "<Making $(BYTE_ARCHIVE)>"
	$(TASKBYTEAR) -o $(BYTE_ARCHIVE) $(BYTE_OBJECTS)


[native_archive]
$(NAT_ARCHIVE): $(NAT_OBJECTS)
	@echo "<Making $(NAT_ARCHIVE)>"
	$(TASKNATAR) -o $(NAT_ARCHIVE) $(NAT_OBJECTS)


## The following section is included for every bytecode executable again.

[byte_exec]
[execname]: $(BYTE_ARCHIVE) [execobjs]
	@echo "<Making [execname]>"
	$(TASKBYTELINK) -o [execname] $(BYTE_ARCHIVE) [execobjs]


[nat_exec]
[execname]: $(NAT_ARCHIVE) [execobjs]
	@echo "<Making [execname]>"
	$(TASKNATLINK) -o [execname] $(NAT_ARCHIVE) [execobjs]


[clean]
.PHONY: clean
clean:
	@echo "<Cleaning up>"
	touch $(TEMPNAME)
	rm -f $(BYTE_FILES) $(NAT_FILES) $(BYTE_EXEC_FILES) $(NAT_EXEC_FILES)
	rm -f $(MF2NAME)
	cat $(TEMPNAME) | xargs rm -f
	rm -f $(TEMPNAME)

.PHONY: CLEAN
CLEAN: clean

.PHONY: distclean
distclean: clean


[install]
.PHONY: install
install: $(INSTALL)

.PHONY: _findlib_install
_findlib_install:
	@echo "<Installing>"
	files=$$( \
	    for f in $(BYTE_INST) $(NAT_INST) $(BYTE_EXEC_INST) $(NAT_EXEC_INST) $(OTHER_INST); do \
	        if [ -f "$$f" ]; then echo $$f; fi; \
	    done; \
        ) && \
	$(TASKINSTALL) $$files

.PHONY: uninstall
uninstall: $(UNINSTALL)

.PHONY: _findlib_uninstall
_findlib_uninstall:
	@echo "<Uninstalling>"
	$(TASKREMOVE)

# The following rules just print some variables.

.PHONY: _print_name
_print_name:
	echo "$(NAME)"

.PHONY: _print_version
_print_version:
	echo "$(VERSION)"

[local]
# ----------------------------------------------------------------------
# Local additions
# ----------------------------------------------------------------------

[trailer]
## ======================================================================
## History:
## 
## $Log: make_wizard.pattern,v $
## Revision 1.2  2003/01/13 00:37:45  gerd
## 	Bugfix NATIVE_ARCHIVE ==> NAT_ARCHIVE (reported by
## Matt Gushee)
##
## Revision 1.1  2002/05/26 14:09:07  gerd
## 	Renaming
##
## Revision 1.1  2002/05/05 20:40:26  gerd
## 	Initial revision
##
## 
