all: byte native # --------- # ocaml env # --------- OCAML_FLAGS?=-w @a-4-6-7-9-26-27-29 OCAMLCC_FLAGS?=-ccopt -Werror -ccopt -Wall -ccopt -Wextra OCAMLCC_D_FLAGS?=-ccopt -Wno-error override OCAMLDEP_FLAGS:=-ml-synonym .cmo -ml-synonym .cmx -ml-synonym .ml -ml-synonym .mll export OCAMLFIND_IGNORE_DUPS_IN:=.. export OCAMLRUNPARAM # -------- # make env # -------- if_arg=$(if $2,$1 $2) map=$(foreach x,$2,$(call $1,$x)) ,:=, .SUFFIXES: MAKEFLAGS += -r # ----- # clean # ----- rmw=$(call if_arg,rm,$(wildcard $1)) cleaning=$(findstring c,$(MAKECMDGOALS))$(findstring clean,$(MAKECMDGOALS))$(findstring cleaner,$(MAKECMDGOALS)) LIBOCAML_MAKE_NO_DEPS+=$(cleaning) c clean: $(patsubst %,%/clean,$(basename $(deps))) %/clean: %/Makefile $(MAKE) -C $* -R clean$(CLEANER) $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.a $*.cma $*.cmxa $*.byte $*.native) %/clean: %.c $(call rmw,$*.s $*.o $(if $(CLEANER),$*.d)) %/clean: %.mll $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.ml $*.byte $*.native $(if $(CLEANER),$*.d)) %/clean: %.ml $(call rmw,$*.s $*.startup.s $*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.byte $*.native $(if $(CLEANER),$*.d)) cc cleaner: CLEANER=er cc cleaner: clean # ---------- # ocaml deps # ---------- ml_of_dir=$(addsuffix .ml,$(wildcard $(cm:.cm=))) .PRECIOUS: %.ml %.d: %.ml $(call if_arg,touch,$(ml_of_dir)) errnos=`{ { ocamlfind ocamldep $(OCAMLDEP_FLAGS) $< || echo >&3 0:$$?; } | \ { sed >$@ -e 's/^[^ ]*\.cmx/&s &/' || echo >&3 1:$$?; } \ } 3>&1` && [ -z "$$errnos" ] || { rm $@ && false; } $(call if_arg,rm,$(ml_of_dir)) %.d: %/Makefile printf >$@ '%s.cmo: %s/byte %s\n%s.cmxs %s.cmx: %s/native %s\n' \ "$*" "$*" "$*" "$*" "$*" "$*" "$*" # ------------ # ocaml object # ------------ o=$(filter %.o,$(deps)) ifeq ($(LIBOCAML_MAKE_NO_DEPS),) -include $(o:.o=.d) endif %.o: %.d %.c ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAMLCC_FLAGS) $(if $(DEBUG),-ccopt -Wa$(,)-aln=$*.s) $(filter %.c,$^) %.d: %.c ocamlfind ocamlc -c -nostdlib -ccopt -MM -ccopt -MT"$@\\ $(@:d=o)" -ccopt -MF$@ $(OCAML_FLAGS) $(OCAMLCC_FLAGS) $(OCAMLCC_D_FLAGS) $< # ----------- # ocaml lexer # ----------- %.ml: %.mll ocamllex $< # ------------ # ocaml module # ------------ cm=$(filter %.cm,$(deps)) ifeq ($(LIBOCAML_MAKE_NO_DEPS),) -include $(cm:.cm=.d) endif cm_bn=$(patsubst %.cm,%.cmo,$(1)) $(patsubst %.cm,%.cmx,$(1)) cm_bns=$(patsubst %.cm,%.cmo,$(1)) $(patsubst %.cm,%.cmx,$(1)) $(patsubst %.cm,%.cmxs,$(1)) %.cmo: %.o %.cmx: %.o %.cmo %.cmi: %.d %.ml ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(filter %.ml,$^) %.cmx %cmi %.o: %.d %.ml ocamlfind ocamlopt -c $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(filter %.ml,$^) %.cmxs %.cmx %cmi %.o: %.d %.ml ocamlfind ocamlopt -shared -o $*.cmxs $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(filter %.ml,$^) %.cmo %.cmi: %.d %/byte %.cmo %.cmi: % %.cmxs %.cmx %.cmi %.o: %.d %/native %.cmxs %.cmx %.cmi %.o: % %/byte: $(MAKE) -C $(@D) -R $(DEBUG) byte %/native: $(MAKE) -C $(@D) -R $(DEBUG) native # ---------- # ocaml pack # ---------- camlcase=$(shell pack=$(1); printf %c $${pack} | tr '[a-z]' '[A-Z]'; printf %s $${pack\#?}) Pack=$(call camlcase,$(notdir $(abspath $1))) ifdef pack b byte: ../$(pack).cmo n native: ../$(pack).cmx 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 . endif # -------------- # 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_bn=$(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 capability # ----------------- %.caps: setcap=$(shell PATH="$$PATH:/sbin"; which setcap) %.caps: % $(if $(caps),[ ! -x "$(setcap)" ] || $(setcap) "$(caps)" $*) # --------------- # ocaml debugging # --------------- export DEBUG debug: $(filter-out debug,$(MAKECMDGOALS)) debug: override OCAML_FLAGS+=-verbose debug: override OCAMLC_FLAGS+=-g -principal 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: