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