]> Git — Sourcephile - ocaml/libocaml_make.git/blob - GNUmakefile
Modification : n'utilise plus make récursivement et permet le parallélisme.
[ocaml/libocaml_make.git] / GNUmakefile
1 # ---------
2 # ocaml env
3 # ---------
4 OCAML_FLAGS?=-w @a-4-6-7-9-26-27-29
5 OCAMLCC_FLAGS?=-ccopt -Werror -ccopt -Wall -ccopt -Wextra
6 OCAMLCC_D_FLAGS?=-ccopt -Wno-error
7 override OCAMLDEP_FLAGS:=-ml-synonym .cmi -ml-synonym .mll
8 export OCAMLRUNPARAM
9
10 # --------
11 # make env
12 # --------
13 camlcase=$(shell pack=$(1); printf %c $${pack} | tr '[a-z]' '[A-Z]'; printf %s $${pack\#?})
14 flock=flock $1 $2 -c "$(subst ",\",$(subst \,\\,$3))"
15 flocks=$(if $2,$(call \
16 flock,$1,$(firstword $2),$(call \
17 flocks,$1,$(wordlist 2,$(words $2),$2),$3)),$3)
18 GNUmakefile.inc?=GNUmakefile.inc
19 if_arg=$(if $2,$1 $2)
20 is_parallel=$(findstring j,$(value MAKEFLAGS))
21 map=$(foreach x,$2,$(call $1,$x))
22 mul=$(foreach p,$1,$(foreach s,$2,$p$s))
23 rev=$(if $1,$(call \
24 rev,$(wordlist 2,$(words $1),$1))) $(firstword $1)
25 ,:=,
26 .SECONDARY:
27 .SUFFIXES:
28 MAKEFLAGS += -r
29 .SHELLFLAGS += -e
30
31 # -----
32 # clean
33 # -----
34 rmw=$(call if_arg,rm,$(wildcard $1))
35 clean+=$(or $(filter c,$(MAKECMDGOALS)),$(filter %/c,$(MAKECMDGOALS)),$(filter clean,$(MAKECMDGOALS)),$(filter %/clean,$(MAKECMDGOALS)))
36 cleaner+=$(or $(filter cc,$(MAKECMDGOALS)),$(filter %/cc,$(MAKECMDGOALS)),$(filter cleaner,$(MAKECMDGOALS)),$(filter %/cleaner,$(MAKECMDGOALS)))
37 LIBOCAML_MAKE_NO_DEPS+=$(or $(clean),$(cleaner))
38 %/clean: %/$(GNUmakefile.inc)
39 $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.a $*.cma $*.cmxa $*.byte $*.native)
40 %/clean: %.c
41 $(call rmw,$*.s $*.o $(if $(cleaner),$*.d))
42 %/clean: %.mll
43 $(call rmw,$*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.ml $*.byte $*.native $(if $(cleaner),$*.d))
44 %/clean: %.ml
45 $(call rmw,$*.s $*.startup.s $*.cmi $*.cmo $*.cmx $*.cmxs $*.o $*.byte $*.native $(if $(cleaner),$*.d))
46
47 # ---------------------
48 # ocaml GNUmakefile.inc
49 # ---------------------
50 define make_GNUmakefile.inc
51 d := $(or $1,.)
52 dir_ptr := $$(dir_ptr).level
53 dirstack_$$(dir_ptr) := $$d
54
55 Pack := $$(if $$(Pack),$$(Pack).)$$(call camlcase,$$(notdir $$d))
56
57 targets :=
58
59 include $1/$(GNUmakefile.inc)
60
61 ifeq ($$(LIBOCAML_MAKE_NO_DEPS),)
62 -include $$(wildcard $$(o:.o=.d) $$(cm:.cm=.d))
63 endif
64
65 dirs := $$(filter-out $1,$$(patsubst %/.,%,$$(wildcard $$(patsubst %,%/.,$$(basename $$(targets))))))
66
67 $1/c $1/clean: clean:=clean
68 $1/cc $1/cleaner: cleaner:=cleaner
69 $1/b $1/byte: byte:=byte
70 $1/n $1/native: native:=native
71 $1/b $1/all: byte:=byte
72 $1/n $1/all: native:=native
73
74 # NOTE: no .PHONY: to trigger %/clean
75 $1/c $1/clean: $$(addsuffix /clean,$$(filter-out $1,$$(basename $$(targets))))
76 $1/cc $1/cleaner: $1/clean
77
78 ifeq ($$(LIBOCAML_MAKE_NO_DEPS),)
79 targets := $$(foreach t,$$(targets), \
80 $$t \
81 $$(if $$(filter %.o,$$t)$$(filter %.cm,$$t) \
82 ,$$(if $$(wildcard $$(basename $$t)),,$$(basename $$t).d)))
83 endif
84
85 $1/b $1/byte: $$(patsubst %.cb,%.byte, $$(patsubst %.ca,%.cma, $$(patsubst %.cm,%.cmo,$$(targets))))
86 $1/n $1/native: $$(patsubst %.cb,%.native,$$(patsubst %.ca,%.cmxa,$$(patsubst %.cm,%.cmx,$$(targets))))
87 $1/n $1/all: $1/byte $1/native
88 $1/xb $1/exec-byte: $$(cb:.cb=.byte.exec)
89 $1/xn $1/exec-native: $$(cb:.cb=.native.exec)
90
91 Pack := $$(basename $$(Pack))
92
93 $$(foreach d,$$(dirs), \
94 $$(eval $1/c $1/clean: $$d/clean) \
95 $$(eval $1/cc $1/cleaner: $$d/cleaner) \
96 $$(eval $1/b $1/byte: $$d/byte) \
97 $$(eval $1/n $1/native: $$d/native) \
98 $$(eval $1/xb $1/exec-native: $$d/exec-byte) \
99 $$(eval $1/xn $1/exec-byte: $$d/exec-native) \
100 $$(eval $$(call make_GNUmakefile.inc,$$d,$2)))
101
102 d := $$(dirstack_$$(dir_ptr))
103 dir_ptr := $$(basename $$(dir_ptr))
104
105 endef
106 include_GNUmakefile.inc = $(eval $(call make_GNUmakefile.inc,$(or $1,.),$2))
107
108 # ----------
109 # ocaml deps
110 # ----------
111 %.d: %.ml
112 errnos=`{ { ocamlfind ocamldep $(OCAMLDEP_FLAGS) $(OCAML_DEPS_FLAGS) $< || echo >&3 0:$$?; } | \
113 { sed >$@ -e 's/^[^ ]*\.cmx/&s \\\\\n&/' -e 's/ :/:/' || echo >&3 1:$$?; } \
114 } 3>&1` && [ -z "$$errnos" ] || { rm $@ && false; }
115
116 # ------------
117 # ocaml object
118 # ------------
119 o=$(filter %.o,$(targets))
120 %.o: %.c
121 ocamlfind ocamlc -ccopt -o -ccopt $@ -c $(OCAML_FLAGS) $(OCAMLCC_FLAGS) $(if $(DEBUG),-ccopt -Wa$(,)-aln=$*.s) $(filter %.c,$^)
122 %.d: %.c
123 ocamlfind ocamlc -ccopt -o -ccopt $@ -c -nostdlib -ccopt -MM -ccopt -MT"$@\\ $(@:d=o)" -ccopt -MF$@ $(OCAML_FLAGS) $(OCAMLCC_FLAGS) $(OCAMLCC_D_FLAGS) $<
124
125 # -----------
126 # ocaml lexer
127 # -----------
128 %.ml: %.mll
129 ocamllex $<
130 touch -r $< $@ # NOTE: to avoid rebuilding %.d
131
132 # ------------
133 # ocaml module
134 # ------------
135 cm=$(filter %.cm,$(targets))
136 lock_ro_cmi=$(if $(and $(byte),$(native),$(is_parallel)),$(call \
137 flocks,-s,$(patsubst %.cmx,%.cmi,$(patsubst %.cmo,%.cmi, \
138 $(filter %.cmi,$^) $(filter %.cmo,$^) $(filter %.cmx,$^))),$1),$1)
139 lock_rw_cmi=$(if $(and $(byte),$(native),$(is_parallel)),$(call \
140 flock,-x,$*.cmi,$(call \
141 flocks,-s,$(patsubst %.cmx,%.cmi,$(patsubst %.cmo,%.cmi, \
142 $(filter %.cmi,$^) $(filter %.cmo,$^) $(filter %.cmx,$^))),$1)),$1)
143 %.cmo %.cmi: %.ml
144 $(call lock_rw_cmi,ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLC_FLAGS) $(filter %.ml,$^))
145 %.cmx %cmi %.o: %.ml
146 $(call lock_rw_cmi,ocamlfind ocamlopt -o $*.cmx -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLOPT_FLAGS) $(filter %.ml,$^))
147 %.cmxs %.cmx %.cmi %.o: %.ml
148 $(call lock_rw_cmi,ocamlfind ocamlopt -shared -o $*.cmxs $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLOPT_FLAGS) $(filter %.ml,$^))
149
150 # ----------
151 # ocaml pack
152 # ----------
153 %.cmo %.cmi: %/$(GNUmakefile.inc)
154 $(call lock_rw_cmi,ocamlfind ocamlc -pack -o $*.cmo $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(OCAMLC_PACK_FLAGS) $(filter %.cmo,$^))
155 %.cmx %.cmi %.o: %/$(GNUmakefile.inc)
156 $(call lock_rw_cmi,ocamlfind ocamlopt -pack -o $*.cmx $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(OCAMLOPT_PACK_FLAGS) $(filter %.cmx,$^))
157
158 # --------------
159 # object archive
160 # --------------
161 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))))
162 a=$(filter %.a,$(targets))
163 %.a:
164 $(call flock,-x,$(dir $*),ar cSru$(AR_FLAGS) $@ $(call \
165 map,o_of_a,$(filter %.a,$^)) $(filter %.o,$^) && ranlib $(RANLIB_FLAGS) $@)
166 dll%.so: CC=$(shell ocamlfind ocamlc -config | sed -ne 's/^native_c_compiler: *//p')
167 dll%.so: lib%.a
168 $(CC) -o $@ -shared $(filter %.o,$(shell ar t $<))
169
170 # -------------
171 # ocaml archive
172 # -------------
173 ca=$(filter %.ca,$(targets))
174 %.cma:
175 $(call lock_ro_cmi,ocamlfind ocamlc -a -o $@ $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(OCAML_ARCH_FLAGS) $(OCAMLC_ARCH_FLAGS) $(filter %.cmo,$^))
176 %.cmxa:
177 $(call lock_ro_cmi,ocamlfind ocamlopt -a -o $@ $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(OCAML_ARCH_FLAGS) $(OCAMLOPT_ARCH_FLAGS) $(filter %.cmx,$^))
178
179 # ------------
180 # ocaml binary
181 # ------------
182 cb=$(filter %.cb,$(targets))
183 %.byte:
184 $(call lock_ro_cmi,ocamlfind ocamlc -o $@ -linkpkg $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLC_FLAGS) $(OCAML_BIN_FLAGS) $(OCAMLC_BIN_FLAGS) $(filter %.cmo,$^))
185 %.native:
186 $(call lock_ro_cmi,ocamlfind ocamlopt -o $@ -linkpkg $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLOPT_FLAGS) $(OCAML_BIN_FLAGS) $(OCAMLOPT_BIN_FLAGS) $(filter %.cmx,$^))
187
188 # -----------------
189 # binary capability
190 # -----------------
191 %.caps: setcap=$(shell PATH="$$PATH:/sbin"; which setcap)
192 %.caps: %
193 $(if $(caps),[ ! -x "$(setcap)" ] || $(setcap) "$(caps)" $*)
194
195 # ----------------
196 # binary execution
197 # ----------------
198 .PHONY: %.byte.exec %.native.exec
199 %.byte.exec: %.byte
200 PATH=".:$$PATH"; \
201 $< $(EXEC_FLAGS) $(EXEC_BYTE_FLAGS)
202 %.native.exec: %.native
203 PATH=".:$$PATH"; \
204 $< $(EXEC_FLAGS) $(EXEC_NATIVE_FLAGS)
205
206 # ---------------
207 # ocaml debugging
208 # ---------------
209 .PHONY: debug
210 export DEBUG
211 debug: $(filter-out debug,$(MAKECMDGOALS))
212 debug: override OCAML_FLAGS+=-verbose
213 debug: override OCAMLC_FLAGS+=-g -principal
214 debug: override OCAMLCC_FLAGS+=-ccopt -ggdb3
215 debug: override OCAMLDEP_FLAGS+=-verbose
216 debug: override OCAMLOPT_FLAGS+=-ccopt -ggdb3
217 debug: override OCAMLRUNPARAM+=b
218 debug: override DEBUG:=debug