## $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
##
##