##===- bindings/ocaml/Makefile.ocaml -----------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## # # An OCaml library is a unique project type in the context of LLVM, so rules are # here rather than in Makefile.rules. # # Reference materials on installing OCaml libraries: # # https://fedoraproject.org/wiki/Packaging/OCaml # http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt # ##===----------------------------------------------------------------------===## include $(LEVEL)/Makefile.config # CFLAGS needs to be set before Makefile.rules is included. CXX.Flags += -I"$(shell $(OCAMLC) -where)" C.Flags += -I"$(shell $(OCAMLC) -where)" include $(LEVEL)/Makefile.common # Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the # user can override this with OCAML_LIBDIR or configure --with-ocaml-libdir=. PROJ_libocamldir := $(DESTDIR)$(OCAML_LIBDIR) OcamlDir := $(LibDir)/ocaml # Info from llvm-config and similar ifndef IS_CLEANING_TARGET ifdef UsedComponents UsedLibs = $(shell $(LLVM_CONFIG) --libs $(UsedComponents)) UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents)) endif endif # Tools OCAMLCFLAGS += -I $(ObjDir) -I $(OcamlDir) ifndef IS_CLEANING_TARGET ifneq ($(ObjectsO),) OCAMLAFLAGS += $(patsubst %,-cclib %, \ $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \ $(shell $(LLVM_CONFIG) --ldflags)) \ $(UsedLibs)) else OCAMLAFLAGS += $(patsubst %,-cclib %, \ $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags)) \ $(UsedLibs)) endif endif # -g was introduced in 3.10.0. #ifneq ($(ENABLE_OPTIMIZED),1) # OCAMLDEBUGFLAG := -g #endif Compile.CMI := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) Compile.CMO := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ -o) Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) ifdef OCAMLOPT Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamlLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) else Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o) endif # Source files ifndef OcamlSources1 OcamlSources1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.ml)) endif ifndef OcamlHeaders1 OcamlHeaders1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.mli)) endif OcamlSources2 := $(filter-out $(ExcludeSources),$(OcamlSources1)) OcamlHeaders2 := $(filter-out $(ExcludeHeaders),$(OcamlHeaders1)) OcamlSources := $(OcamlSources2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) OcamlHeaders := $(OcamlHeaders2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) # Intermediate files ObjectsCMI := $(OcamlSources:%.ml=%.cmi) ObjectsCMO := $(OcamlSources:%.ml=%.cmo) ObjectsCMX := $(OcamlSources:%.ml=%.cmx) ifdef LIBRARYNAME LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa endif ifdef TOOLNAME ToolEXE := $(ObjDir)/$(TOOLNAME)$(EXEEXT) endif # Output files # The .cmo files are the only intermediates; all others are to be installed. OutputsCMI := $(ObjectsCMI:$(ObjDir)/%.cmi=$(OcamlDir)/%.cmi) OutputsCMX := $(ObjectsCMX:$(ObjDir)/%.cmx=$(OcamlDir)/%.cmx) OutputLibs := $(UsedLibNames:%=$(OcamlDir)/%) ifdef LIBRARYNAME LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma) OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa) endif ifdef TOOLNAME ifdef EXAMPLE_TOOL OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT) else OutputEXE := $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT) endif endif # Installation targets DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%) ifdef LIBRARYNAME DestA := $(PROJ_libocamldir)/lib$(LIBRARYNAME).a DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa endif ##===- Dependencies -------------------------------------------------------===## # Copy the sources into the intermediate directory because older ocamlc doesn't # support -o except when linking (outputs are placed next to inputs). $(ObjDir)/%.mli: $(PROJ_SRC_DIR)/%.mli $(ObjDir)/.dir $(Verb) $(CP) -f $< $@ $(ObjDir)/%.ml: $(PROJ_SRC_DIR)/%.ml $(ObjDir)/.dir $(Verb) $(CP) -f $< $@ $(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi) ifdef LIBRARYNAME $(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ $(OcamlDir)/.dir $(ObjDir)/.dir $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ -include $(ObjDir)/$(LIBRARYNAME).ocamldep endif ifdef TOOLNAME $(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ $(OcamlDir)/.dir $(ObjDir)/.dir $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ -include $(ObjDir)/$(TOOLNAME).ocamldep endif ##===- Build static library from C sources --------------------------------===## ifdef LibraryA all-local:: $(LibraryA) clean-local:: clean-a install-local:: install-a uninstall-local:: uninstall-a $(LibraryA): $(ObjectsO) $(OcamlDir)/.dir $(Echo) "Building $(BuildMode) $(notdir $@)" -$(Verb) $(RM) -f $@ $(Verb) $(Archive) $@ $(ObjectsO) $(Verb) $(Ranlib) $@ clean-a:: -$(Verb) $(RM) -f $(LibraryA) install-a:: $(LibraryA) $(Echo) "Installing $(BuildMode) $(DestA)" $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) $(INSTALL) $(LibraryA) $(DestA) $(Verb) uninstall-a:: $(Echo) "Uninstalling $(DestA)" -$(Verb) $(RM) -f $(DestA) endif ##===- Deposit dependent libraries adjacent to Ocaml libs -----------------===## all-local:: build-deplibs clean-local:: clean-deplibs install-local:: install-deplibs uninstall-local:: uninstall-deplibs build-deplibs: $(OutputLibs) $(OcamlDir)/%.a: $(LibDir)/%.a $(Verb) ln -sf $< $@ $(OcamlDir)/%.o: $(LibDir)/%.o $(Verb) ln -sf $< $@ clean-deplibs: $(Verb) $(RM) -f $(OutputLibs) install-deplibs: $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) for i in $(DestLibs:$(PROJ_libocamldir)/%=%); do \ ln -sf "$(PROJ_libdir)/$$i" "$(PROJ_libocamldir)/$$i"; \ done uninstall-deplibs: $(Verb) $(RM) -f $(DestLibs) ##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## ifneq ($(OcamlHeaders),) all-local:: build-cmis clean-local:: clean-cmis install-local:: install-cmis uninstall-local:: uninstall-cmis build-cmis: $(OutputsCMI) $(OcamlDir)/%.cmi: $(ObjDir)/%.cmi $(OcamlDir)/.dir $(Verb) $(CP) -f $< $@ $(ObjDir)/%.cmi: $(ObjDir)/%.mli $(ObjDir)/.dir $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" $(Verb) $(Compile.CMI) $@ $< clean-cmis:: -$(Verb) $(RM) -f $(OutputsCMI) # Also install the .mli's (headers) as documentation. install-cmis: $(OutputsCMI) $(OcamlHeaders) $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ $(DataInstall) $(ObjDir)/$$i "$(PROJ_libocamldir)/$$i"; \ done $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ done uninstall-cmis:: $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ $(RM) -f "$(PROJ_libocamldir)/$$i"; \ done $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ $(RM) -f "$(PROJ_libocamldir)/$$i"; \ done endif ##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===## $(ObjDir)/%.cmo: $(ObjDir)/%.ml $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" $(Verb) $(Compile.CMO) $@ $< ifdef LIBRARYNAME all-local:: $(OutputCMA) clean-local:: clean-cma install-local:: install-cma uninstall-local:: uninstall-cma $(OutputCMA): $(LibraryCMA) $(OcamlDir)/.dir $(Verb) $(CP) -f $< $@ $(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" $(Verb) $(Archive.CMA) $@ $(ObjectsCMO) clean-cma:: $(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%) install-cma:: $(OutputCMA) $(Echo) "Installing $(BuildMode) $(DestCMA)" $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) $(DataInstall) $(OutputCMA) "$(DestCMA)" uninstall-cma:: $(Echo) "Uninstalling $(DestCMA)" -$(Verb) $(RM) -f $(DestCMA) endif ##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## # The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. # If unavailable, 'configure' will not define OCAMLOPT in Makefile.config. ifdef OCAMLOPT $(OcamlDir)/%.cmx: $(ObjDir)/%.cmx $(Verb) $(CP) -f $< $@ $(ObjDir)/%.cmx: $(ObjDir)/%.ml $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build" $(Verb) $(Compile.CMX) $@ $< ifdef LIBRARYNAME all-local:: $(OutputCMXA) $(OutputsCMX) clean-local:: clean-cmxa install-local:: install-cmxa uninstall-local:: uninstall-cmxa $(OutputCMXA): $(LibraryCMXA) $(Verb) $(CP) -f $< $@ $(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a) $(LibraryCMXA): $(ObjectsCMX) $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" $(Verb) $(Archive.CMXA) $@ $(ObjectsCMX) $(Verb) $(RM) -f $(@:.cmxa=.o) clean-cmxa:: $(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX) install-cmxa:: $(OutputCMXA) $(OutputsCMX) $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Echo) "Installing $(BuildMode) $(DestCMXA)" $(Verb) $(DataInstall) $(OutputCMXA) $(DestCMXA) $(Echo) "Installing $(BuildMode) $(DestCMXA:.cmxa=.a)" $(Verb) $(DataInstall) $(OutputCMXA:.cmxa=.a) $(DestCMXA:.cmxa=.a) $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ done uninstall-cmxa:: $(Echo) "Uninstalling $(DestCMXA)" $(Verb) $(RM) -f $(DestCMXA) $(Echo) "Uninstalling $(DestCMXA:.cmxa=.a)" $(Verb) $(RM) -f $(DestCMXA:.cmxa=.a) $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ $(RM) -f $(PROJ_libocamldir)/$$i; \ done endif endif ##===- Build executables --------------------------------------------------===## ifdef TOOLNAME all-local:: $(OutputEXE) clean-local:: clean-exe $(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir $(Verb) $(CP) -f $< $@ ifndef OCAMLOPT $(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" $(Verb) $(Archive.EXE) $@ $(ObjectsCMO) else $(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" $(Verb) $(Archive.EXE) $@ $(ObjectsCMX) endif endif ##===- Generate documentation ---------------------------------------------===## $(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) $(Echo) "Documenting $(notdir $@)" $(Verb) $(OCAMLDOC) -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc ##===- Debugging gunk -----------------------------------------------------===## printvars:: printcamlvars printcamlvars:: $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' $(Echo) "OCAMLC : " '$(OCAMLC)' $(Echo) "OCAMLOPT : " '$(OCAMLOPT)' $(Echo) "OCAMLDEP : " '$(OCAMLDEP)' $(Echo) "Compile.CMI : " '$(Compile.CMI)' $(Echo) "Compile.CMO : " '$(Compile.CMO)' $(Echo) "Archive.CMA : " '$(Archive.CMA)' $(Echo) "Compile.CMX : " '$(Compile.CMX)' $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' $(Echo) "LibraryCMA : " '$(LibraryCMA)' $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' $(Echo) "OcamlSources1: " '$(OcamlSources1)' $(Echo) "OcamlSources2: " '$(OcamlSources2)' $(Echo) "OcamlSources : " '$(OcamlSources)' $(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)' $(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)' $(Echo) "OcamlHeaders : " '$(OcamlHeaders)' $(Echo) "ObjectsCMI : " '$(ObjectsCMI)' $(Echo) "ObjectsCMO : " '$(ObjectsCMO)' $(Echo) "ObjectsCMX : " '$(ObjectsCMX)' $(Echo) "OCAML_LIBDIR : " '$(OCAML_LIBDIR)' $(Echo) "DestA : " '$(DestA)' $(Echo) "DestCMA : " '$(DestCMA)' $(Echo) "DestCMXA : " '$(DestCMXA)' $(Echo) "UsedLibs : " '$(UsedLibs)' $(Echo) "UsedLibNames : " '$(UsedLibNames)' .PHONY: printcamlvars build-cmis \ clean-a clean-cmis clean-cma clean-cmxa \ install-a install-cmis install-cma install-cmxa \ install-exe \ uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \ uninstall-exe