]> Git — Sourcephile - ocaml/libocaml_make.git/blob - GNUmakefile
Ajout : %.cm{o,x}/clean .
[ocaml/libocaml_make.git] / GNUmakefile
1 # ---------
2 # ocaml env
3 # ---------
4 OCAML_FLAGS?=-w @a-4-6-7-9-23-26-27-29-41
5 OCAMLCC_FLAGS?=-ccopt -Werror -ccopt -Wall -ccopt -Wextra
6 OCAMLCC_D_FLAGS?=-ccopt -Wno-error
7 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 ocamlc_version:=$(shell ocamlfind ocamlc -version)
15 ocamlopt_version:=$(shell ocamlfind ocamlopt -version)
16 filter-flag=$(if $2 \
17 ,$(if $(patsubst $1,,$(firstword $2)), \
18 $(call filter-flag,$1,$(wordlist 2,$(words $2),$2)), \
19 $(wordlist 2,2,$2) $(call filter-flag,$1,$(wordlist 3,$(words $2),$2))) \
20 ,)
21 dllpath-pkg-recursive=$(call filter-flag,-dllpath,$(shell \
22 OCAMLPATH='$(OCAMLPATH)' \
23 OCAMLFIND_COMMANDS='ocamlc=echo' \
24 ocamlfind ocamlc -dllpath-all $1))
25 dirname=$(patsubst %/,%,$(dir $1))
26 filter-dir=$(patsubst %/.,%,$(wildcard $(patsubst %,%/.,$1)))
27 filter-dir-out=$(foreach x,$1,$(if $(call filter-dir,$x),,$x))
28 flock=flock $1 $2 -c "$(subst ",\",$(subst \,\\,$3))"
29 flocks=$(if $2,$(call \
30 flock,$1,$(firstword $2),$(call \
31 flocks,$1,$(wordlist 2,$(words $2),$2),$3)),$3)
32 GNUmakefile.inc?=GNUmakefile.inc
33 if_arg=$(if $2,$1 $2)
34 is_parallel=$(findstring j,$(value MAKEFLAGS))
35 map=$(foreach x,$2,$(call $1,$x))
36 mul=$(foreach p,$1,$(foreach s,$2,$p$s))
37 rev=$(if $1,$(call \
38 rev,$(wordlist 2,$(words $1),$1))) $(firstword $1)
39 uniq=$(if $1,$(call \
40 uniq,$(wordlist 2,$(words $1),$1),$2 $(if \
41 $(filter $(firstword $1),$2),,$(firstword $1)))\
42 ,$2)
43 ,:=,
44 .SECONDARY:
45 .SUFFIXES:
46 MAKEFLAGS += -r
47 .SHELLFLAGS += -e
48
49 # -----
50 # clean
51 # -----
52 rmw=$(call if_arg,rm,$(wildcard $1))
53 cleaner+=$(or $(filter cc,$(MAKECMDGOALS)),$(filter %/cc,$(MAKECMDGOALS)),$(filter cleaner,$(MAKECMDGOALS)),$(filter %/cleaner,$(MAKECMDGOALS)))
54 clean+=$(or $(filter c,$(MAKECMDGOALS)),$(filter %/c,$(MAKECMDGOALS)),$(filter clean,$(MAKECMDGOALS)),$(filter %/clean,$(MAKECMDGOALS)))$(cleaner)
55 LIBOCAML_MAKE_NO_DEPS+=$(or $(clean),$(cleaner))
56 %.ml/clean: %.mll
57 $(call rmw,$(@:/clean=))
58 %.ml/clean:
59
60 %.mli/clean:
61 $(call rmw,$(if $(cleaner),$*.d))
62 %.o/clean:
63 $(call rmw,$(@:/clean=) $*.s $(if $(cleaner),$*.d))
64 %.a/clean: %.a.clean
65
66 lib%.a.clean: dll%.so.clean
67 $(call rmw,$(@:.clean=))
68 %.so/clean: %.so.clean
69
70 dll%.so.clean: lib%.so.clean
71 $(call rmw,$(@:.clean=))
72 lib%.so.clean:
73 $(call rmw,$(@:.clean=))
74 %.cmo/clean: %.ml/clean
75 $(call rmw,$*.cmo $*.cmi $(if $(cleaner),$*.d))
76 %.cmx/clean: %.ml/clean
77 $(call rmw,$*.cmx $*.cmxs $*.o $*.s $*.startup.s $*.cmi $(if $(cleaner),$*.d))
78 %.cm/clean %.cd/clean: %.ml/clean
79 $(call rmw,$*.cmo $*.cmx $*.cmxs $*.o $*.s $*.startup.s $*.cmi $(if $(cleaner),$*.d))
80 %.cmi/clean: %.mli/clean
81 $(call rmw,$*.cmi $(if $(cleaner),$*.d))
82 %.ca/clean:
83 $(call rmw,$*.cma $*.cmxa $*.a)
84 %.cb/clean:
85 $(call rmw,$*.byte $*.native)
86 %/configure/clean:
87 $(call rmw,$(@:/clean=.*) $*/pa_configure.ml)
88
89 # ---------------------
90 # ocaml GNUmakefile.inc
91 # ---------------------
92 define make_GNUmakefile.inc
93 d := $1
94 dir_ptr := $$(dir_ptr).level
95 dirstack_$$(dir_ptr) := $$d
96
97 Pack := $$(if $$(Pack),$$(Pack).)$$(call camlcase,$$(notdir $1))
98
99 targets :=
100
101 ifneq ($$(wildcard $1/configure),)
102 ifeq ($$(clean),)
103 include $1/configure.make
104 endif
105 endif
106
107 include $1/$(GNUmakefile.inc)
108
109 ifeq ($$(LIBOCAML_MAKE_NO_DEPS),)
110 -include $$(wildcard $$(o:.o=.d) $$(cm:.cm=.d) $$(cd:.cd=.d))
111 endif
112
113 dirs := $$(call filter-dir,$$(filter-out $1,$$(call uniq,$$(basename $$(targets)))))
114
115 $1/c $1/clean: clean:=clean
116 $1/cc $1/cleaner: cleaner:=cleaner
117 $1/b $1/byte: byte:=byte
118 $1/n $1/native: native:=native
119 ifneq ($(ocamlc_version),)
120 $1/all: byte:=byte
121 endif
122 ifneq ($(ocamlopt_version),)
123 $1/all: native:=native
124 endif
125
126 # NOTE: no .PHONY: to trigger %/clean
127 $1/clean: $$(addsuffix /clean,$$(targets))
128 $1/clean: $1/configure/clean
129 $1/cleaner: $1/clean
130 $1/c: $1/clean
131 $1/cc: $1/cleaner
132
133
134 ifeq ($$(LIBOCAML_MAKE_NO_DEPS),)
135 targets := $$(foreach t,$$(targets), \
136 $$t \
137 $$(if $$(filter %.o,$$t)$$(filter %.cm,$$t)$$(filter %.cd,$$t) \
138 ,$$(if $$(wildcard $$(basename $$t)),,$$(basename $$t).d)))
139 endif
140
141 $1/byte: $$(patsubst %.cb,%.byte, $$(patsubst %.ca,%.cma, $$(patsubst %.cm,%.cmo,$$(patsubst %.cd,%.cmo, $$(targets)))))
142 $1/native: $$(patsubst %.cb,%.native,$$(patsubst %.ca,%.cmxa,$$(patsubst %.cm,%.cmx,$$(patsubst %.cd,%.cmxs,$$(targets)))))
143 $1/all: $(if $(ocamlc_version),$1/byte) $(if $(ocamlopt_version),$1/native)
144 $1/exec-byte: $$(cb:.cb=.byte.exec)
145 $1/exec-native: $$(cb:.cb=.native.exec)
146 $1/b: $1/byte
147 $1/n: $1/native
148 $1/xb: $1/exec-byte
149 $1/xn: $1/exec-native
150
151 $$(foreach d,$$(dirs), \
152 $$(eval $1/clean: $$d/clean) \
153 $$(eval $1/cleaner: $$d/cleaner) \
154 $$(eval $1/byte: $$d/byte) \
155 $$(eval $1/native: $$d/native) \
156 $$(eval $1/exec-byte: $$d/exec-byte) \
157 $$(eval $1/exec-native: $$d/exec-native) \
158 $$(call include_GNUmakefile.inc,$$d))
159
160 Pack := $$(if $$(findstring .,$$(Pack)),$$(basename $$(Pack)),)
161
162 d := $$(dirstack_$$(dir_ptr))
163 dir_ptr := $$(basename $$(dir_ptr))
164
165 endef
166 include_GNUmakefile.inc = $(eval $(call make_GNUmakefile.inc,$(or $1,.)))
167
168 # ---------------
169 # ocaml configure
170 # ---------------
171 %/configure.c %/configure.log %/configure.make %/configure.ml %/pa_configure.ml): %/configure
172 ocaml $< $(CONFIGURE_FLAGS)
173
174 # ----------
175 # ocaml deps
176 # ----------
177 %.d: %.mli %.ml
178 ocamlfind ocamldep $(OCAML_DEPS_FLAGS) $(OCAMLDEP_FLAGS) $*.mli >$@ || { rm $@ && false; }
179 errnos=`{ { ocamlfind ocamldep $(OCAML_DEPS_FLAGS) $(OCAMLDEP_FLAGS) $*.ml || echo >&3 0:$$?; } | \
180 { sed >>$@ -e 's/^[^ ]*\.cmx/&s \\\\\n&/' -e 's/ :/:/' || echo >&3 1:$$?; } \
181 } 3>&1` && [ -z "$$errnos" ] || { rm $@ && false; }
182 %.d: %.mli
183 ocamlfind ocamldep $(OCAML_DEPS_FLAGS) $(OCAMLDEP_FLAGS) $< >$@ || { rm $@ && false; }
184 %.d: %.ml
185 errnos=`{ { ocamlfind ocamldep $(OCAML_DEPS_FLAGS) $(OCAMLDEP_FLAGS) $< || echo >&3 0:$$?; } | \
186 { sed >$@ -e 's/^[^ ]*\.cmx/&s \\\\\n&/' -e 's/ :/:/' || echo >&3 1:$$?; } \
187 } 3>&1` && [ -z "$$errnos" ] || { rm $@ && false; }
188
189 # ------------
190 # ocaml object
191 # ------------
192 o=$(filter %.o,$(targets))
193 %.o: %.c
194 ocamlfind ocamlc -ccopt -o -ccopt $@ -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLCC_FLAGS) $(foreach x,$(CFLAGS),-ccopt $x) $(foreach x,$(LDFLAGS),-cclib $x) $(if $(DEBUG),-ccopt -Wa$(,)-aln=$*.s) $<
195 %.d: %.c
196 ocamlfind ocamlc -ccopt -o -ccopt $@ -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLCC_FLAGS) $(OCAMLCC_D_FLAGS) -nostdlib -ccopt -MM -ccopt -MT"$@\\ $(@:d=o)" -ccopt -MF$@ $<
197
198 # -----------
199 # ocaml lexer
200 # -----------
201 %.ml: %.mll
202 ocamllex $<
203 touch -r $< $@ # NOTE: to avoid rebuilding %.d
204
205 # ---------------
206 # ocaml interface
207 # ---------------
208 cmi=$(filter %.cmi,$(targets))
209 %.cmi: %.mli
210 $(call lock_rw_cmi,ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAML_INTF_FLAGS) $(filter %.mli,$^))
211 %.cmi: %.ml
212
213
214 # ------------
215 # ocaml module
216 # ------------
217 cm=$(filter %.cm,$(targets))
218 cd=$(filter %.cd,$(targets))
219 lock_ro_cmi=$(if $(and $(byte),$(native),$(is_parallel)),$(call \
220 flocks,-s,$(patsubst %.cmx,%.cmi,$(patsubst %.cmo,%.cmi, \
221 $(filter %.cmi,$^) $(filter %.cmo,$^) $(filter %.cmx,$^))),$1),$1)
222 lock_rw_cmi=$(if $(and $(byte),$(native),$(is_parallel)),$(call \
223 flock,-x,$*.cmi,$(call \
224 flocks,-s,$(patsubst %.cmx,%.cmi,$(patsubst %.cmo,%.cmi, \
225 $(filter %.cmi,$^) $(filter %.cmo,$^) $(filter %.cmx,$^))),$1)),$1)
226 %.cmo: %.ml %.cmi
227 $(call lock_rw_cmi,ocamlfind ocamlc -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLC_FLAGS) $(filter %.ml,$^))
228 %.cmx %.o: %.ml %.cmi
229 $(call lock_rw_cmi,ocamlfind ocamlopt -c $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLOPT_FLAGS) $(filter %.ml,$^))
230 %.cmxs %.cmx %.o: %.ml %.cmi
231 $(call lock_rw_cmi,ocamlfind ocamlopt -shared -o $*.cmxs $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLOPT_FLAGS) $(filter %.ml,$^))
232 # NOTE : remember to install the .cmx files as they enable cross-module optimizations
233
234 # ----------
235 # ocaml pack
236 # ----------
237 %.cmo %.cmi: | %
238 $(call lock_rw_cmi,ocamlfind ocamlc -pack -o $*.cmo $(OCAML_FLAGS) $(OCAMLC_FLAGS) $(OCAMLC_PACK_FLAGS) $(filter %.cmo,$^))
239 %.cmx %.cmi %.o: | %
240 $(call lock_rw_cmi,ocamlfind ocamlopt -pack -o $*.cmx $(OCAML_FLAGS) $(OCAMLOPT_FLAGS) $(OCAMLOPT_PACK_FLAGS) $(filter %.cmx,$^))
241
242 # --------------
243 # object archive
244 # --------------
245 a=$(filter %.a,$(targets))
246 lock_rw_a=$(if $(is_parallel),$(call flock,-x,$(@D),$1),$1)
247 lib%.a dll%.so:
248 $(call lock_rw_a,ocamlfind ocamlmklib -failsafe $(OCAML_DEPS_FLAGS) $(OCAMLMKLIB_FLAGS) -oc $* $(OCAMLMKLIB_OBJECT_FLAGS) $(foreach x,$(LDFLAGS),-ldopt $x) $(filter %.o,$^) \
249 $(if $(STRIP), && strip --strip-unneeded $(STRIP_FLAGS) $(STRIP_LIB_FLAGS) $(@D)/lib$(*F).a \
250 && if [ -e '$(@D)/dll$(*F).so' ]; then strip $(STRIP_FLAGS) $(STRIP_DLL_FLAGS) $(@D)/dll$(*F).so; fi))
251
252 # -------------
253 # ocaml archive
254 # -------------
255 ca=$(filter %.ca,$(targets))
256 %.cma:
257 $(if $(filter %.a,$^), \
258 $(call lock_ro_cmi,ocamlfind ocamlmklib -o $* \
259 -oc $(patsubst lib%.a,%,$(notdir $(firstword $(filter %.a,$^)))) \
260 $(OCAML_DEPS_FLAGS) $(OCAMLMKLIB_FLAGS) $(OCAMLMKLIB_OCAML_FLAGS) $(OCAMLMKLIB_BYTE_FLAGS) \
261 $(filter %.cmo,$^)), \
262 $(call lock_ro_cmi,ocamlfind ocamlc -a -o $@ $(OCAMLC_ARCHIVE_FLAGS) $(filter %.cmo,$^)))
263 %.cmxa:
264 $(if $(filter %.a,$^), \
265 $(call lock_ro_cmi,ocamlfind ocamlmklib -o $* \
266 -oc $(patsubst lib%.a,%,$(notdir $(firstword $(filter %.a,$^)))) \
267 $(OCAML_DEPS_FLAGS) $(OCAMLMKLIB_FLAGS) $(OCAMLMKLIB_OCAML_FLAGS) $(OCAMLMKLIB_NATIVE_FLAGS) \
268 $(filter %.cmx,$^)), \
269 $(call lock_ro_cmi,ocamlfind ocamlopt -a -o $@ $(OCAMLOPT_ARCHIVE_FLAGS) $(filter %.cmx,$^)))
270
271 # ------------
272 # ocaml binary
273 # ------------
274 cb=$(filter %.cb,$(targets))
275 %.byte:
276 $(call lock_ro_cmi,ocamlfind ocamlc -o $@ -linkpkg $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLC_FLAGS) $(OCAML_BIN_FLAGS) $(OCAMLC_BIN_FLAGS) $(filter %.cmo,$^))
277 %.native:
278 $(call lock_ro_cmi,ocamlfind ocamlopt -o $@ -linkpkg $(OCAML_FLAGS) $(OCAML_DEPS_FLAGS) $(OCAMLOPT_FLAGS) $(OCAML_BIN_FLAGS) $(OCAMLOPT_BIN_FLAGS) $(filter %.cmx,$^) \
279 $(if $(STRIP), && strip $(STRIP_FLAGS) $(STRIP_NATIVE_FLAGS) $@))
280
281 # -------------
282 # ocaml linking
283 # -------------
284 ocaml_stublibs/=$(abspath $d/stublibs)
285 %/dynamic: export LINKING_MODE=dynamic
286 %/dynamic: ,ocaml-predicates= \
287 $(patsubst -thread,$(,)mt$(,)mt_posix threads.posix,$(filter -thread,$(OCAML_DEPS_FLAGS)))
288 %/dynamic: ocaml-packages= \
289 $(shell OCAMLPATH='$(OCAMLPATH)' ocamlfind query -recursive -format %p \
290 -predicates byte$(,ocaml-predicates) \
291 $(call filter-flag,-package,$(OCAML_DEPS_FLAGS)))
292 %/dynamic: ocaml-dll=$(shell ocamlobjinfo \
293 $$(OCAMLPATH='$(OCAMLPATH)' ocamlfind query -recursive -format %d/%a \
294 -predicates byte$(,ocaml-predicates) $(ocaml-packages)) | sed -n \
295 -e '/^Extra dynamically-loaded libraries:/{s/^[^:]*://;p}')
296 %/dynamic: \
297 override OCAMLOPT_BIN_FLAGS+= \
298 -noautolink \
299 -cclib -L$(shell ocamlfind printconf stdlib)/stublibs \
300 $(shell ocamlobjinfo \
301 $$(OCAMLPATH='$(OCAMLPATH)' ocamlfind query -recursive -format %d/%a \
302 -predicates native$(,ocaml-predicates) $(ocaml-packages) | \
303 { \
304 set --; \
305 while IFS= read -r line; \
306 do set -- "$$line" "$$@"; \
307 done; \
308 printf '%s\n' "$$@"; \
309 }) | sed -n \
310 -e '/^Extra C options:/{s/^[^:]*://;s/[^ ][^ ]*/-ccopt \0/g;p}' \
311 -e '/^Extra C object files:/{s/^[^:]*://; \
312 $(patsubst -l%,s/ -l\(%\)\( \|$$\)/ -l:dll\1.so /g;,$(ocaml-dll))s/[^ ][^ ]*/-cclib \0/g;p}')
313 # NOTE: the above rule enables the dynamic linking
314 # against dll*.so in native code, by rewriting
315 # the -l* flags for ocaml stubs (listed in .cma archives)
316 # embedded in *.cmxa archives, to -l:dll*.so flags.
317 # Beware that the paths where dll*.so are found at link-time
318 # will be used at runtime to load them.
319 # Note also that the gain in size is likely to be small
320 # and not worth the complexity of dynamic linking.
321 %/dynamic: %
322
323
324 %/static: export LINKING_MODE=static
325 %/static: override OCAMLMKLIB_FLAGS+=-custom
326 %/static: override OCAMLC_FLAGS+=-custom -ccopt -static -cclib -Wl,--start-group -cclib -ltermcap
327 # NOTE : with static linking -lcamlrun needs -ltermcap
328 # this unclosed (sic) --start-group is needed
329 # because ocamlc puts -lcamlrun after all the -cclib .
330 %/static: override OCAMLOPT_FLAGS+=-nodynlink -ccopt -static $(if $(filter x86_64,$(shell uname -m)),-fno-PIC)
331 %/static: %
332
333
334 %/strip: export STRIP=strip
335 %/strip: %
336
337
338 # -----------------
339 # binary capability
340 # -----------------
341 %.caps: setcap=$(shell PATH="$$PATH:/sbin"; which setcap)
342 %.caps: %
343 $(if $(caps),[ ! -x "$(setcap)" ] || $(setcap) "$(caps)" $*)
344
345 # ----------------
346 # binary execution
347 # ----------------
348 .PHONY: %.byte.exec %.native.exec
349 %.byte.exec: %.byte
350 PATH=".:$$PATH"; \
351 $< $(EXEC_FLAGS) $(EXEC_BYTE_FLAGS)
352 %.native.exec: %.native
353 PATH=".:$$PATH"; \
354 $< $(EXEC_FLAGS) $(EXEC_NATIVE_FLAGS)
355
356 # ---------------
357 # ocaml debugging
358 # ---------------
359 export DEBUG
360 %/debug: override OCAML_FLAGS+=-verbose
361 %/debug: override OCAMLC_FLAGS+=-g -principal
362 %/debug: override OCAMLCC_FLAGS+=-ccopt -ggdb3 -ccopt -rdynamic -ccopt -DDEBUG
363 %/debug: override OCAMLMKLIB_FLAGS+=-verbose
364 %/debug: override OCAMLOPT_FLAGS+=-principal -ccopt -ggdb3 -ccopt -rdynamic
365 %/debug: override OCAMLRUNPARAM+=b
366 %/debug: override DEBUG:=debug
367 %/debug: %
368
369
370 $(call include_GNUmakefile.inc,$(SRCDIR))