propset - enables svn keywords
[build.git] / Makefile
1 #
2 # Thierry Parmentelat - INRIA Sophia Antipolis 
3 #
4 ### $Id$
5
6 # run 'make help' for more info
7
8 #################### Makefile
9 # Default target
10 all:
11 .PHONY:all
12
13 ### default values
14 PLDISTRO := onelab
15 RPMBUILD := rpmbuild
16 export CVS_RSH := ssh
17
18 ########## pldistro.mk holds PLDISTRO - it is generated at stage1 (see below)
19 ifeq "$(stage1)" ""
20 include pldistro.mk
21 endif
22
23 #################### include onelab.mk
24 # describes the set of components
25 PLDISTROCONTENTS := $(PLDISTRO).mk
26 include $(PLDISTROCONTENTS)
27
28 #################### include <pldistro>-tags.mk
29 # describes where to fetch components, and the related tags if using cvs
30 PLDISTROTAGS := $(PLDISTRO)-tags.mk
31 include $(PLDISTROTAGS)
32
33 ########## stage1 and stage2
34 # extract specs and compute .mk files by running 
35 # make stage1=true
36 # entering stage1, we compute all the spec files
37 # then we use stage2 to compute the .mk iteratively, 
38 # ensuring that the n-1 first makefiles are loaded when creating the n-th one
39 # when stage2 is set, it is supposed to be an index (starting at 1) in $(ALL)
40
41 ALLMKS := $(foreach package, $(ALL), MAKE/$(package).mk)
42
43 ### stage2 : need some arithmetic, see
44 # http://www.cmcrossroads.com/articles/ask-mr.-make/learning-gnu-make-functions-with-arithmetic.html
45 ifneq "$(stage2)" ""
46 # the first n packages
47 packages := $(wordlist 1,$(words $(stage2)),$(ALL))
48 # the n-th package
49 package := $(word $(words $(packages)),$(packages))
50 # the n-1 first packages
51 stage2_1 := $(wordlist 2,$(words $(stage2)),$(stage2))
52 previous := $(wordlist 1,$(words $(stage2_1)),$(ALL))
53 previousmks := $(foreach package,$(previous),MAKE/$(package).mk)
54 include $(previousmks)
55 all: verbose
56 verbose:
57         @echo "========== stage2 : $(package)"
58         @echo "stage2 : included .mk files : $(previousmks)"
59 all: $($(package)_specpath)
60 all: MAKE/$(package).mk
61 else
62 ### stage1
63 ifneq "$(stage1)" ""
64 all : verbose
65 verbose :
66         @echo "========== stage1"
67 all : spec2make
68 all : .rpmmacros
69 # specs and makes are done sequentially by stage2
70 all : stage2
71 stage2:
72         arg=""; for n in $(ALL) ; do arg="$$arg x"; $(MAKE) --no-print-directory stage2="$$arg"; done
73 ### regular make
74 else
75 ### once .mks are OK, you can run make normally
76 include $(ALLMKS)
77 #all : tarballs
78 #all : sources
79 #all : codebases
80 #all : rpms
81 #all : srpms
82 # mention $(ALL) here rather than rpms 
83 # this is because the inter-package dependencies are expressed like
84 # util-vserver: util-python
85 all: $(ALL)
86 all: srpms
87 endif
88 endif
89
90 ####################
91 # gather build information for the 'About' page
92 SOURCES/myplc-release:
93         @echo 'Creating myplc-release'
94         mkdir -p SOURCES
95         rm -f $@
96         (echo -n 'Build bdate: ' ; date '+%Y.%m.%d') >> $@
97         (echo -n 'Build btime: ' ; date '+%H:%M') >> $@
98         (echo -n 'Build hostname: ' ; hostname) >> $@
99         (echo -n 'Build location: ' ; pwd) >> $@
100         (echo -n 'Build tags file: ' ; fgrep '$$''Id' $(PLDISTROTAGS)) >> $@
101         echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx modules versions info" >> $@
102         $(MAKE) --no-print-directory versions >> $@
103
104 ####################
105 # notes: 
106 # * to make configuration easier, we always use the first module's
107 # definitions (CVSROOT,TAG, or SVNPATH) to extract the spec file
108 # * for the same reason, in case cvs is used, the first module name is added to 
109 # $(package)-SPEC - otherwise the cvs modules have to define spec as 
110 # <module>/<module>.spec while svn modules just define it as <module>.spec
111 #
112 define stage1_variables
113 $(1)_spec = $(notdir $($(1)-SPEC))
114 $(1)_specpath = SPECS/$(notdir $($(1)-SPEC))
115 $(1)_module = $(firstword $($(1)-MODULE))
116 endef
117
118 $(foreach package, $(ALL), $(eval $(call stage1_variables,$(package))))
119
120 #
121 # for each package, compute whether we need to set date (i.e. whether we use the trunk)
122 # the myplc package is forced to have a date, because it is more convenient
123 # (we cannot bump its number everytime something changes in the system)
124
125 define package_hasdate
126 $(1)_hasdate = $(if $(subst myplc,,$(1)), \
127                   $(if $($(1)-SVNPATH),\
128                      $(if $(findstring /trunk,$($(1)-SVNPATH)),yes,),\
129                      $(if $(findstring HEAD,$($(1)-TAG)),yes,)), \
130                 yes)
131 endef
132
133 $(foreach package, $(ALL), $(eval $(call package_hasdate,$(package))))
134
135 ### extract spec file from scm
136 # usage: extract_spec_file package 
137 # see early releases for comments on other possible implementations
138 # cannot use variables in such rules, we need to inline everything, sigh
139 define target_spec
140 $($(1)_specpath):
141         mkdir -p SPECS
142         echo "%define pldistro $(PLDISTRO)" > $($(1)_specpath)
143         $(if $($(1)_hasdate),echo "%define date $(shell date +%Y.%m.%d)" >> $($(1)_specpath),)
144         $(if $($(1)-SPECVARS), \
145           $(foreach line,$($(1)-SPECVARS), \
146             echo "%define" $(word 1,$(subst =, ,$(line))) "$(word 2,$(subst =, ,$(line)))" >> $($(1)_specpath) ;))
147         $(if $($($(1)_module)-SVNPATH),\
148           svn cat $($($(1)_module)-SVNPATH)/$($(1)-SPEC) >> $($(1)_specpath),\
149           cvs -d $($($(1)_module)-CVSROOT) checkout \
150               -r $($($(1)_module)-TAG) \
151               -p $($(1)_module)/$($(1)-SPEC) >> $($(1)_specpath))
152         @if [ -z $($(1)_specpath) ] ; then rm $($(1)_specpath) ; exit 1 ; fi
153 endef
154
155 $(foreach package,$(ALL),$(eval $(call target_spec,$(package))))
156
157 ### this utility allows to extract various info from a spec file
158 ### and to define them in makefiles
159 spec2make: spec2make.c
160         $(CC) -g -Wall $< -o $@ -lrpm -lrpmbuild
161
162 # Base rpmbuild in the current directory
163 export HOME := $(shell pwd)
164 .rpmmacros:
165         echo "%_topdir $(HOME)" > $@
166         echo "%_tmppath $(HOME)/tmp" >> $@
167
168 ### run spec2make on the spec file and include the result
169 # usage: spec2make package
170 define target_mk
171 MAKE/$(1).mk: $($(1)_specpath) spec2make .rpmmacros
172         mkdir -p MAKE
173         ./spec2make $($(1)-RPMFLAGS) $($(1)_specpath) $(1) > MAKE/$(1).mk
174         @if [ -z MAKE/$(1).mk ] ; then rm MAKE/$(1).mk ; exit 1 ; fi
175 endef
176
177 $(foreach package,$(ALL),$(eval $(call target_mk,$(package))))
178
179 # stores PLDISTRO in a file
180 # this is done at stage1. later run wont get confused
181 pldistro.mk:
182         echo "PLDISTRO:=$(PLDISTRO)" > $@
183         echo "PLDISTROTAGS:=$(PLDISTROTAGS)" >> $@
184
185 savepldistro: pldistro.mk
186 .PHONY: savepldistro
187
188 # always refresh this
189 all: savepldistro
190
191 ####################
192 ### pack sources into tarballs
193 ALLTARBALLS:= $(foreach package, $(ALL), $($(package)-TARBALL))
194 tarballs: $(ALLTARBALLS)
195         @echo $(words $(ALLTARBALLS)) source tarballs OK
196 .PHONY: tarballs
197
198 SOURCES/%.tar.bz2: SOURCES/%
199         tar chpjf $@ -C SOURCES $*
200
201 SOURCES/%.tar.gz: SOURCES/%
202         tar chpzf $@ -C SOURCES $*
203
204 SOURCES/%.tgz: SOURCES/%
205         tar chpzf $@ -C SOURCES $*
206
207 ### the directory SOURCES/<package>-<version> is made 
208 # with a copy -rl from CODEBASES/<package>
209 # the former is $(package-SOURCE) and the latter is $(package-CODEBASE)
210 ALLSOURCES:=$(foreach package, $(ALL), $($(package)-SOURCE))
211 # so that make does not use the rule below directly for creating the tarball files
212 .SECONDARY: $(ALLSOURCES)
213
214 sources: $(ALLSOURCES)
215         @echo $(words $(ALLSOURCES)) versioned source trees OK
216 .PHONY: sources
217
218 define target_link_codebase_sources
219 $($(1)-SOURCE): $($(1)-CODEBASE) ; mkdir -p SOURCES ; cp -rl $($(1)-CODEBASE) $($(1)-SOURCE)
220 endef
221
222 $(foreach package,$(ALL),$(eval $(call target_link_codebase_sources,$(package))))
223
224 ### codebase extraction
225 ALLCODEBASES:=$(foreach package, $(ALL), $($(package)-CODEBASE))
226 # so that make does not use the rule below directly for creating the tarball files
227 .SECONDARY: $(ALLCODEBASES)
228
229 codebases : $(ALLCODEBASES)
230         @echo $(words $(ALLCODEBASES)) codebase OK
231 .PHONY: codebases
232
233 ### extract codebase 
234 # usage: extract_single_module package 
235 define extract_single_module
236         mkdir -p CODEBASES
237         $(if $($($(1)_module)-SVNPATH), cd CODEBASES && svn export $($($(1)_module)-SVNPATH) $(1), cd CODEBASES && cvs -d $($($(1)_module)-CVSROOT) export -r $($($(1)_module)-TAG) -d $(1) $($(1)_module))
238 endef
239
240 # usage: extract_multi_module package 
241 define extract_multi_module
242         mkdir -p CODEBASES/$(1) && cd CODEBASES/$(1) && (\
243         $(foreach m,$($(1)-MODULE), $(if $($(m)-SVNPATH), svn export $($(m)-SVNPATH) $(m);, cvs -d $($(m)-CVSROOT) export -r $($(m)-TAG) $(m);)))
244 endef
245
246 CODEBASES/%: package=$(notdir $@)
247 CODEBASES/%: module=$($(package)-MODULE)
248 CODEBASES/%: multi_module=$(word 2,$(module))
249 CODEBASES/%: 
250         @(echo -n "XXXXXXXXXXXXXXX -- BEG CODEBASE $(package) : $@ " ; date)
251         $(if $(multi_module),\
252           $(call extract_multi_module,$(package)),\
253           $(call extract_single_module,$(package)))
254         @(echo -n "XXXXXXXXXXXXXXX -- END CODEBASE $(package) : $@ " ; date)
255
256 ### rpmbuild invokation
257 ALLRPMS:=$(foreach package,$(ALL),$($(package)-RPM))
258 # same as above, mention $(ALL) and not $(ALLRPMS)
259 rpms: $(ALL)
260         @echo $(words $(ALLRPMS)) binary rpms OK
261 .PHONY: rpms
262
263 # usage: build_binary_rpm package
264 # xxx hacky - invoke createrepo if DEPENDFILES mentions RPMS/yumgroups.xml
265 define target_binary_rpm 
266 $($(1)-RPM): $($(1)_specpath) $($(1)-TARBALL) .rpmmacros
267         mkdir -p BUILD RPMS tmp
268         @(echo -n "XXXXXXXXXXXXXXX -- BEG RPM $(1) " ; date)
269         $(if $(findstring RPMS/yumgroups.xml,$($(1)-DEPENDFILES)), createrepo --quiet -g yumgroups.xml RPMS/ , )
270         $(if $($(1)-RPMBUILD),\
271           $($(1)-RPMBUILD) $($(1)-RPMFLAGS) -bb $($(1)_specpath), \
272           $(RPMBUILD)  $($(1)-RPMFLAGS) -bb $($(1)_specpath))
273         @(echo -n "XXXXXXXXXXXXXXX -- END RPM $(1) " ; date)
274 endef
275
276 $(foreach package,$(ALL),$(eval $(call target_binary_rpm,$(package))))
277
278 ### source rpms
279 ALLSRPMS:=$(foreach package,$(ALL),$($(package)-SRPM))
280 srpms: $(ALLSRPMS)
281         @echo $(words $(ALLSRPMS)) source rpms OK
282 .PHONY: srpms
283
284 # usage: build_source_rpm package
285 define target_source_rpm 
286 $($(1)-SRPM): $($(1)_specpath) $($(1)-TARBALL) .rpmmacros
287         mkdir -p BUILD SRPMS tmp
288         @(echo -n "XXXXXXXXXXXXXXX -- BEG SRPM $(1) " ; date)
289         $(if $($(1)-RPMBUILD),\
290           $($(1)-RPMBUILD) $($(1)-RPMFLAGS) -bs $($(1)_specpath),
291           $(RPMBUILD) $($(1)-RPMFLAGS) -bs $($(1)_specpath))    
292         @(echo -n "XXXXXXXXXXXXXXX -- END SRPM $(1) " ; date)
293 endef
294
295 $(foreach package,$(ALL),$(eval $(call target_source_rpm,$(package))))
296
297 ### RPMS/yumgroups.xml
298 ifndef YUMGROUPS
299 YUMGROUPS := groups/$(PLDISTRO).xml
300 endif
301 RPMS/yumgroups.xml: $(YUMGROUPS)
302         install -D -m 644 $(YUMGROUPS) $@
303
304 ### shorthand target
305 # e.g. make proper -> does propers rpms
306 # usage shorthand_target package
307 define target_shorthand 
308 $(1): $($(package)-RPM)
309 .PHONY: $(1)
310 $(1)-spec: $($(package)-SPEC)
311 .PHONY: $(1)-spec
312 $(1)-mk: $($(package)-MK)
313 .PHONY: $(1)-mk
314 $(1)-tarball: $($(package)-TARBALL)
315 .PHONY: $(1)-tarball
316 $(1)-codebase: $($(package)-CODEBASE)
317 .PHONY: $(1)-source
318 $(1)-source: $($(package)-SOURCE)
319 .PHONY: $(1)-codebase
320 $(1)-rpm: $($(package)-RPM)
321 .PHONY: $(1)-rpm
322 $(1)-srpm: $($(package)-SRPM)
323 .PHONY: $(1)-srpm
324 endef
325
326 $(foreach package,$(ALL),$(eval $(call target_shorthand,$(package))))
327
328 ### dependencies
329 define package_depends_on_file
330 $(1):$(2)
331 $($(1)-RPM):$(2)
332 endef
333
334 define target_dependfiles
335 $(foreach file,$($(1)-DEPENDFILES),$(eval $(call package_depends_on_file,$(1),$(file))))
336 endef
337
338 define package_depends_on_package
339 $(1):$(2)
340 $(1):$($(2)-RPM)
341 $($(1)-RPM):$($(2)-RPM)
342 endef
343
344 define target_depends
345 $(foreach package,$($(1)-DEPENDS),$(eval $(call package_depends_on_package,$(1),$(package))))
346 endef
347
348 $(foreach package,$(ALL),$(eval $(call target_depends,$(package))))
349 $(foreach package,$(ALL),$(eval $(call target_dependfiles,$(package))))
350
351
352 ### clean target
353 # usage: target_clean package
354 define target_clean
355 $(1)-clean-codebase:
356         rm -rf $($(1)-CODEBASE)
357 .PHONY: $(1)-clean-codebase
358 CLEANS += $(1)-clean-codebase
359 $(1)-clean-source:
360         rm -rf $($(1)-SOURCE)
361 .PHONY: $(1)-clean-source
362 CLEANS += $(1)-clean-source
363 $(1)-clean-tarball:
364         rm -rf $($(1)-TARBALL)
365 .PHONY: $(1)-clean-tarball
366 CLEANS += $(1)-clean-tarball
367 $(1)-clean-rpm:
368         rm -rf $($(1)-RPM)
369 .PHONY: $(1)-clean-rpm
370 CLEANS += $(1)-clean-rpm
371 $(1)-clean-srpm:
372         rm -rf $($(1)-SRPM)
373 .PHONY: $(1)-clean-srpm
374 CLEANS += $(1)-clean-srpm
375 $(1)-clean: $(1)-clean-codebase $(1)-clean-source $(1)-clean-tarball $(1)-clean-rpm $(1)-clean-srpm
376 .PHONY: $(1)-clean
377 endef
378
379 $(foreach package,$(ALL),$(eval $(call target_clean,$(package))))
380
381 ### clean precisely
382 clean:
383         $(MAKE) $(CLEANS)
384 .PHONY: clean
385
386 clean-help:
387         @echo Available clean targets
388         @echo $(CLEANS)
389
390 ### brute force clean
391 distclean1:
392         rm -rf pldistro.mk .rpmmacros spec2make SPECS MAKE 
393 distclean2:
394         rm -rf CODEBASES SOURCES BUILD RPMS SRPMS tmp
395 distclean: distclean1 distclean2
396 .PHONY: distclean1 distclean2 distclean
397
398 # xxx tmp - I cannot use this on my mac for local testing
399 ISMACOS=$(findstring Darwin,$(shell uname))
400 ifneq "$(ISMACOS)" ""
401 #################### produce reliable version information
402 # for a given module
403 VFORMAT="%30s := %s\n"
404 define print_version
405 $(1)-version:
406         @$(if $($(1)-SVNPATH),\
407            printf $(VFORMAT) $(1)-SVNPATH "$($(1)-SVNPATH)",\
408            printf $(VFORMAT) $(1)-CVSROOT "$($(1)-CVSROOT)" ; printf $(VFORMAT) $(1)-TAG "$($(1)-TAG)")
409 endef
410
411 # compute all modules
412 ALL-MODULES :=
413 $(foreach package,$(ALL), $(eval ALL-MODULES+=$($(package)-MODULE)))
414 ALL-MODULES:=$(sort $(ALL-MODULES))
415
416 $(foreach module,$(ALL-MODULES), $(eval $(call print_version,$(module))))
417
418 versions: $(foreach module, $(ALL-MODULES), $(module)-version)
419 else
420 versions:
421         @echo "warning : the 'versions' target is not supported on macos"
422 endif
423
424 #################### include install Makefile
425 # the default is to use the distro-dependent install file
426 # however the main distro file can redefine PLDISTROINSTALL
427 ifndef PLDISTROINSTALL
428 PLDISTROINSTALL := $(PLDISTRO)-install.mk
429 endif
430 # only if present
431 -include $(PLDISTROINSTALL)
432
433 ####################
434 help:
435         @echo "Known pakages are"
436         @echo "  $(ALL)"
437         @echo "Run make in two stages:"
438         @echo ""
439         @echo "make stage1=true PLDISTRO=onelab"
440         @echo " -> extracts all spec files in SPECS/ and mk files in MAKE/"
441         @echo "    as well as save PLDISTRO for subsequent runs"
442         @echo ""
443         @echo "Then you can use the following targets"
444         @echo '$ make'
445         @echo "  rebuilds everything"
446         @echo '$ make util-vserver'
447         @echo "  makes the RPMS related to util-vserver"
448         @echo "  equivalent to 'make util-vserver-rpm'"
449         @echo ""
450         @echo "Or, vertically - step-by-step for a given package"
451         @echo '$ make util-vserver-codebase'
452         @echo "  performs codebase extraction in CODEBASES/util-vserver"
453         @echo '$ make util-vserver-source'
454         @echo "  creates source link in SOURCES/util-vserver-<version>"
455         @echo '$ make util-vserver-tarball'
456         @echo "  creates source tarball in SOURCES/util-vserver-<version>.<tarextension>"
457         @echo '$ make util-vserver-rpm'
458         @echo "  build rpm(s) in RPMS/"
459         @echo '$ make util-vserver-srpm'
460         @echo "  build source rpm in SRPMS/"
461         @echo ""
462         @echo "Or, horizontally, reach a step for all known packages"
463         @echo '$ make codebases'
464         @echo '$ make sources'
465         @echo '$ make tarballs'
466         @echo '$ make rpms'
467         @echo '$ make srpms'
468         @echo ""
469         @echo "Cleaning examples"
470         @echo "$ make clean"
471         @echo "  removes the files made by make"
472         @echo "$ make distclean"
473         @echo "  brute-force cleaning, removes entire directories - requires a new stage1"
474         @echo "$ make util-vserver-clean"
475         @echo "  removes codebase, source, tarball, rpm and srpm for util-vserver"
476         @echo "$ make util-vserver-clean-codebase"
477         @echo "  and so on"
478
479
480 #################### convenience, for debugging only
481 # make +foo : prints the value of $(foo)
482 # make ++foo : idem but verbose, i.e. foo=$(foo)
483 ++%: varname=$(subst +,,$@)
484 ++%:
485         @echo "$(varname)=$($(varname))"
486 +%: varname=$(subst +,,$@)
487 +%:
488         @echo "$($(varname))"