# This file was edited by Valerio Bigiani, AKA The Bigg, starting from
# 30 december 2005. All changes for this file are listed in
# diffs/Makefile.ocaml.diff file, as the output of a diff -Bw -c -N command.

#*
#* Description:
#*
#* Copyright (c) 2000 by
#*  George C. Necula	necula@cs.berkeley.edu
#*   
#* All rights reserved.  Permission to use, copy, modify and distribute
#* this software for research purposes only is hereby granted, 
#* provided that the following conditions are met: 
#* 1.  Redistributions of source code must retain the above copyright notice, 
#* this list of conditions and the following disclaimer. 
#* 2. Redistributions in binary form must reproduce the above copyright 
#* notice, this list of conditions and the following disclaimer in the 
#* documentation and/or other materials provided with the distribution. 
#* 3. The name of the authors may not be used to endorse or promote products 
#* derived from this software without specific prior written permission. 
#*
#* DISCLAIMER:
#* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 
#* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
#* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
#* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
#* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
#* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
#* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
#* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
#* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#*
#*

  # Generic Makefile for Ocaml projects
  # Written by necula@cs.berkeley.edu
  # 
  # Features: 
  #   - keeps byproducts of building in a separate directory
  #   - handles dependencies automatically
  #   - user specifies just what modules go into a project and 
  #     everything else is done automatically
  #   - you can use one Makefile for several Ocaml projects
  #   
  # You must include this file in your Makefile. Before the include point 
  # you must defined the following variables (which are glob al for all Ocaml 
  # projects specified in one Makefile):
  # 
  # OBJDIR     - the directory where to put all object files. This directory 
  #              must exist (default obj)
  # DEPENDDIR  - the directory where to put dependency files. This directory 
  #              must exist.  (default obj/.depend)
  # NATIVECAML - if set then will use the native compiler
  # UNSAFE     - if set then will turn off safety checks (only with NATIVECAML)

  # MODULES    - a list of all modules for all projects defined in the 
  #              Makefile. Give only the basenames (no directory,
  #              no extension).  This is used to create the dependencies.
  # SOURCEDIRS - a list of all directories containing sources for all 
  #              projects defined in a Makefile. This is used to set vpath.
  # MLLS       - a list of all .mll (ocamllex input) files for all 
  #              projects defined in the Makefile. 
  # MLYS       - a list of all .mly (ocamlyacc input) files for all 
  #              projects defined in the Makefile. 
  # ECHO       - if specifically set to nothing then it will print 
  #              all of the commands issued. Set this in the command line
  #              if you want to see what is going on.
  #
  # After you set all of the above you must do the following for EACH separate 
  # executable that you want to build.
  #
  # Define the following:
  # PROJECT_EXECUTABLE - the name of the executable you want to build. To take 
  #                      advantage of the naming scheme that separates the 
  #                      bytecode version and the native version, use the 
  #                      $(EXE) variable which is defined to either .byte.exe 
  #                      or .asm.exe. I typically put the executable in 
  #                      $(OBJDIR) as well.
  # PROJECT_MODULES    - the base names of the modules that make this 
  #                      executable in the order in which they must be
  #                      passed to the linker. Make sure that all of
  #                      the names mentioned here are also mentioned in 
  #                      MODULES.
  # PROJECT_CMODULES   - same as modules but for the C modules. These
  #                      do not need to be mentioned in MODULES
  # PROJECT_LIBS       - the base names of the libraries that you 
  #                      want to link in the executable.
  #
  #
  # Then include Makefile.ocaml.build to generate a customized
  # rule for making your executable.
  #
  # Example:
  # 
  # OBJDIR     = obj
  # DEPENDDIR  = obj/.depend
  # SOURCEDIRS = src src/special
  # MLLS       = mylex 
  # MLYS       = myparse
  #
  # MODULES    = mod11 mod12 mod21 modcommon
  #
  #  # Rules for project 1
  # PROJECT_EXECUTABLE = $(OBJDIR)/proj1$(EXE)
  # PROJECT_MODULES    = mod11 mod12 modcommon
  # PROJECT_CMODULES   =  
  # PROJEC_LIBS        = unix
  # include Makefile.ocaml.build
  #
  #
  #  # Rules for project 2 
  # PROJECT_EXECUTABLE = $(OBJDIR)/proj2$(EXE)
  # PROJECT_MODULES    = mod21 modcommon
  # PROJECT_CMODULES   =  
  # PROJEC_LIBS        = unix str
  # include Makefile.ocaml.build

CAMLLEX = $(OCAMLDIR)/ocamllex
CAMLYACC= $(OCAMLDIR)/ocamlyacc
CAMLDEP = $(OCAMLDIR)/ocamldep
ELKHOUND= $(shell which $(ELKHOUND_BIN))

CAMLFLAGS    =-I $(OBJDIR)

# sm: two styles for echoing compilation progress:
#   style 1, by George:
#     - print English descriptions of what's happening
#     - set ECHO to "" to see *everything*
#   style 2, by Scott:
#     - do not print English descriptions
#     - print every shell command that is executed which has a side effect,
#       so that they could be pasted into a shell to reproduce manually
#     - omit some of the details of dependency generation
#
# to be able to choose which style, several variables are used:
#   @$(NARRATIVE)  - put this before English descriptions for style 1
#   @$(COMMAND)    - put this before shell commands which are to be
#                    printed for style 2; the command is *not* executed
#   $(AT)          - put this before shell commands which are to be executed,
#                    and also printed in style 2
#   $(ECHO)        - use in place of '@' for things not printed in either style
ifdef ECHOSTYLE_SCOTT
  # 'true' silently consumes its arguments, whereas 'echo' prints them
  NARRATIVE   := true
  COMMAND     := echo
  AT          := 
  ECHO        := @
else
  NARRATIVE   := echo
  COMMAND     := true
  # change these next two definitions to <empty> to echo everything,
  # or leave as @ to suppress echoing
  AT          := @
  ECHO        := @
endif

ifdef PROFILE
# NATIVECAML	= 1
 CAMLC          = $(OCAMLDIR)/ocamlopt$(USEOPT) -p $(COMPILEFLAGS)
 CAMLLINK       = $(OCAMLDIR)/ocamlopt$(USEOPT) -p $(LINKFLAGS)
 CMO            = cmx
 CMXA           = cmxa
 EXEEXT         = .asm
 MOVEAFTERCAMLC = cmi cmx $(OBJEXT)
 MOVEAFTERCAMLCF= cmi $(OBJEXT)
else
ifdef NATIVECAML
 #foo := $(shell echo "I am in NATIVECAML mode" >&2; echo whatever)
 CAMLC          = $(OCAMLDIR)/ocamlopt$(USEOPT) -unsafe-string $(COMPILEFLAGS)
 CAMLLINK       = $(OCAMLDIR)/ocamlopt$(USEOPT) -unsafe-string $(LINKFLAGS)
 CMO            = cmx
 CMXA           = cmxa
 EXEEXT         = .asm
 MOVEAFTERCAMLC = cmi cmx $(OBJEXT)
 MOVEAFTERCAMLCF= cmi $(OBJEXT)
 COMPILETOWHAT  = native code
 # sm: by adding -native in native mode, we prevent spurious
 # dependencies on .cmo files which were causing lots of
 # extra recompilation
 CAMLDEP        = $(OCAMLDIR)/ocamldep -native
else 
 CAMLC          = $(OCAMLDIR)/ocamlc -g $(COMPILEFLAGS)
 CAMLLINK       = $(OCAMLDIR)/ocamlc -custom -g $(LINKFLAGS)
 CMO            = cmo
 CMXA           = cma
 EXEEXT         = .asm
 MOVEAFTERCAMLC = cmi cmo
 MOVEAFTERCAMLCF= cmi        # sm: 'F' for failed -- cmo isn't created
 COMPILETOWHAT  = bytecode
endif
endif

ifdef UNSAFE 
 CAMLC          := $(CAMLC) -unsafe -noassert
endif


EXE		= $(EXEEXT).exe
OBJ   	= o

export EXE



    # Allow searching for .ml and .mli
vpath %.mll $(SOURCEDIRS)
vpath %.mly $(SOURCEDIRS)
vpath %.ml  $(SOURCEDIRS) $(OBJDIR)
vpath %.mli $(SOURCEDIRS) $(OBJDIR)
vpath %.c   $(SOURCEDIRS)
vpath %.gr  $(SOURCEDIRS)


#  Secondaries are intermediates that we don't want make to delete
#  By giving the right names to secondary files we tell make where to make
#  them if they are not already made. VERY USEFUL!!
.SECONDARY : $(MLLS:%.mll=$(OBJDIR)/%.ml) $(MLYS:%.mly=$(OBJDIR)/%.ml) \
             $(MLYS:%.mly=$(OBJDIR)/%.mli) $(GRS:%.gr=$(OBJDIR)/%.ml) \
             $(GRS:%.gr=$(OBJDIR)/%.mli)

             # Run the lexer generator
             # Move the result to the OBJDIR directory
             # If there is a .mli file in the same directory with .mll then
             # copy it to OBJDIR (where the .ml) file will live.
$(OBJDIR)/%.ml: %.mll
	$(CAMLLEX) $<
	$(AT)mv -f $(basename $<).ml $(OBJDIR)
	$(ECHO)if test -f $(basename $<).mli ;then \
	  $(COMMAND) cp -f $(basename $<).mli $(OBJDIR); \
	  cp -f $(basename $<).mli $(OBJDIR) \
        ;fi

             # Run the parser generator
             # Move the result to the $(OBJDIR) directory.
$(OBJDIR)/%.ml $(OBJDIR)/%.mli: %.mly
	$(CAMLYACC) $(CAMLYACCFLAGS) $<
	$(AT)mv -f $(basename $<).ml $(basename $<).mli $(OBJDIR)

             # Run the parser generator
             # Move the result to the $(OBJDIR) directory.
$(OBJDIR)/%.ml $(OBJDIR)/%.mli: %.gr
	$(ELKHOUND) -ocaml $<
	$(AT)mv -f $(basename $<).ml $(basename $<).mli $(OBJDIR)

         # Compile an MLI file. After compilation move the result to OBJDIR
$(OBJDIR)/%.cmi: %.mli
	@$(NARRATIVE) Compiling interface $<
	$(AT)$(CAMLC) $(CAMLFLAGS) -c $<
	$(ECHO)if test $(OBJDIR) != $(<D) ;then \
                   $(COMMAND) mv -f $(basename $<).cmi $(OBJDIR); \
                   mv -f $(basename $<).cmi $(OBJDIR) \
        ;fi

         # Compile an ML file. Before invoking CAMLC we copy to the source
         # directory the .cmi file (if one exists). After compilation we 
         # copy to $(OBJDIR) the .cmi and the result of compilation.
$(OBJDIR)/%.$(CMO): %.ml
	@$(NARRATIVE) "Compiling $< to $(COMPILETOWHAT)"
	$(ECHO)if test $(OBJDIR) != $(<D) ;then \
                 if test -f $(OBJDIR)/$(*F).cmi ;then \
                      $(COMMAND) cp -f $(OBJDIR)/$(*F).cmi $(<D); \
                      cp -f $(OBJDIR)/$(*F).cmi $(<D) \
                 ;fi \
        ;fi
	@$(COMMAND) $(CAMLC) $(CAMLFLAGS) -c $<
	$(ECHO)if $(CAMLC) $(CAMLFLAGS) -c $<  ;then \
	   if test $(OBJDIR) != $(<D) ;then \
              if test -f $(basename $<).cmi ;then \
                $(COMMAND) mv -f $(foreach ext,$(MOVEAFTERCAMLC), $(basename $<).$(ext)) $(OBJDIR); \
                mv -f $(foreach ext,$(MOVEAFTERCAMLC), $(basename $<).$(ext)) \
                      $(OBJDIR) \
              ;fi \
           ;fi ; exit 0 \
        ;else \
	   if test $(OBJDIR) != $(<D) ;then \
                $(COMMAND) cp -f $(foreach ext,$(MOVEAFTERCAMLCF), $(basename $<).$(ext)) $(OBJDIR); \
                cp -f $(foreach ext,$(MOVEAFTERCAMLCF), $(basename $<).$(ext)) \
                      $(OBJDIR) \
           ;fi ; exit 1 \
        ;fi 

             # Compile C files
             # They appear to be left in the current directory
$(OBJDIR)/%.$(OBJEXT): %.c
	@$(NARRATIVE) Compiling C file $<
	$(AT)$(CAMLC) -verbose $(CAMLFLAGS) -c $<
	$(AT)mv -f $(basename $(notdir $<)).$(OBJEXT) $(OBJDIR)

      # This is a generic function that builds your project
      # See start of this file for usage instructions
      # 
# 
#	Phonies should be "remade" even if someone mistakenly creates them
.PHONY: cleancaml
cleancaml:
	-find $(OBJDIR) \( \
		-name '*.cmi' -o \
		-name '*.cmo' -o \
                -name '*.cmx' -o \
		-name '*.cma' -o \
		-name '*.cmxa' -o \
		-name '*.exe' -o \
		-name '*.o' -o \
		-name '*.obj' \
	\) -exec rm {} \;
	-rm -f $(DEPENDDIR)/*.d $(DEPENDDIR)/*.di
	-rm -f $(MLLS:%.mll=$(OBJDIR)/%.ml) \
               $(MLLS:%.mll=$(OBJDIR)/%.mli) \
               $(MLYS:%.mly=$(OBJDIR)/%.ml) \
               $(MLYS:%.mly=$(OBJDIR)/%.mli) \
               $(GRS:%.gr=$(OBJDIR)/%.ml) \
               $(GRS:%.gr=$(OBJDIR)/%.mli)


# Automatic dependency generation (see GNU info for details)
#
# Each .ml file has a .d (dependency file) which is automatically
# generated and included by the rules below.  The perl script replaces
# directory paths with $(OBJDIR)/
#
# Dependencies for .mli files reside in corresponding .di files.
#

FIXDEPEND:=perl -e 'while(<>) { s%[^/\\ :]+[/\\]% %g; s%([^ :\\\n\r]+)%$(OBJDIR)/$$1%g; print $$_;}'

# This sed substitution is valid for GNU sed but not for BSD sed (and
# probably not POSIX). \r is not a recognised control character.
# FIXDEPEND:=sed -e '{ s%[^/\\ :][^/\\ :]*[/\\]% %g; s%\([^ :\\\n\r][^ :\\\n\r]*\)%$(OBJDIR)/\1%g; }'

# FIXDEPEND:=cat
DEPINCLUDES= -I $(OBJDIR) $(SOURCEDIRS:%=-I %)
$(DEPENDDIR)/%.d: %.ml
	@mkdir -p obj/.depend obj/x86_LINUX obj/X86_WIN32
	@$(NARRATIVE) Generating dependency information for $<
	@$(COMMAND) $(CAMLDEP) $(DEPINCLUDES) $<
	$(ECHO)$(CAMLDEP) $(DEPINCLUDES) $< | $(FIXDEPEND) > $@

$(DEPENDDIR)/%.di: %.mli
	@$(NARRATIVE) Generating dependency information for $<
	@$(COMMAND) $(CAMLDEP) $(DEPINCLUDES) $<
	$(ECHO)$(CAMLDEP) $(DEPINCLUDES) $< | $(FIXDEPEND) > $@

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),doc)
ifneq ($(MAKECMDGOALS),src_zip)
-include $(MODULES:%=$(DEPENDDIR)/%.d)
-include $(MODULES:%=$(DEPENDDIR)/%.di)
endif
endif
endif
