Makefile 8.39 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
.PHONY: clean

COLD         += clean

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

# A few settings differ on Windows versus Unix.

include ../Makefile.arch

# ----------------------------------------------------------------------------
# Locating the ocaml compilers.
# If ocamlfind is available, then it is used for that purpose.

CAMLTOP         := ocaml

CAMLC           := $(shell if ocamlfind ocamlc -v >/dev/null 2>&1 ; \
                       then echo ocamlfind ocamlc ; \
		       elif ocamlc.opt -v >/dev/null 2>&1 ; \
                       then echo ocamlc.opt ; \
		       else echo ocamlc ; fi)

CAMLOPT         := $(shell if ocamlfind ocamlopt -v >/dev/null 2>&1 ; \
                       then echo ocamlfind ocamlopt ; \
		       elif ocamlopt.opt -v >/dev/null 2>&1 ; \
                       then echo ocamlopt.opt ; \
		       else echo ocamlopt ; fi)

CAMLDEP         := $(shell if ocamlfind ocamldep -version >/dev/null 2>&1 ; \
                       then echo ocamlfind ocamldep ; \
		       elif ocamldep.opt -version >/dev/null 2>&1 ; \
                       then echo ocamldep.opt ; \
		       else echo ocamldep ; fi)

CAMLDEPWRAPPER  := ../demos/ocamldep.wrapper

CAMLLEX         := ocamllex

CAMLYACC        := ocamlyacc -v

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

# Compilation flags.

BFLAGS       := -g
OFLAGS       := -inline 1000
LNKBFLAGS    := -g
LNKOFLAGS    :=
BLIBS        := unix.cma
OLIBS        := unix.cmxa
PGFLAGS      := -v -lg 1 -la 1 -lc 1 --comment --infer --error-recovery --stdlib . --strict

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

# A list of the source files that must be generated prior to dependency
# analysis.

GENERATED := installation.ml lexmli.ml lexer.ml parser.mli parser.ml		\
lineCount.ml lexdep.ml sentenceParser.mli sentenceParser.ml sentenceLexer.ml

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

# A list of the modules that must be linked into the MenhirLib library.

# This library is used both at compile time (i.e., within Menhir itself)
# and at run time (i.e., it is made available to Menhir users, who need
# to link it with their own executables if they have used the --table
# option).

# If you change this list, please also update the files LICENSE and
# GNUmakefile in the toplevel directory.

LIBMODULES := infiniteArray packedIntArray rowDisplacement engineTypes	\
engine tableFormat tableInterpreter convert

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

# A list of the modules that must be linked into the Menhir executable.

MODULES := menhirLib Fix stringSet stringMap mark compressedBitSet	\
           unionFind tarjan patricia misc option	\
           breadth listMonad dot installation version settings time	\
           positions error parameters keyword lineCount printer		\
           action parserAux parser lexer partialGrammar	\
           parameterizedGrammar reachability unparameterizedPrinter	\
           preFront codeBits tokenType interface IO lexmli lexdep	\
           infer nonTerminalDefinitionInlining front grammar item lr0	\
           slr lr1 lr1partial derivation conflict invariant codePieces	\
           sentenceParser sentenceLexer pprint cst			\
           referenceInterpreter interpret tableBackend codeBackend	\
           coqBackend traverse inliner back

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

# How to bootstrap.

# Set TARGET to byte or opt depending on the desired architecture.

ifndef TARGET
  TARGET     := opt
endif

# The variable GOAL is the name of the executable file.

GOAL         := menhir.$(TARGET)

# We create a symbolic link of GOAL to MENHIREXE.

$(MENHIREXE): .versioncheck
# Build a stage one executable using ocamlyacc.
	$(MAKE) -s PGEN="$(CAMLYACC)" PARSER=parser $(GOAL)
# Remove the ocamlyacc-built parser.
	@/bin/rm -f parser.ml parser.mli
# Build a stage two executable using the stage one executable (which is overwritten).
	$(MAKE) -s PGEN="./$(GOAL) $(PGFLAGS)" PARSER=fancy-parser $(GOAL)
# Create a stage three parser and make sure that it is identical.
	@./$(GOAL) $(PGFLAGS) -b reference fancy-parser.mly 2>/dev/null
	@if diff parser.mli reference.mli 2>&1 >/dev/null ; then \
	  if diff parser.ml reference.ml 2>&1 >/dev/null ; then \
	    echo "Bootstrap successful." ; \
	  else \
	    echo "Bootstrap FAILED: the implementation files differ." && false ; \
          fi ; \
	else \
	  echo "Bootstrap FAILED: the interface files differ." && false ; \
	fi
	@rm -f reference.ml reference.mli
# Rename the stage two executable to the desired name.
# Use a symbolic link, so that further development builds implicitly update
# menhir.
	@ln -sf $(GOAL) $@

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

# Linking.

menhirLib.cmo menhirLib.cmi: $(LIBMODULES:=.cmo)
	$(CAMLC) $(BFLAGS) -pack -o menhirLib.cmo $^

menhirLib.cmx menhirLib.o: $(LIBMODULES:=.cmx)
	$(CAMLOPT) -pack -o menhirLib.cmx $^

menhir.byte: $(MODULES:=.cmo)
	$(CAMLC) -o $@ $(LNKBFLAGS) $(BLIBS) $^

menhir.opt: $(MODULES:=.cmx)
	$(CAMLOPT) -o $@ $(LNKOFLAGS) $(OLIBS) $^

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

# Computing dependencies. This can be done in a simple way, even though
# we exploit --infer, because we compile in two stages. Not a good example
# of how to do it yourself -- have a look at demos/Makefile.shared.

# For completeness, we must force ocamldep to understand that MenhirLib
# is a module name. We do this by creating phantom source files for it.

.depend: $(wildcard *.ml *.mli) $(GENERATED)
	@/bin/rm -f .depend
	for i in *.ml *.mli; do \
           $(CAMLDEPWRAPPER) menhirLib.ml menhirLib.mli - $(CAMLDEP) $$i \
        >> $@; \
	done

ifeq ($(findstring $(MAKECMDGOALS),$(COLD)),)
-include .depend
endif

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

# Cleaning up.

clean::
	/bin/rm -f menhir.byte menhir.opt $(MENHIREXE)
	/bin/rm -f *.cmi *.cmx *.cmo *.$(OBJ) *~ .*~
	/bin/rm -f reference.ml reference.mli $(GENERATED)
	/bin/rm -f .depend *.conflicts *.automaton *.annot *.output

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

# Compiling. The parser source is found in $(PARSER).mly and is
# processed using $(PGEN).

# These two default definitions really shouldn't be necessary, but
# there are corner cases where they are needed (e.g. when make is
# invoked without a target and the .depend file is regenerated).

ifndef PGEN
  PGEN       := $(CAMLYACC)
endif
ifndef PARSER
  PARSER     := parser
endif

%.cmi: %.mli
	$(CAMLC) $(BFLAGS) -c $<

%.cmo: %.ml
	$(CAMLC) $(BFLAGS) -c $<

# If the module that is being compiled is part of MenhirLib, add the
# -for-pack option to the command line. This is required only when
# compiling to native code (the bytecode compiler accepts but ignores
# this option).

PACK = $(shell if echo $(LIBMODULES) | grep $* >/dev/null ; then echo -for-pack MenhirLib ; else echo ; fi)

%.cmx %.o: %.ml
	$(CAMLOPT) $(OFLAGS) $(PACK) -c $<

# The source file for this parser varies. It is either parser.mly or
# fancy-parser.mly.
#
parser.ml parser.mli: $(PARSER).mly
	@/bin/rm -f parser.ml parser.mli
	$(PGEN) -b parser $<

# This parser must be built with ocamlyacc, because its client
# watches for Parsing.Parse_error!
#
# Using ocamlyacc or Menhir interchangeably would be possible,
# via an ocamlyacc wrapper that adds the definition "exception
# Error = Parsing.Parse_error" at the end of the generated .ml
# and .mli files.
#
sentenceParser.ml sentenceParser.mli : sentenceParser.mly
	@/bin/rm -f sentenceParser.ml sentenceParser.mli
	$(CAMLYACC) -b sentenceParser $<

%.ml: %.mll
	@/bin/rm -f $@
	$(CAMLLEX) $<

# ----------------------------------------------------------------------------
# Checking the version of the ocaml compiler.
#
# We check the bytecode compiler only, because some architectures don't have
# the native code compiler. We assume that both compilers, if present, are in
# sync.

# We build a bytecode executable (rather than use the toplevel loop) because
# we need to load str.cma and some ocaml ports do not support dynamic loading
# (e.g. ocaml 3.09, MacOS/Intel).

.versioncheck:
	@ echo Checking that Objective Caml is recent enough...
	@ $(CAMLC) -o check-ocaml-version str.cma checkOCamlVersion.ml
	@ ./check-ocaml-version --verbose --gt "3.09"
	@ rm check-ocaml-version
	@ touch .versioncheck

clean::
	rm -f .versioncheck