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