1##===- bindings/ocaml/Makefile.ocaml -----------------------*- Makefile -*-===## 2# 3# The LLVM Compiler Infrastructure 4# 5# This file is distributed under the University of Illinois Open Source 6# License. See LICENSE.TXT for details. 7# 8##===----------------------------------------------------------------------===## 9# 10# An OCaml library is a unique project type in the context of LLVM, so rules are 11# here rather than in Makefile.rules. 12# 13# Reference materials on installing OCaml libraries: 14# 15# https://fedoraproject.org/wiki/Packaging/OCaml 16# http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt 17# 18##===----------------------------------------------------------------------===## 19 20include $(LEVEL)/Makefile.config 21 22# We have our own rules for building static libraries. 23NO_BUILD_ARCHIVE = 1 24 25# CFLAGS needs to be set before Makefile.rules is included. 26CXX.Flags += -I"$(shell $(OCAMLFIND) c -where)" 27C.Flags += -I"$(shell $(OCAMLFIND) c -where)" 28 29ifeq ($(ENABLE_SHARED),1) 30LINK_COMPONENTS := all 31endif 32 33include $(LEVEL)/Makefile.common 34 35# Used in out-of-tree builds of OCaml bindings only. 36ifdef SYSTEM_LLVM_CONFIG 37LLVM_CONFIG = $(SYSTEM_LLVM_CONFIG) 38LLVMLibsOptions += $(shell $(LLVM_CONFIG) --ldflags) 39endif 40 41# Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the 42# user can override this with OCAML_LIBDIR or configure --with-ocaml-libdir=. 43PROJ_libocamldir := $(DESTDIR)$(OCAML_LIBDIR) 44OcamlDir := $(LibDir)/ocaml 45 46# Info from llvm-config and similar 47ifndef IS_CLEANING_TARGET 48ifdef UsedComponents 49UsedLibs = $(shell $(LLVM_CONFIG) --libs --system-libs $(UsedComponents)) 50UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents)) 51endif 52endif 53 54# How do we link OCaml executables with LLVM? 55# 1) If this is a --enable-shared build, build stub libraries. This also allows 56# to use LLVM from toplevels. 57# 2) If this is a --disable-shared build, embed ocamlc options for building 58# a custom runtime and a static executable. It is not possible to use LLVM 59# from toplevels. 60ifneq ($(ObjectsO),) 61ifeq ($(ENABLE_SHARED),1) 62OCAMLSTUBS := 1 63OCAMLSTUBFLAGS := $(patsubst %,-cclib %, $(LLVMLibsOptions) -l$(LIBRARYNAME)) 64endif 65endif 66 67# Avoid the need for LD_LIBRARY_PATH 68ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) 69ifneq ($(HOST_OS),Darwin) 70OCAMLRPATH := $(RPATH) -Wl,'$$ORIGIN/../../lib' 71endif 72endif 73 74# See http://caml.inria.fr/mantis/view.php?id=6642 75OCAMLORIGIN := -ccopt -L'$$CAMLORIGIN/..' \ 76 -ccopt $(RPATH) -ccopt -Wl,'$$CAMLORIGIN/..' 77 78# Tools 79OCAMLCFLAGS += -I $(OcamlDir) $(addprefix -package ,$(FindlibPackages)) 80 81ifndef IS_CLEANING_TARGET 82ifneq ($(ObjectsO),) 83OCAMLAFLAGS += $(patsubst %,-cclib %, \ 84 $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \ 85 $(shell $(LLVM_CONFIG) --ldflags)) \ 86 $(UsedLibs) $(ExtraLibs)) 87else 88OCAMLAFLAGS += $(patsubst %,-cclib %, \ 89 $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags)) \ 90 $(UsedLibs) $(ExtraLibs)) 91endif 92endif 93 94ifneq ($(DEBUG_SYMBOLS),1) 95 OCAMLDEBUGFLAG := -g 96endif 97 98Compile.CMI := $(strip $(OCAMLFIND) c -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) 99Compile.CMO := $(strip $(OCAMLFIND) c -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) 100Compile.CMX := $(strip $(OCAMLFIND) opt -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) 101 102ifdef OCAMLSTUBS 103# -dllib is engaged with ocamlc builds, $(OCAMLSTUBFLAGS) in ocamlc -custom builds. 104Archive.CMA := $(strip $(OCAMLFIND) c -a -dllib -l$(LIBRARYNAME) $(OCAMLSTUBFLAGS) \ 105 $(OCAMLDEBUGFLAG) $(OCAMLORIGIN) -o) 106else 107Archive.CMA := $(strip $(OCAMLFIND) c -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ 108 $(OCAMLORIGIN) -o) 109endif 110 111ifdef OCAMLSTUBS 112Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLSTUBFLAGS) $(OCAMLDEBUGFLAG) \ 113 $(OCAMLORIGIN) -o) 114else 115Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ 116 $(OCAMLORIGIN) -o) 117endif 118 119# Source files 120ifndef OcamlSources1 121OcamlSources1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.ml)) 122endif 123 124ifndef OcamlHeaders1 125OcamlHeaders1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.mli)) 126endif 127 128OcamlSources2 := $(filter-out $(ExcludeSources),$(OcamlSources1)) 129OcamlHeaders2 := $(filter-out $(ExcludeHeaders),$(OcamlHeaders1)) 130 131OcamlSources := $(OcamlSources2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) 132OcamlHeaders := $(OcamlHeaders2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) 133 134# Intermediate files 135ObjectsCMI := $(OcamlSources:%.ml=%.cmi) 136ObjectsCMO := $(OcamlSources:%.ml=%.cmo) 137ObjectsCMX := $(OcamlSources:%.ml=%.cmx) 138 139ifdef LIBRARYNAME 140LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma 141LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa 142endif 143 144ifdef TOOLNAME 145ToolEXE := $(ObjDir)/$(TOOLNAME)$(EXEEXT) 146endif 147 148# Output files 149# The .cmo files are the only intermediates; all others are to be installed. 150OutputsCMI := $(ObjectsCMI:$(ObjDir)/%.cmi=$(OcamlDir)/%.cmi) 151OutputsCMX := $(ObjectsCMX:$(ObjDir)/%.cmx=$(OcamlDir)/%.cmx) 152OutputLibs := $(UsedLibNames:%=$(OcamlDir)/%) 153 154ifdef LIBRARYNAME 155LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a 156OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma) 157OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa) 158endif 159 160ifdef OCAMLSTUBS 161SharedLib := $(OcamlDir)/dll$(LIBRARYNAME)$(SHLIBEXT) 162endif 163 164ifdef TOOLNAME 165ifdef EXAMPLE_TOOL 166OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT) 167else 168OutputEXE := $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT) 169endif 170endif 171 172# Installation targets 173DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%) 174 175ifdef LIBRARYNAME 176DestA := $(PROJ_libocamldir)/lib$(LIBRARYNAME).a 177DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma 178DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa 179endif 180 181ifdef OCAMLSTUBS 182DestSharedLib := $(PROJ_libocamldir)/dll$(LIBRARYNAME)$(SHLIBEXT) 183endif 184 185##===- Dependencies -------------------------------------------------------===## 186# Copy the sources into the intermediate directory because older ocamlc doesn't 187# support -o except when linking (outputs are placed next to inputs). 188 189$(ObjDir)/%.mli: $(PROJ_SRC_DIR)/%.mli $(ObjDir)/.dir 190 $(Verb) $(CP) -f $< $@ 191 192$(ObjDir)/%.ml: $(PROJ_SRC_DIR)/%.ml $(ObjDir)/.dir 193 $(Verb) $(CP) -f $< $@ 194 195$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi) 196 197ifdef LIBRARYNAME 198$(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ 199 $(OcamlDir)/.dir $(ObjDir)/.dir 200 $(Verb) $(OCAMLFIND) dep $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ 201 202-include $(ObjDir)/$(LIBRARYNAME).ocamldep 203endif 204 205ifdef TOOLNAME 206$(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ 207 $(OcamlDir)/.dir $(ObjDir)/.dir 208 $(Verb) $(OCAMLFIND) dep $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ 209 210-include $(ObjDir)/$(TOOLNAME).ocamldep 211endif 212 213##===- Build static library from C sources --------------------------------===## 214 215ifdef LibraryA 216all-local:: $(LibraryA) 217clean-local:: clean-a 218install-local:: install-a 219uninstall-local:: uninstall-a 220 221$(LibraryA): $(ObjectsO) $(OcamlDir)/.dir 222 $(Echo) "Building $(BuildMode) $(notdir $@)" 223 -$(Verb) $(RM) -f $@ 224 $(Verb) $(Archive) $@ $(ObjectsO) 225 $(Verb) $(Ranlib) $@ 226 227clean-a:: 228 -$(Verb) $(RM) -f $(LibraryA) 229 230install-a:: $(LibraryA) 231 $(Echo) "Installing $(BuildMode) $(DestA)" 232 $(Verb) $(MKDIR) $(PROJ_libocamldir) 233 $(Verb) $(INSTALL) $(LibraryA) $(DestA) 234 $(Verb) 235 236uninstall-a:: 237 $(Echo) "Uninstalling $(DestA)" 238 -$(Verb) $(RM) -f $(DestA) 239endif 240 241 242##===- Build stub library from C sources ----------------------------------===## 243 244ifdef SharedLib 245all-local:: $(SharedLib) 246clean-local:: clean-shared 247install-local:: install-shared 248uninstall-local:: uninstall-shared 249 250$(SharedLib): $(ObjectsO) $(OcamlDir)/.dir 251 $(Echo) "Building $(BuildMode) $(notdir $@)" 252 $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) -o $@ $(ObjectsO) \ 253 $(LLVMLibsOptions) 254 255clean-shared:: 256 -$(Verb) $(RM) -f $(SharedLib) 257 258install-shared:: $(SharedLib) 259 $(Echo) "Installing $(BuildMode) $(DestSharedLib)" 260 $(Verb) $(MKDIR) $(PROJ_libocamldir) 261 $(Verb) $(INSTALL) $(SharedLib) $(DestSharedLib) 262 $(Verb) 263 264uninstall-shared:: 265 $(Echo) "Uninstalling $(DestSharedLib)" 266 -$(Verb) $(RM) -f $(DestSharedLib) 267endif 268 269 270##===- Deposit dependent libraries adjacent to OCaml libs -----------------===## 271 272ifndef SYSTEM_LLVM_CONFIG 273all-local:: build-deplibs 274clean-local:: clean-deplibs 275install-local:: install-deplibs 276uninstall-local:: uninstall-deplibs 277 278build-deplibs: $(OutputLibs) 279 280$(OcamlDir)/%.so: $(LibDir)/%.so 281 $(Verb) ln -sf $< $@ 282$(OcamlDir)/%.a: $(LibDir)/%.a 283 $(Verb) ln -sf $< $@ 284 285$(OcamlDir)/%.o: $(LibDir)/%.o 286 $(Verb) ln -sf $< $@ 287 288clean-deplibs: 289 $(Verb) $(RM) -f $(OutputLibs) 290 291install-deplibs: 292 $(Verb) $(MKDIR) $(PROJ_libocamldir) 293 $(Verb) for i in $(DestLibs:$(PROJ_libocamldir)/%=%); do \ 294 ln -sf "$(PROJ_libdir)/$$i" "$(PROJ_libocamldir)/$$i"; \ 295 done 296 297uninstall-deplibs: 298 $(Verb) $(RM) -f $(DestLibs) 299endif 300 301##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## 302 303ifneq ($(OcamlHeaders),) 304all-local:: build-cmis 305clean-local:: clean-cmis 306install-local:: install-cmis 307uninstall-local:: uninstall-cmis 308 309build-cmis: $(OutputsCMI) 310 311$(OcamlDir)/%.cmi: $(ObjDir)/%.cmi $(OcamlDir)/.dir 312 $(Verb) $(CP) -f $< $@ 313 314$(ObjDir)/%.cmi: $(ObjDir)/%.mli $(ObjDir)/.dir 315 $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" 316 $(Verb) $(Compile.CMI) $@ $< 317 318clean-cmis:: 319 -$(Verb) $(RM) -f $(OutputsCMI) 320 321# Also install the .mli's (headers) as documentation. 322install-cmis: $(OutputsCMI) $(OcamlHeaders) 323 $(Verb) $(MKDIR) $(PROJ_libocamldir) 324 $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ 325 $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ 326 $(DataInstall) $(ObjDir)/$$i "$(PROJ_libocamldir)/$$i"; \ 327 done 328 $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ 329 $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ 330 $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ 331 done 332 333uninstall-cmis:: 334 $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ 335 $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ 336 $(RM) -f "$(PROJ_libocamldir)/$$i"; \ 337 done 338 $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ 339 $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ 340 $(RM) -f "$(PROJ_libocamldir)/$$i"; \ 341 done 342endif 343 344 345##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===## 346 347$(ObjDir)/%.cmo: $(ObjDir)/%.ml 348 $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" 349 $(Verb) $(Compile.CMO) $@ $< 350 351ifdef LIBRARYNAME 352all-local:: $(OutputCMA) 353clean-local:: clean-cma 354install-local:: install-cma 355uninstall-local:: uninstall-cma 356 357$(OutputCMA): $(LibraryCMA) $(OcamlDir)/.dir 358 $(Verb) $(CP) -f $< $@ 359 360$(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir 361 $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" 362 $(Verb) $(Archive.CMA) $@ $(ObjectsCMO) 363 364clean-cma:: 365 $(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%) 366 367install-cma:: $(OutputCMA) 368 $(Echo) "Installing $(BuildMode) $(DestCMA)" 369 $(Verb) $(MKDIR) $(PROJ_libocamldir) 370 $(Verb) $(DataInstall) $(OutputCMA) "$(DestCMA)" 371 372uninstall-cma:: 373 $(Echo) "Uninstalling $(DestCMA)" 374 -$(Verb) $(RM) -f $(DestCMA) 375endif 376 377##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## 378 379# The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. 380# If unavailable, 'configure' will set HAVE_OCAMLOPT to 0 in Makefile.config. 381ifeq ($(HAVE_OCAMLOPT),1) 382 383$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx 384 $(Verb) $(CP) -f $< $@ 385 386$(ObjDir)/%.cmx: $(ObjDir)/%.ml 387 $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build" 388 $(Verb) $(Compile.CMX) $@ $< 389 390ifdef LIBRARYNAME 391all-local:: $(OutputCMXA) $(OutputsCMX) 392clean-local:: clean-cmxa 393install-local:: install-cmxa 394uninstall-local:: uninstall-cmxa 395 396$(OutputCMXA): $(LibraryCMXA) 397 $(Verb) $(CP) -f $< $@ 398 $(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a) 399 400$(LibraryCMXA): $(ObjectsCMX) 401 $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" 402 $(Verb) $(Archive.CMXA) $@ $(ObjectsCMX) 403 $(Verb) $(RM) -f $(@:.cmxa=.o) 404 405clean-cmxa:: 406 $(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX) 407 408install-cmxa:: $(OutputCMXA) $(OutputsCMX) 409 $(Verb) $(MKDIR) $(PROJ_libocamldir) 410 $(Echo) "Installing $(BuildMode) $(DestCMXA)" 411 $(Verb) $(DataInstall) $(OutputCMXA) $(DestCMXA) 412 $(Echo) "Installing $(BuildMode) $(DestCMXA:.cmxa=.a)" 413 $(Verb) $(DataInstall) $(OutputCMXA:.cmxa=.a) $(DestCMXA:.cmxa=.a) 414 $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ 415 $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ 416 $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ 417 done 418 419uninstall-cmxa:: 420 $(Echo) "Uninstalling $(DestCMXA)" 421 $(Verb) $(RM) -f $(DestCMXA) 422 $(Echo) "Uninstalling $(DestCMXA:.cmxa=.a)" 423 $(Verb) $(RM) -f $(DestCMXA:.cmxa=.a) 424 $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ 425 $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ 426 $(RM) -f $(PROJ_libocamldir)/$$i; \ 427 done 428endif 429endif 430 431##===- Generate documentation ---------------------------------------------===## 432 433$(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) 434 $(Echo) "Documenting $(notdir $@)" 435 $(Verb) $(OCAMLFIND) doc -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) 436 437ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc 438 439##===- Debugging gunk -----------------------------------------------------===## 440printvars:: printcamlvars 441 442printcamlvars:: 443 $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' 444 $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' 445 $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' 446 $(Echo) "OCAMLRPATH : " '$(OCAMLRPATH)' 447 $(Echo) "OCAMLSTUBS : " '$(OCAMLSTUBS)' 448 $(Echo) "OCAMLSTUBFLAGS : " '$(OCAMLSTUBFLAGS)' 449 $(Echo) "OCAMLFIND : " '$(OCAMLFIND)' 450 $(Echo) "Compile.CMI : " '$(Compile.CMI)' 451 $(Echo) "Compile.CMO : " '$(Compile.CMO)' 452 $(Echo) "Archive.CMA : " '$(Archive.CMA)' 453 $(Echo) "Compile.CMX : " '$(Compile.CMX)' 454 $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' 455 $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' 456 $(Echo) "LibraryA : " '$(LibraryA)' 457 $(Echo) "LibraryCMA : " '$(LibraryCMA)' 458 $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' 459 $(Echo) "SharedLib : " '$(SharedLib)' 460 $(Echo) "OcamlSources1: " '$(OcamlSources1)' 461 $(Echo) "OcamlSources2: " '$(OcamlSources2)' 462 $(Echo) "OcamlSources : " '$(OcamlSources)' 463 $(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)' 464 $(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)' 465 $(Echo) "OcamlHeaders : " '$(OcamlHeaders)' 466 $(Echo) "ObjectsCMI : " '$(ObjectsCMI)' 467 $(Echo) "ObjectsCMO : " '$(ObjectsCMO)' 468 $(Echo) "ObjectsCMX : " '$(ObjectsCMX)' 469 $(Echo) "OCAML_LIBDIR : " '$(OCAML_LIBDIR)' 470 $(Echo) "DestA : " '$(DestA)' 471 $(Echo) "DestCMA : " '$(DestCMA)' 472 $(Echo) "DestCMXA : " '$(DestCMXA)' 473 $(Echo) "DestSharedLib: " '$(DestSharedLib)' 474 $(Echo) "UsedLibs : " '$(UsedLibs)' 475 $(Echo) "UsedLibNames : " '$(UsedLibNames)' 476 $(Echo) "ExtraLibs : " '$(ExtraLibs)' 477 478.PHONY: printcamlvars build-cmis \ 479 clean-a clean-cmis clean-cma clean-cmxa \ 480 install-a install-cmis install-cma install-cmxa \ 481 install-exe \ 482 uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \ 483 uninstall-exe 484