* tentative merge of the onelab build, be sure to run
[build.git] / Makefile
index 6746aea..bbdfa8d 100644 (file)
--- a/Makefile
+++ b/Makefile
 #
-# PlanetLab RPM generation
+# Thierry Parmentelat - INRIA Sophia Antipolis 
 #
-# Copyright (c) 2003  The Trustees of Princeton University (Trustees).
-# All Rights Reserved.
+### $Id: Makefile 1088 2007-11-15 14:51:33Z thierry $
 # 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: 
-# 
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-# 
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-# 
-#     * Neither the name of the copyright holder nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# $Id: Makefile,v 1.32 2004/05/19 12:35:11 alk-pl_rpm Exp $
-#
+# run 'make help' for more info
 
+#################### Makefile
 # Default target
 all:
+.PHONY:all
 
-#
-# CVSROOT: CVSROOT to use
-# INITIAL: CVS tag to use for Source0 tarball
-# TAG: CVS tag to patch to
-# MODULE: CVS module name to use
-# SPEC: RPM spec file template
-# RPMFLAGS: Miscellaneous RPM flags
-# CVS_RSH: If not ssh
-# ALL: default targets
-#
-# If INITIAL is different than TAG, PatchSets will be generated
-# automatically with cvsps(1) to bring Source0 up to TAG. If TAG is
-# HEAD, a %{date} variable will be defined in the generated spec
-# file. If a Patch: tag in the spec file matches a generated PatchSet
-# number, the name of the patch will be as specified. Otherwise, the
-# name of the patch will be the PatchSet number. %patch tags in the
-# spec file are generated automatically.
-#
-
-#
-# kernel
-#
-
-kernel-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-kernel-INITIAL := linux-2_4_22
-kernel-TAG := HEAD
-kernel-MODULE := linux-2.4
-kernel-SPEC := linux-2.4/scripts/kernel-planetlab.spec
-ALL += kernel
-
-#
-# plkmod
-#
-
-plkmod-CVSROOT := pup-silk@cvs.planet-lab.org:/cvs
-plkmod-INITIAL := HEAD
-plkmod-TAG := HEAD
-plkmod-MODULE := sys-v3
-plkmod-SPEC := sys-v3/rpm/plkmod.spec
-plkmod-RPMFLAGS = --define "kernelver $(shell rpmquery --queryformat '%{VERSION}-%{RELEASE}\n' --specfile SPECS/$(notdir $(kernel-SPEC)) | head -1)"
-ALL += plkmod
-
-# Build kernel first so we can bootstrap off of its build
-plkmod: kernel
-
-#
-# vdk
-#
-
-vdk-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vdk-INITIAL := vdk_918
-vdk-TAG := HEAD
-vdk-MODULE := vdk
-vdk-SPEC := vdk/vtune_driver.spec
-vdk-RPMFLAGS = --define "kernelver $(shell rpmquery --queryformat '%{VERSION}-%{RELEASE}\n' --specfile SPECS/$(notdir $(kernel-SPEC)) | head -1)"
-ALL += vdk
-
-# Build kernel first so we can bootstrap off of its build
-vdk: kernel
-
-#
-# ltt
-#
-
-ltt-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-ltt-INITIAL := HEAD
-ltt-TAG := HEAD
-ltt-MODULE := ltt
-ltt-SPEC := ltt/ltt.spec
-ALL += ltt
-
-#
-# lkcdutils
-#
-
-lkcdutils-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-lkcdutils-INITIAL := lkcdutils-4_1
-lkcdutils-TAG := HEAD
-lkcdutils-MODULE := lkcdutils
-lkcdutils-SPEC := lkcdutils/spec/lkcdutils.spec
-ALL += lkcdutils
-
-# Build kernel first so we can bootstrap off of its build
-lkcdutils: kernel
-
-#
-# vserver
-#
-
-vserver-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vserver-INITIAL := vserver-0_29
-vserver-TAG := HEAD
-vserver-MODULE := vserver
-vserver-SPEC := vserver/vserver.spec
-ALL += vserver
-
-#
-# vserver-init
-#
-
-vserver-init-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vserver-init-INITIAL := HEAD
-vserver-init-TAG := HEAD
-vserver-init-MODULE := vserver-init
-vserver-init-SPEC := vserver-init/vserver-init.spec
-ALL += vserver-init
-
-#
-# vserver-cache
-#
-
-vserver-cache-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vserver-cache-INITIAL := HEAD
-vserver-cache-TAG := HEAD
-vserver-cache-MODULE := vserver-cache
-vserver-cache-SPEC := vserver-cache/vserver-cache.spec
-ALL += vserver-cache
-
-#
-# vserver-quota
-#
-
-vserver-quota-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vserver-quota-INITIAL := HEAD
-vserver-quota-TAG := HEAD
-vserver-quota-MODULE := vserver-quota
-vserver-quota-SPEC := vserver-quota/vserver-quota.spec
-ALL += vserver-quota
-
-#
-# vserver-util
-#
-
-vserver-util-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vserver-util-INITIAL := HEAD
-vserver-util-TAG := HEAD
-vserver-util-MODULE := vserver-util
-vserver-util-SPEC := vserver-util/vserver-util-planetlab.spec
-ALL += vserver-util
-
-#
-# vr-tools
-#
-
-vr-tools-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vr-tools-INITIAL := HEAD
-vr-tools-TAG := HEAD
-vr-tools-MODULE := vr-tools
-vr-tools-SPEC := vr-tools/vr-tools.spec
-ALL += vr-tools
-
-#
-# vsh
-#
-
-vsh-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-vsh-INITIAL := bash-2_05
-vsh-TAG := HEAD
-vsh-MODULE := vsh
-vsh-SPEC := vsh/vsh-planetlab.spec
-ALL += vsh
-
-# Build kernel first so we can bootstrap off of its build
-vsh: kernel
-
-#
-# e2fsprogs
-#
-
-e2fsprogs-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-e2fsprogs-INITIAL := e2fsprogs-1_33
-e2fsprogs-TAG := HEAD
-e2fsprogs-MODULE := e2fsprogs
-e2fsprogs-SPEC := e2fsprogs/e2fsprogs.spec
-ALL += e2fsprogs
-
-#
-# initscripts
-#
-
-initscripts-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-initscripts-INITIAL := initscripts-7_14
-initscripts-TAG := HEAD
-initscripts-MODULE := initscripts
-initscripts-SPEC := initscripts/initscripts.spec
-ALL += initscripts
-
-#
-# cq-tools
-#
-
-cq-tools-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-cq-tools-INITIAL := HEAD
-cq-tools-TAG := HEAD
-cq-tools-MODULE := cq-tools
-cq-tools-SPEC := cq-tools/cq-tools.spec
-ALL += cq-tools
-
-#
-# yum
-#
-
-yum-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-yum-INITIAL := YUM_2_0_3
-yum-TAG := HEAD
-yum-MODULE := yum
-yum-SPEC := yum/yum.spec
-ALL += yum
-
-#
-# ksymoops
-#
+### default values
+PLDISTRO := onelab
+RPMBUILD := rpmbuild
+export CVS_RSH := ssh
 
-ksymoops-CVSROOT := pup-pl_kernel@cvs.planet-lab.org:/cvs
-ksymoops-INITIAL := ksymoops-2_4_9
-ksymoops-TAG := HEAD
-ksymoops-MODULE := ksymoops
-ksymoops-SPEC := ksymoops/ksymoops.spec
-ALL += ksymoops
-
-#
-# PlanetLabAccounts
-#
-
-PlanetLabAccounts-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-PlanetLabAccounts-INITIAL := HEAD
-PlanetLabAccounts-TAG := HEAD
-PlanetLabAccounts-MODULE := PlanetLabAccounts
-PlanetLabAccounts-SPEC := PlanetLabAccounts/PlanetLabAccounts.spec
-ALL += PlanetLabAccounts
-
-#
-# MAKEDEV
-#
-
-MAKEDEV-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-MAKEDEV-INITIAL := MAKEDEV_3_2_2
-MAKEDEV-TAG := HEAD
-MAKEDEV-MODULE := MAKEDEV
-MAKEDEV-SPEC := MAKEDEV/MAKEDEV.spec
-ALL += MAKEDEV
-
-#
-# NodeUpdate
-#
-
-NodeUpdate-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-NodeUpdate-INITIAL := HEAD
-NodeUpdate-TAG := HEAD
-NodeUpdate-MODULE := NodeUpdate
-NodeUpdate-SPEC := NodeUpdate/NodeUpdate.spec
-ALL += NodeUpdate
-
-#
-# PlanetLabConf
-#
-
-PlanetLabConf-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-PlanetLabConf-INITIAL := HEAD
-PlanetLabConf-TAG := HEAD
-PlanetLabConf-MODULE := PlanetLabConf
-PlanetLabConf-SPEC := PlanetLabConf/PlanetLabConf.spec
-ALL += PlanetLabConf
-
-#
-# PlanetLabKeys
-#
-
-PlanetLabKeys-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-PlanetLabKeys-INITIAL := HEAD
-PlanetLabKeys-TAG := HEAD
-PlanetLabKeys-MODULE := PlanetLabKeys
-PlanetLabKeys-SPEC := PlanetLabKeys/PlanetLabKeys.spec
-ALL += PlanetLabKeys
-
-#
-# BWLimit
-#
-
-BWLimit-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-BWLimit-INITIAL := HEAD
-BWLimit-TAG := HEAD
-BWLimit-MODULE := BWLimit
-BWLimit-SPEC := BWLimit/BWLimit.spec
-ALL += BWLimit
-
-#
-# perl-IO-Stty
-#
-
-perl-IO-Stty-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-perl-IO-Stty-INITIAL := PERL-IO-STTY_0_2
-perl-IO-Stty-TAG := HEAD
-perl-IO-Stty-MODULE := perl-IO-Stty
-perl-IO-Stty-SPEC := perl-IO-Stty/perl-IO-Stty.spec
-ALL += perl-IO-Stty
-
-#
-# ipod
-#
-
-ipod-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-ipod-INITIAL := HEAD
-ipod-TAG := HEAD
-ipod-MODULE := ipod
-ipod-SPEC := ipod/ipod.spec
-ALL += ipod
-
-#
-# sudo
-#
-
-sudo-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-sudo-INITIAL := HEAD
-sudo-TAG := HEAD
-sudo-MODULE := sudo
-sudo-SPEC := sudo/planetlab_sudo.spec
-ALL += sudo
-
-#
-# blacklist
-#
-
-blacklist-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-blacklist-INITIAL := HEAD
-blacklist-TAG := HEAD
-blacklist-MODULE := blacklist
-blacklist-SPEC := blacklist/PlanetLab-blacklist.spec
-ALL += blacklist
-
-#
-# httpd
-#
-
-httpd-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-httpd-INITIAL := HEAD
-httpd-TAG := HEAD
-httpd-MODULE := httpd
-httpd-SPEC := httpd/httpd.spec
-ALL += httpd
-
-#
-# BootServerRequest
-#
-
-BootServerRequest-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-BootServerRequest-INITIAL := HEAD
-BootServerRequest-TAG := HEAD
-BootServerRequest-MODULE := BootServerRequest
-BootServerRequest-SPEC := BootServerRequest/PLBootServerRequest.spec
-ALL += BootServerRequest
-
-#
-# PlanetLabID
-#
-
-PlanetLabID-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-PlanetLabID-INITIAL := HEAD
-PlanetLabID-TAG := HEAD
-PlanetLabID-MODULE := PlanetLabID
-PlanetLabID-SPEC := PlanetLabID/PlanetLabID.spec
-ALL += PlanetLabID
-
-#
-# iputils
-#
-
-iputils-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-iputils-INITIAL := HEAD
-iputils-TAG := HEAD
-iputils-MODULE := iputils
-iputils-SPEC := iputils/iputils.spec
-ALL += iputils
-
-#
-# traceroute
-#
-
-traceroute-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-traceroute-INITIAL := HEAD
-traceroute-TAG := HEAD
-traceroute-MODULE := traceroute
-traceroute-SPEC := traceroute/traceroute.spec
-ALL += traceroute
-
-#
-# net-tools
-#
-
-net-tools-CVSROOT := pup-node_pkgs@cvs.planet-lab.org:/cvs
-net-tools-INITIAL := net-tools-1_60
-net-tools-TAG := HEAD
-net-tools-MODULE := net-tools
-net-tools-SPEC := net-tools/RPM/net-tools.spec
-ALL += net-tools
-
-ifeq ($(findstring $(package),$(ALL)),)
+########## pldistro.mk holds PLDISTRO - it is generated at stage1 (see below)
+ifeq "$(stage1)" ""
+include pldistro.mk
+endif
 
-# Build all packages
+#################### include onelab.mk
+# describes the set of components
+PLDISTROCONTENTS := $(PLDISTRO).mk
+include $(PLDISTROCONTENTS)
+
+#################### include <pldistro>-tags.mk
+# describes where to fetch components, and the related tags if using cvs
+PLDISTROTAGS := $(PLDISTRO)-tags.mk
+include $(PLDISTROTAGS)
+
+########## stage1 and stage2
+# extract specs and compute .mk files by running 
+# make stage1=true
+# entering stage1, we compute all the spec files
+# then we use stage2 to compute the .mk iteratively, 
+# ensuring that the n-1 first makefiles are loaded when creating the n-th one
+# when stage2 is set, it is supposed to be an index (starting at 1) in $(ALL)
+
+ALLMKS := $(foreach package, $(ALL), MAKE/$(package).mk)
+
+### stage2 : need some arithmetic, see
+# http://www.cmcrossroads.com/articles/ask-mr.-make/learning-gnu-make-functions-with-arithmetic.html
+ifneq "$(stage2)" ""
+# the first n packages
+packages := $(wordlist 1,$(words $(stage2)),$(ALL))
+# the n-th package
+package := $(word $(words $(packages)),$(packages))
+# the n-1 first packages
+stage2_1 := $(wordlist 2,$(words $(stage2)),$(stage2))
+previous := $(wordlist 1,$(words $(stage2_1)),$(ALL))
+previousmks := $(foreach package,$(previous),MAKE/$(package).mk)
+include $(previousmks)
+all: verbose
+verbose:
+       @echo "========== stage2 : $(package)"
+       @echo "stage2 : included .mk files : $(previousmks)"
+all: $($(package)_specpath)
+all: MAKE/$(package).mk
+else
+### stage1
+ifneq "$(stage1)" ""
+all : verbose
+verbose :
+       @echo "========== stage1"
+all : spec2make
+all : .rpmmacros
+# specs and makes are done sequentially by stage2
+all : stage2
+stage2:
+       arg=""; for n in $(ALL) ; do arg="$$arg x"; $(MAKE) --no-print-directory stage2="$$arg"; done
+### regular make
+else
+### once .mks are OK, you can run make normally
+include $(ALLMKS)
+#all : tarballs
+#all : sources
+#all : codebases
+#all : rpms
+#all : srpms
+# mention $(ALL) here rather than rpms 
+# this is because the inter-package dependencies are expressed like
+# util-vserver: util-python
 all: $(ALL)
+all: srpms
+endif
+endif
 
-# Recurse
-$(ALL):
-       $(MAKE) package=$@
-
-# Remove files generated by this package
-$(foreach package,$(ALL),$(package)-clean): %-clean:
-       $(MAKE) package=$* clean
-
-# Remove all generated files
+####################
+# gather build information for the 'About' page
+SOURCES/myplc-release:
+       @echo 'Creating myplc-release'
+       mkdir -p SOURCES
+       rm -f $@
+       (echo -n 'Build bdate: ' ; date '+%Y.%m.%d') >> $@
+       (echo -n 'Build btime: ' ; date '+%H:%M') >> $@
+       (echo -n 'Build hostname: ' ; hostname) >> $@
+       (echo -n 'Build location: ' ; pwd) >> $@
+       (echo -n 'Build tags file: ' ; fgrep '$$''Id' $(PLDISTROTAGS)) >> $@
+       echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx modules versions info" >> $@
+       $(MAKE) --no-print-directory versions >> $@
+
+####################
+# notes: 
+# * to make configuration easier, we always use the first module's
+# definitions (CVSROOT,TAG, or SVNPATH) to extract the spec file
+# * for the same reason, in case cvs is used, the first module name is added to 
+# $(package)-SPEC - otherwise the cvs modules have to define spec as 
+# <module>/<module>.spec while svn modules just define it as <module>.spec
+#
+define stage1_variables
+$(1)_spec = $(notdir $($(1)-SPEC))
+$(1)_specpath = SPECS/$(notdir $($(1)-SPEC))
+$(1)_module = $(firstword $($(1)-MODULE))
+endef
+
+$(foreach package, $(ALL), $(eval $(call stage1_variables,$(package))))
+
+#
+# for each package, compute whether we need to set date (i.e. whether we use the trunk)
+# the myplc package is forced to have a date, because it is more convenient
+# (we cannot bump its number everytime something changes in the system)
+# 
+define package_hasdate
+$(1)_hasdate = $(if $(subst myplc,,$(1)), \
+                 $(if $($(1)-SVNPATH),\
+                    $(if $(findstring /trunk,$($(1)-SVNPATH)),yes,),\
+                    $(if $(findstring HEAD,$($(1)-TAG)),yes,)), \
+               yes)
+endef
+
+$(foreach package, $(ALL), $(eval $(call package_hasdate,$(package))))
+
+### extract spec file from scm
+# usage: extract_spec_file package 
+# see early releases for comments on other possible implementations
+# cannot use variables in such rules, we need to inline everything, sigh
+define target_spec
+$($(1)_specpath):
+       mkdir -p SPECS
+       echo "%define pldistro $(PLDISTRO)" > $($(1)_specpath)
+       $(if $($(1)_hasdate),echo "%define date $(shell date +%Y.%m.%d)" >> $($(1)_specpath),)
+       $(if $($(1)-SPECVARS), \
+         $(foreach line,$($(1)-SPECVARS), \
+           echo "%define" $(word 1,$(subst =, ,$(line))) "$(word 2,$(subst =, ,$(line)))" >> $($(1)_specpath) ;))
+       $(if $($($(1)_module)-SVNPATH),\
+          svn cat $($($(1)_module)-SVNPATH)/$($(1)-SPEC) >> $($(1)_specpath),\
+          cvs -d $($($(1)_module)-CVSROOT) checkout \
+             -r $($($(1)_module)-TAG) \
+             -p $($(1)_module)/$($(1)-SPEC) >> $($(1)_specpath))
+       @if [ -z $($(1)_specpath) ] ; then rm $($(1)_specpath) ; exit 1 ; fi
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_spec,$(package))))
+
+### this utility allows to extract various info from a spec file
+### and to define them in makefiles
+spec2make: spec2make.c
+       $(CC) -g -Wall $< -o $@ -lrpm -lrpmbuild
+
+# Base rpmbuild in the current directory
+export HOME := $(shell pwd)
+.rpmmacros:
+       echo "%_topdir $(HOME)" > $@
+       echo "%_tmppath $(HOME)/tmp" >> $@
+
+### run spec2make on the spec file and include the result
+# usage: spec2make package
+define target_mk
+MAKE/$(1).mk: $($(1)_specpath) spec2make .rpmmacros
+       mkdir -p MAKE
+       ./spec2make $($(1)-RPMFLAGS) $($(1)_specpath) $(1) > MAKE/$(1).mk
+       @if [ -z MAKE/$(1).mk ] ; then rm MAKE/$(1).mk ; exit 1 ; fi
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_mk,$(package))))
+
+# stores PLDISTRO in a file
+# this is done at stage1. later run wont get confused
+pldistro.mk:
+       echo "PLDISTRO:=$(PLDISTRO)" > $@
+       echo "PLDISTROTAGS:=$(PLDISTROTAGS)" >> $@
+
+savepldistro: pldistro.mk
+.PHONY: savepldistro
+
+# always refresh this
+all: savepldistro
+
+####################
+### pack sources into tarballs
+ALLTARBALLS:= $(foreach package, $(ALL), $($(package)-TARBALL))
+tarballs: $(ALLTARBALLS)
+       @echo $(words $(ALLTARBALLS)) source tarballs OK
+.PHONY: tarballs
+
+SOURCES/%.tar.bz2: SOURCES/%
+       tar chpjf $@ -C SOURCES $*
+
+SOURCES/%.tar.gz: SOURCES/%
+       tar chpzf $@ -C SOURCES $*
+
+SOURCES/%.tgz: SOURCES/%
+       tar chpzf $@ -C SOURCES $*
+
+### the directory SOURCES/<package>-<version> is made 
+# with a copy -rl from CODEBASES/<package>
+# the former is $(package-SOURCE) and the latter is $(package-CODEBASE)
+ALLSOURCES:=$(foreach package, $(ALL), $($(package)-SOURCE))
+# so that make does not use the rule below directly for creating the tarball files
+.SECONDARY: $(ALLSOURCES)
+
+sources: $(ALLSOURCES)
+       @echo $(words $(ALLSOURCES)) versioned source trees OK
+.PHONY: sources
+
+define target_link_codebase_sources
+$($(1)-SOURCE): $($(1)-CODEBASE) ; mkdir -p SOURCES ; cp -rl $($(1)-CODEBASE) $($(1)-SOURCE)
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_link_codebase_sources,$(package))))
+
+### codebase extraction
+ALLCODEBASES:=$(foreach package, $(ALL), $($(package)-CODEBASE))
+# so that make does not use the rule below directly for creating the tarball files
+.SECONDARY: $(ALLCODEBASES)
+
+codebases : $(ALLCODEBASES)
+       @echo $(words $(ALLCODEBASES)) codebase OK
+.PHONY: codebases
+
+### extract codebase 
+# usage: extract_single_module package 
+define extract_single_module
+       mkdir -p CODEBASES
+       $(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))
+endef
+
+# usage: extract_multi_module package 
+define extract_multi_module
+       mkdir -p CODEBASES/$(1) && cd CODEBASES/$(1) && (\
+       $(foreach m,$($(1)-MODULE), $(if $($(m)-SVNPATH), svn export $($(m)-SVNPATH) $(m);, cvs -d $($(m)-CVSROOT) export -r $($(m)-TAG) $(m);)))
+endef
+
+CODEBASES/%: package=$(notdir $@)
+CODEBASES/%: module=$($(package)-MODULE)
+CODEBASES/%: multi_module=$(word 2,$(module))
+CODEBASES/%: 
+       @(echo -n "XXXXXXXXXXXXXXX -- BEG CODEBASE $(package) : $@ " ; date)
+       $(if $(multi_module),\
+         $(call extract_multi_module,$(package)),\
+         $(call extract_single_module,$(package)))
+       @(echo -n "XXXXXXXXXXXXXXX -- END CODEBASE $(package) : $@ " ; date)
+
+### rpmbuild invokation
+ALLRPMS:=$(foreach package,$(ALL),$($(package)-RPM))
+# same as above, mention $(ALL) and not $(ALLRPMS)
+rpms: $(ALL)
+       @echo $(words $(ALLRPMS)) binary rpms OK
+.PHONY: rpms
+
+# usage: build_binary_rpm package
+# xxx hacky - invoke createrepo if DEPENDFILES mentions RPMS/yumgroups.xml
+define target_binary_rpm 
+$($(1)-RPM): $($(1)_specpath) $($(1)-TARBALL) .rpmmacros
+       mkdir -p BUILD RPMS tmp
+       @(echo -n "XXXXXXXXXXXXXXX -- BEG RPM $(1) " ; date)
+       $(if $(findstring RPMS/yumgroups.xml,$($(1)-DEPENDFILES)), createrepo --quiet -g yumgroups.xml RPMS/ , )
+       $(if $($(1)-RPMBUILD),\
+         $($(1)-RPMBUILD) $($(1)-RPMFLAGS) -bb $($(1)_specpath), \
+         $(RPMBUILD)  $($(1)-RPMFLAGS) -bb $($(1)_specpath))
+       @(echo -n "XXXXXXXXXXXXXXX -- END RPM $(1) " ; date)
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_binary_rpm,$(package))))
+
+### source rpms
+ALLSRPMS:=$(foreach package,$(ALL),$($(package)-SRPM))
+srpms: $(ALLSRPMS)
+       @echo $(words $(ALLSRPMS)) source rpms OK
+.PHONY: srpms
+
+# usage: build_source_rpm package
+define target_source_rpm 
+$($(1)-SRPM): $($(1)_specpath) $($(1)-TARBALL) .rpmmacros
+       mkdir -p BUILD SRPMS tmp
+       @(echo -n "XXXXXXXXXXXXXXX -- BEG SRPM $(1) " ; date)
+       $(if $($(1)-RPMBUILD),\
+         $($(1)-RPMBUILD) $($(1)-RPMFLAGS) -bs $($(1)_specpath),
+         $(RPMBUILD) $($(1)-RPMFLAGS) -bs $($(1)_specpath))    
+       @(echo -n "XXXXXXXXXXXXXXX -- END SRPM $(1) " ; date)
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_source_rpm,$(package))))
+
+### RPMS/yumgroups.xml
+ifndef YUMGROUPS
+YUMGROUPS := groups/$(PLDISTRO).xml
+endif
+RPMS/yumgroups.xml: $(YUMGROUPS)
+       install -D -m 644 $(YUMGROUPS) $@
+
+### shorthand target
+# e.g. make proper -> does propers rpms
+# usage shorthand_target package
+define target_shorthand 
+$(1): $($(package)-RPM)
+.PHONY: $(1)
+$(1)-spec: $($(package)-SPEC)
+.PHONY: $(1)-spec
+$(1)-mk: $($(package)-MK)
+.PHONY: $(1)-mk
+$(1)-tarball: $($(package)-TARBALL)
+.PHONY: $(1)-tarball
+$(1)-codebase: $($(package)-CODEBASE)
+.PHONY: $(1)-source
+$(1)-source: $($(package)-SOURCE)
+.PHONY: $(1)-codebase
+$(1)-rpm: $($(package)-RPM)
+.PHONY: $(1)-rpm
+$(1)-srpm: $($(package)-SRPM)
+.PHONY: $(1)-srpm
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_shorthand,$(package))))
+
+### dependencies
+define package_depends_on_file
+$(1):$(2)
+$($(1)-RPM):$(2)
+endef
+
+define target_dependfiles
+$(foreach file,$($(1)-DEPENDFILES),$(eval $(call package_depends_on_file,$(1),$(file))))
+endef
+
+define package_depends_on_package
+$(1):$(2)
+$(1):$($(2)-RPM)
+$($(1)-RPM):$($(2)-RPM)
+endef
+
+define target_depends
+$(foreach package,$($(1)-DEPENDS),$(eval $(call package_depends_on_package,$(1),$(package))))
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_depends,$(package))))
+$(foreach package,$(ALL),$(eval $(call target_dependfiles,$(package))))
+
+
+### clean target
+# usage: target_clean package
+define target_clean
+$(1)-clean-codebase:
+       rm -rf $($(1)-CODEBASE)
+.PHONY: $(1)-clean-codebase
+CLEANS += $(1)-clean-codebase
+$(1)-clean-source:
+       rm -rf $($(1)-SOURCE)
+.PHONY: $(1)-clean-source
+CLEANS += $(1)-clean-source
+$(1)-clean-tarball:
+       rm -rf $($(1)-TARBALL)
+.PHONY: $(1)-clean-tarball
+CLEANS += $(1)-clean-tarball
+$(1)-clean-rpm:
+       rm -rf $($(1)-RPM)
+.PHONY: $(1)-clean-rpm
+CLEANS += $(1)-clean-rpm
+$(1)-clean-srpm:
+       rm -rf $($(1)-SRPM)
+.PHONY: $(1)-clean-srpm
+CLEANS += $(1)-clean-srpm
+$(1)-clean: $(1)-clean-codebase $(1)-clean-source $(1)-clean-tarball $(1)-clean-rpm $(1)-clean-srpm
+.PHONY: $(1)-clean
+endef
+
+$(foreach package,$(ALL),$(eval $(call target_clean,$(package))))
+
+### clean precisely
 clean:
-       rm -rf BUILD RPMS SOURCES SPECS SRPMS .rpmmacros .cvsps
-
-.PHONY: all $(ALL) $(foreach package,$(ALL),$(package)-clean) clean
-
+       $(MAKE) $(CLEANS)
+.PHONY: clean
+
+clean-help:
+       @echo Available clean targets
+       @echo $(CLEANS)
+
+### brute force clean
+distclean1:
+       rm -rf pldistro.mk .rpmmacros spec2make SPECS MAKE 
+distclean2:
+       rm -rf CODEBASES SOURCES BUILD RPMS SRPMS tmp
+distclean: distclean1 distclean2
+.PHONY: distclean1 distclean2 distclean
+
+# xxx tmp - I cannot use this on my mac for local testing
+ISMACOS=$(findstring Darwin,$(shell uname))
+ifneq "$(ISMACOS)" ""
+#################### produce reliable version information
+# for a given module
+VFORMAT="%30s := %s\n"
+define print_version
+$(1)-version:
+       @$(if $($(1)-SVNPATH),\
+          printf $(VFORMAT) $(1)-SVNPATH "$($(1)-SVNPATH)",\
+          printf $(VFORMAT) $(1)-CVSROOT "$($(1)-CVSROOT)" ; printf $(VFORMAT) $(1)-TAG "$($(1)-TAG)")
+endef
+
+# compute all modules
+ALL-MODULES :=
+$(foreach package,$(ALL), $(eval ALL-MODULES+=$($(package)-MODULE)))
+ALL-MODULES:=$(sort $(ALL-MODULES))
+
+$(foreach module,$(ALL-MODULES), $(eval $(call print_version,$(module))))
+
+versions: $(foreach module, $(ALL-MODULES), $(module)-version)
 else
+versions:
+       @echo "warning : the 'versions' target is not supported on macos"
+endif
 
-# Define variables for Makerules
-CVSROOT := $($(package)-CVSROOT)
-INITIAL := $($(package)-INITIAL)
-TAG := $($(package)-TAG)
-MODULE := $($(package)-MODULE)
-SPEC := $($(package)-SPEC)
-RPMFLAGS := $($(package)-RPMFLAGS)
-CVS_RSH := $(if $($(package)-CVS_RSH),$($(package)-CVS_RSH),ssh)
-
-include Makerules
-
+#################### include install Makefile
+# the default is to use the distro-dependent install file
+# however the main distro file can redefine PLDISTROINSTALL
+ifndef PLDISTROINSTALL
+PLDISTROINSTALL := $(PLDISTRO)-install.mk
 endif
+# only if present
+-include $(PLDISTROINSTALL)
+
+####################
+help:
+       @echo "Known pakages are"
+       @echo "  $(ALL)"
+       @echo "Run make in two stages:"
+       @echo ""
+       @echo "make stage1=true PLDISTRO=onelab"
+       @echo " -> extracts all spec files in SPECS/ and mk files in MAKE/"
+       @echo "    as well as save PLDISTRO for subsequent runs"
+       @echo ""
+       @echo "Then you can use the following targets"
+       @echo '$ make'
+       @echo "  rebuilds everything"
+       @echo '$ make util-vserver'
+       @echo "  makes the RPMS related to util-vserver"
+       @echo "  equivalent to 'make util-vserver-rpm'"
+       @echo ""
+       @echo "Or, vertically - step-by-step for a given package"
+       @echo '$ make util-vserver-codebase'
+       @echo "  performs codebase extraction in CODEBASES/util-vserver"
+       @echo '$ make util-vserver-source'
+       @echo "  creates source link in SOURCES/util-vserver-<version>"
+       @echo '$ make util-vserver-tarball'
+       @echo "  creates source tarball in SOURCES/util-vserver-<version>.<tarextension>"
+       @echo '$ make util-vserver-rpm'
+       @echo "  build rpm(s) in RPMS/"
+       @echo '$ make util-vserver-srpm'
+       @echo "  build source rpm in SRPMS/"
+       @echo ""
+       @echo "Or, horizontally, reach a step for all known packages"
+       @echo '$ make codebases'
+       @echo '$ make sources'
+       @echo '$ make tarballs'
+       @echo '$ make rpms'
+       @echo '$ make srpms'
+       @echo ""
+       @echo "Cleaning examples"
+       @echo "$ make clean"
+       @echo "  removes the files made by make"
+       @echo "$ make distclean"
+       @echo "  brute-force cleaning, removes entire directories - requires a new stage1"
+       @echo "$ make util-vserver-clean"
+       @echo "  removes codebase, source, tarball, rpm and srpm for util-vserver"
+       @echo "$ make util-vserver-clean-codebase"
+       @echo "  and so on"
+
+
+#################### convenience, for debugging only
+# make +foo : prints the value of $(foo)
+# make ++foo : idem but verbose, i.e. foo=$(foo)
+++%: varname=$(subst +,,$@)
+++%:
+       @echo "$(varname)=$($(varname))"
++%: varname=$(subst +,,$@)
++%:
+       @echo "$($(varname))"