# vim: ft=make all: byte native # --------- # ocaml env # --------- OCAML_FLAGS?=-w @a-4-6-7-9-26-27-29 OCAMLCC_FLAGS?=-ccopt -Werror -ccopt -Wall -ccopt -Wextra override OCAMLDEP_FLAGS:=-ml-synonym .cmo -ml-synonym .cmx -ml-synonym .ml ocamllex?=ocamllex export OCAMLFIND_IGNORE_DUPS_IN:=.. export OCAMLRUNPARAM # -------- # make env # -------- if_args=$(if $2,$1 $2) map=$(foreach x,$2,$(call $1,$x)) curdir:=$(notdir $(abspath .)) .SUFFIXES: MAKEFLAGS += -r # ----- # clean # ----- rmw=$(call if_args,rm,$(wildcard $1)) c clean: $(patsubst %,%/clean,$(basename $(deps))) $(call rmw,Makefile.deps) %/clean: %/Makefile $(MAKE) -C $* -R clean $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.a $*.cma $*.cmxa $*.byte $*.native) %/clean: %.c $(call rmw,$*.o) %/clean: %.mll $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.ml $*.byte $*.native) %/clean: %.ml $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.byte $*.native) # ---------- # ocaml pack # ---------- cm=$(filter %.cm,$(deps)) ifndef pack pack:=$(curdir) b byte: ../$(pack).cmo n native: ../$(pack).cmx endif pack_ ?=$(notdir $(abspath ..)) pack__ ?=$(notdir $(abspath ../..)) pack___?=$(notdir $(abspath ../../..)) camlcase=$(shell pack=$(1); printf %c $${pack} | tr '[a-z]' '[A-Z]'; printf %s $${pack\#?}) Pack =$(call camlcase,$(pack)) Pack_ =$(call camlcase,$(pack_)) Pack__ =$(call camlcase,$(pack__)) Pack___=$(call camlcase,$(pack___)) pack_cm?=$(cm) ../$(pack).cmo ../$(pack).cmi: $(pack_cm:=o) ocamlfind ocamlc -pack -o ../$(pack).cmo $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(OCAMLC_PACK_FLAGS) $(filter %.cmo,$^) touch . ../$(pack).cmx ../$(pack).o: $(pack_cm:=x) ocamlfind ocamlopt -pack -o ../$(pack).cmx $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(OCAMLOPT_PACK_FLAGS) $(filter %.cmx,$^) touch . #../%: # $(MAKE) -C .. -R $* # ------------ # ocaml object # ------------ o=$(filter %.o,$(deps)) %.o: %.c ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAMLCC_FLAGS) $< # ------------ # ocaml module # ------------ cm_ox=$(patsubst %.cm,%.cmo,$(1)) $(patsubst %.cm,%.cmx,$(1)) cm_oxs=$(patsubst %.cm,%.cmo,$(1)) $(patsubst %.cm,%.cmxs,$(1)) $(patsubst %.cm,%.cmx,$(1)) %.cmo: %.o %.cmx: %.o %.cmo %.cmi: %.ml ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAMLC_FLAGS) $< %.cmx %cmi %.o: %.ml ocamlfind ocamlopt -c $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $< %.cmxs %.cmx %cmi %.o: %.ml ocamlfind ocamlopt -shared -o $*.cmxs $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $< %.cmo %.cmi: %/byte %.cmo %.cmi: % %.cmxs %.cmx %.cmi %.o: %/native %.cmxs %.cmx %.cmi %.o: % %/byte: $(MAKE) -C $(@D) -R $(DEBUG) byte %/native: $(MAKE) -C $(@D) -R $(DEBUG) native # ----------- # ocaml lexer # ----------- %.ml: %.mll $(ocamllex) $< # -------------- # object archive # -------------- o_of_a=$(patsubst %,$(1:.a=)/%,$(filter %.o,$(shell ar t $1))) $(call map,o_of_a,$(patsubst %,$(1:.a=)/%,$(filter %.a,$(shell ar t $1)))) a=$(filter %.a,$(deps)) %.a: ar cSru$(AR_FLAGS) $@ $(call map,o_of_a,$(filter %.a,$^)) $(filter %.o,$^) ranlib $(RANLIB_FLAGS) $@ dll%.so: CC=$(shell ocamlfind ocamlc -config | sed -ne 's/^native_c_compiler: *//p') dll%.so: lib%.a $(CC) -o $@ -shared $(filter %.o,$(shell ar t $<)) # ------------- # ocaml archive # ------------- ca=$(filter %.ca,$(deps)) ca_x_a=$(patsubst %.ca,%.cma,$(1)) $(patsubst %.ca,%.cmxa,$(1)) %.cma: ocamlfind ocamlc -a -o $@ $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(OCAML_ARCH_FLAGS) $(OCAMLC_ARCH_FLAGS) $(filter %.cmo,$^) %.cmxa: ocamlfind ocamlopt -a -o $@ $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(OCAML_ARCH_FLAGS) $(OCAMLOPT_ARCH_FLAGS) $(filter %.cmx,$^) # ------------ # ocaml binary # ------------ cb_bn=$(patsubst %.cb,%.byte,$(1)) $(patsubst %.cb,%.native,$(1)) %.byte: ocamlfind ocamlc -o $@ -linkpkg $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(OCAML_BIN_FLAGS) $(OCAMLC_BIN_FLAGS) $(filter %.cmo,$^) %.native: ocamlfind ocamlopt -o $@ -linkpkg $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(OCAML_BIN_FLAGS) $(OCAMLOPT_BIN_FLAGS) $(filter %.cmx,$^) # ------------------- # binary capabilities # ------------------- %.caps: setcap=$(shell PATH="$$PATH:/sbin"; which setcap) %.caps: % $(if $(caps),[ ! -x "$(setcap)" ] || $(setcap) "$(caps)" $*) # ------------------ # ocaml dependencies # ------------------ ml_of_mll=$(patsubst %.mll,%.ml,$(wildcard $(cm:.cm=.mll))) ml_of_dir=$(addsuffix .ml,$(wildcard $(cm:.cm=))) Makefile.deps: $(wildcard $(cm:.cm=.ml) $(cm:.cm=.mll)) $(call if_args,touch,$(ml_of_dir)) for mll in $(filter %.mll,$^); do $(ocamllex) $$mll; done deps="$$(ocamlfind ocamldep $(OCAMLDEP_FLAGS) $(^:.mll=.ml))"; \ if [ $$? = 0 ]; \ then printf "%s\n" "$$deps" | sed >$@ -e 's/^[^ ]*\.cmx/&s &/'; \ else rm -f $(ml_of_dir) $(ml_of_mll); false; fi $(call if_args,rm,$(ml_of_dir)) $(call if_args,rm,$(ml_of_mll)) for dir in $(wildcard $(cm:.cm=)); do printf >>$@ '%s.cmo: %s/byte %s\n%s.cmxs %s.cmx: %s/native %s\n' "$$dir" "$$dir" "$$dir" "$$dir" "$$dir" "$$dir" "$$dir"; done ifeq ($(NO_MAKEFILE_DEPS)$(findstring c,$(MAKECMDGOALS))$(findstring clean,$(MAKECMDGOALS)),) include Makefile.deps endif # --------------- # ocaml debugging # --------------- export DEBUG debug: $(filter-out debug,$(MAKECMDGOALS)) debug: override OCAML_FLAGS+=-verbose debug: override OCAMLC_FLAGS+=-g debug: override OCAMLCC_FLAGS+=-ccopt -ggdb3 debug: override OCAMLDEP_FLAGS+=-verbose debug: override OCAMLOPT_FLAGS+=-ccopt -ggdb3 debug: override OCAMLRUNPARAM+=b debug: override DEBUG:=debug debug: