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)/%.a: $(LibDir)/%.a 281 $(Verb) ln -sf $< $@ 282 283$(OcamlDir)/%.o: $(LibDir)/%.o 284 $(Verb) ln -sf $< $@ 285 286clean-deplibs: 287 $(Verb) $(RM) -f $(OutputLibs) 288 289install-deplibs: 290 $(Verb) $(MKDIR) $(PROJ_libocamldir) 291 $(Verb) for i in $(DestLibs:$(PROJ_libocamldir)/%=%); do \ 292 ln -sf "$(PROJ_libdir)/$$i" "$(PROJ_libocamldir)/$$i"; \ 293 done 294 295uninstall-deplibs: 296 $(Verb) $(RM) -f $(DestLibs) 297endif 298 299##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## 300 301ifneq ($(OcamlHeaders),) 302all-local:: build-cmis 303clean-local:: clean-cmis 304install-local:: install-cmis 305uninstall-local:: uninstall-cmis 306 307build-cmis: $(OutputsCMI) 308 309$(OcamlDir)/%.cmi: $(ObjDir)/%.cmi $(OcamlDir)/.dir 310 $(Verb) $(CP) -f $< $@ 311 312$(ObjDir)/%.cmi: $(ObjDir)/%.mli $(ObjDir)/.dir 313 $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" 314 $(Verb) $(Compile.CMI) $@ $< 315 316clean-cmis:: 317 -$(Verb) $(RM) -f $(OutputsCMI) 318 319# Also install the .mli's (headers) as documentation. 320install-cmis: $(OutputsCMI) $(OcamlHeaders) 321 $(Verb) $(MKDIR) $(PROJ_libocamldir) 322 $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ 323 $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ 324 $(DataInstall) $(ObjDir)/$$i "$(PROJ_libocamldir)/$$i"; \ 325 done 326 $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ 327 $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ 328 $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ 329 done 330 331uninstall-cmis:: 332 $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ 333 $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ 334 $(RM) -f "$(PROJ_libocamldir)/$$i"; \ 335 done 336 $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ 337 $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ 338 $(RM) -f "$(PROJ_libocamldir)/$$i"; \ 339 done 340endif 341 342 343##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===## 344 345$(ObjDir)/%.cmo: $(ObjDir)/%.ml 346 $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" 347 $(Verb) $(Compile.CMO) $@ $< 348 349ifdef LIBRARYNAME 350all-local:: $(OutputCMA) 351clean-local:: clean-cma 352install-local:: install-cma 353uninstall-local:: uninstall-cma 354 355$(OutputCMA): $(LibraryCMA) $(OcamlDir)/.dir 356 $(Verb) $(CP) -f $< $@ 357 358$(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir 359 $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" 360 $(Verb) $(Archive.CMA) $@ $(ObjectsCMO) 361 362clean-cma:: 363 $(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%) 364 365install-cma:: $(OutputCMA) 366 $(Echo) "Installing $(BuildMode) $(DestCMA)" 367 $(Verb) $(MKDIR) $(PROJ_libocamldir) 368 $(Verb) $(DataInstall) $(OutputCMA) "$(DestCMA)" 369 370uninstall-cma:: 371 $(Echo) "Uninstalling $(DestCMA)" 372 -$(Verb) $(RM) -f $(DestCMA) 373endif 374 375##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## 376 377# The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. 378# If unavailable, 'configure' will set HAVE_OCAMLOPT to 0 in Makefile.config. 379ifeq ($(HAVE_OCAMLOPT),1) 380 381$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx 382 $(Verb) $(CP) -f $< $@ 383 384$(ObjDir)/%.cmx: $(ObjDir)/%.ml 385 $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build" 386 $(Verb) $(Compile.CMX) $@ $< 387 388ifdef LIBRARYNAME 389all-local:: $(OutputCMXA) $(OutputsCMX) 390clean-local:: clean-cmxa 391install-local:: install-cmxa 392uninstall-local:: uninstall-cmxa 393 394$(OutputCMXA): $(LibraryCMXA) 395 $(Verb) $(CP) -f $< $@ 396 $(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a) 397 398$(LibraryCMXA): $(ObjectsCMX) 399 $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" 400 $(Verb) $(Archive.CMXA) $@ $(ObjectsCMX) 401 $(Verb) $(RM) -f $(@:.cmxa=.o) 402 403clean-cmxa:: 404 $(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX) 405 406install-cmxa:: $(OutputCMXA) $(OutputsCMX) 407 $(Verb) $(MKDIR) $(PROJ_libocamldir) 408 $(Echo) "Installing $(BuildMode) $(DestCMXA)" 409 $(Verb) $(DataInstall) $(OutputCMXA) $(DestCMXA) 410 $(Echo) "Installing $(BuildMode) $(DestCMXA:.cmxa=.a)" 411 $(Verb) $(DataInstall) $(OutputCMXA:.cmxa=.a) $(DestCMXA:.cmxa=.a) 412 $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ 413 $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ 414 $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ 415 done 416 417uninstall-cmxa:: 418 $(Echo) "Uninstalling $(DestCMXA)" 419 $(Verb) $(RM) -f $(DestCMXA) 420 $(Echo) "Uninstalling $(DestCMXA:.cmxa=.a)" 421 $(Verb) $(RM) -f $(DestCMXA:.cmxa=.a) 422 $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ 423 $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ 424 $(RM) -f $(PROJ_libocamldir)/$$i; \ 425 done 426endif 427endif 428 429##===- Generate documentation ---------------------------------------------===## 430 431$(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) 432 $(Echo) "Documenting $(notdir $@)" 433 $(Verb) $(OCAMLFIND) doc -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) 434 435ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc 436 437##===- Debugging gunk -----------------------------------------------------===## 438printvars:: printcamlvars 439 440printcamlvars:: 441 $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' 442 $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' 443 $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' 444 $(Echo) "OCAMLRPATH : " '$(OCAMLRPATH)' 445 $(Echo) "OCAMLSTUBS : " '$(OCAMLSTUBS)' 446 $(Echo) "OCAMLSTUBFLAGS : " '$(OCAMLSTUBFLAGS)' 447 $(Echo) "OCAMLFIND : " '$(OCAMLFIND)' 448 $(Echo) "Compile.CMI : " '$(Compile.CMI)' 449 $(Echo) "Compile.CMO : " '$(Compile.CMO)' 450 $(Echo) "Archive.CMA : " '$(Archive.CMA)' 451 $(Echo) "Compile.CMX : " '$(Compile.CMX)' 452 $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' 453 $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' 454 $(Echo) "LibraryA : " '$(LibraryA)' 455 $(Echo) "LibraryCMA : " '$(LibraryCMA)' 456 $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' 457 $(Echo) "SharedLib : " '$(SharedLib)' 458 $(Echo) "OcamlSources1: " '$(OcamlSources1)' 459 $(Echo) "OcamlSources2: " '$(OcamlSources2)' 460 $(Echo) "OcamlSources : " '$(OcamlSources)' 461 $(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)' 462 $(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)' 463 $(Echo) "OcamlHeaders : " '$(OcamlHeaders)' 464 $(Echo) "ObjectsCMI : " '$(ObjectsCMI)' 465 $(Echo) "ObjectsCMO : " '$(ObjectsCMO)' 466 $(Echo) "ObjectsCMX : " '$(ObjectsCMX)' 467 $(Echo) "OCAML_LIBDIR : " '$(OCAML_LIBDIR)' 468 $(Echo) "DestA : " '$(DestA)' 469 $(Echo) "DestCMA : " '$(DestCMA)' 470 $(Echo) "DestCMXA : " '$(DestCMXA)' 471 $(Echo) "DestSharedLib: " '$(DestSharedLib)' 472 $(Echo) "UsedLibs : " '$(UsedLibs)' 473 $(Echo) "UsedLibNames : " '$(UsedLibNames)' 474 $(Echo) "ExtraLibs : " '$(ExtraLibs)' 475 476.PHONY: printcamlvars build-cmis \ 477 clean-a clean-cmis clean-cma clean-cmxa \ 478 install-a install-cmis install-cma install-cmxa \ 479 install-exe \ 480 uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \ 481 uninstall-exe 482