# OMake configuration and custom rules.

open build/C
open build/OCaml
DefineCommandVars()

OCAML_LIBRARY_DIR = $(shell $(OCAMLC) -where)

#
# Functions to read compilation directives from source files.
#

GetPP(file) =
  PP =
  awk($(file))
  case $"^[(][*]\(pp\) \(.*\)[*][)]"
    if $(OCAMLFIND)
      PP = -syntax camlp4o $(mapprefix -ppopt,$2)
      export
    else
      PP = -pp "camlp4o pa_ulex.cma $2"
      export
    export
  value $(PP)

#
# Next, some rules modified from the original OMakeroot.src.
#

%.cmx: %.ml
    section rule
        if $(not $(NATIVE_ENABLED))
            eprintln(!!! You are trying to build OCaml native code file: %.cmx)
            eprintln(!!! However\, the NATIVE_ENABLED flag is not set.)
            eprintln(!!! Include the following definition in your OMakefile)
            eprintln(!!! if you really want to build this file.)
            eprintln(NATIVE_ENABLED = true)
            exit(1)
        if $(target-exists %.mli)
            %.cmx %$(EXT_OBJ): %.ml %.cmi :scanner: scan-ocaml-%.ml
                $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                        $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
        else
            if $(BYTE_ENABLED)
                %.cmx %.cmi %$(EXT_OBJ) %.cmo: %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)  \
                            $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
                    $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
            else
                %.cmx %.cmi %$(EXT_OBJ): %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)  \
                            $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<

%$(EXT_OBJ): %.ml
    section rule
        if $(not $(NATIVE_ENABLED))
            eprintln(!!! You are trying to build OCaml native code file: %$(EXT_OBJ))
            eprintln(!!! However\, the NATIVE_ENABLED flag is not set.)
            eprintln(!!! Include the following definition in your OMakefile)
            eprintln(!!! if you really want to build this file.)
            eprintln(NATIVE_ENABLED = true)
            exit(1)
        if $(target-exists %.mli)
            %$(EXT_OBJ) %.cmx: %.ml %.cmi :scanner: scan-ocaml-%.ml
                $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                        $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
        else
            if $(BYTE_ENABLED)
                %$(EXT_OBJ) %.cmi %.cmx %.cmo: %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
                    $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
            else
                %$(EXT_OBJ) %.cmi %.cmx: %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<

%.cmo: %.ml
    section rule
        if $(not $(BYTE_ENABLED))
            eprintln(!!! You are trying to build bytecode file: %.cmo)
            eprintln(!!! However\, the BYTE_ENABLED flag is not set.)
            eprintln(!!! Include the following definition in your OMakefile)
            eprintln(!!! if you really want to build this file.)
            eprintln(BYTE_ENABLED = true)
            exit(1)
        if $(target-exists %.mli)
            %.cmo: %.ml %.cmi :scanner: scan-ocaml-%.ml
                $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                        $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
        else
            if $(NATIVE_ENABLED)
                %.cmo %.cmi %.cmx %$(EXT_OBJ): %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
                    $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
            else
                %.cmo %.cmi: %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<

%.cmi: %.ml
    section rule
        if $(BYTE_ENABLED)
            if $(NATIVE_ENABLED)
                %.cmi %.cmo %.cmx %$(EXT_OBJ): %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
                    $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
            else
                %.cmi %.cmo: %.ml :scanner: scan-ocaml-%.ml
                    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                            $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<
        else
            %.cmi %.cmx %$(EXT_OBJ): %.ml :scanner: scan-ocaml-%.ml
                $(OCAMLFIND) $(OCAMLOPT) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
                        $(OCAMLOPTFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<

%.cmi: %.mli :scanner: scan-ocaml-%.mli
    $(OCAMLFIND) $(OCAMLC) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
        $(OCAMLCFLAGS) $(GetPP $<) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -c $<


.SCANNER: scan-ocaml-%.mli: %.mli OCamlGeneratedFilesTarget :value: $(OCamlScannerDeps $&)
    $(OCAMLFIND) $(OCAMLDEP) $(PREFIXED_OCAMLPACKS) $(OCAMLDEPFLAGS) $(GetPP $<) $(PREFIXED_OCAMLINCLUDES) $<

.SCANNER: scan-ocaml-%.ml: %.ml OCamlGeneratedFilesTarget :exists: %.mli :value: $(OCamlScannerDeps $&)
    $(OCAMLFIND) $(OCAMLDEP) $(PREFIXED_OCAMLPACKS) $(OCAMLDEPFLAGS) $(GetPP $<) $(PREFIXED_OCAMLINCLUDES) $<

OCamlProgram(name, files) =
   CMOFILES  = $(addsuffix .cmo, $(files))
   CMXFILES  = $(addsuffix .cmx, $(files))
   OFILES    = $(addsuffix $(EXT_OBJ),   $(files))

   CMAFILES  = $(addsuffix .cma,  $(OCAML_LIBS))
   CMXAFILES = $(addsuffix .cmxa, $(OCAML_LIBS))
   ARFILES   = $(addsuffix $(EXT_LIB), $(OCAML_LIBS))
   CMA_OTHER_FILES = $(addsuffix .cma, $(OCAML_OTHER_LIBS))
   CMXA_OTHER_FILES = $(addsuffix .cmxa, $(OCAML_OTHER_LIBS))

   BYTE_CLIBS = $(addsuffix $(EXT_LIB), $(OCAML_CLIBS))
   NATIVE_CLIBS = $(addsuffix $(EXT_LIB), $(OCAML_CLIBS))
   CLIBS = $(addsuffix $(EXT_LIB), $(LIBS))

   if $(NATIVE_ENABLED)
     BYTEPROG = $(file $(name).run)
     OPTPROG  = $(file $(name)$(EXE))
     export
   else
     BYTEPROG = $(file $(name)$(EXE))
     OPTPROG  = $(file $(name).opt)
     export

   #
   # Rules to build byte-code and native targets
   #
   $(BYTEPROG): $(CMAFILES) $(CMOFILES) $(BYTE_CLIBS) $(CLIBS)
        $(OCAMLFIND) $(OCAMLLINK) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) $(OCAMLCFLAGS)\
                $(PREFIXED_OCAMLINCLUDES) $(OCAML_BYTE_LINK_FLAGS)\
                -o $@ $(CMA_OTHER_FILES) $(CMAFILES) $(OCamlLinkSort $(CMOFILES))\
                $(BYTE_CLIBS) $(CLIBS) $(OCAML_LINK_FLAGS)

   $(OPTPROG): $(CMXAFILES) $(ARFILES) $(CMXFILES) $(OFILES) $(NATIVE_CLIBS) $(CLIBS)
        $(OCAMLFIND) $(OCAMLOPTLINK) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) $(OCAMLOPTFLAGS)\
                $(PREFIXED_OCAMLINCLUDES) $(OCAML_NATIVE_LINK_FLAGS)\
                -o $@ $(CMXA_OTHER_FILES) $(CMXAFILES) $(OCamlLinkSort $(CMXFILES))\
                $(NATIVE_CLIBS) $(CLIBS) $(OCAML_LINK_FLAGS)


#
# Finally, include the OMakefile in this directory.
#
.SUBDIRS: .
