Hello,
I have written a Makefile for convenient handling of a set of patches to
a piece of sourcecode. I have tried to write it in a way that it can
easily be reused, and therefore most targets are automatically
"generated" either by variable operations or by static pattern rules or
implicit rules. However, I have a problem in creating the
interdependencies between different patches.
This is how it works currently: For every patch in $(patchdir), I also
have a file that lists all files changed by the patch:
ls patchdir/
patch-doc patch-doc.files patch-src patch-src.files patch-tmp patch-tmp.files
What I want to do in the Makefile is to only give it a list of patches
(in the above example
patchnames = patch-deb patch-src patch-texdoc patch-texdoctk patch-tmp
) and let the Makefile generate all the necessary targets. The targets I
want are, with the example of patch-src
apply-patch-src
unapply-patch-src
(with their obvious meanings)
and
edit-patch-src
create-patch-src
The edit target creates a copy for every file in patch-src.files, then
applies the patch, and I can edit the files. After that, I do
create-patch-src, and it diffs all files in patch-src.files and cats the
diffs into the new patch-src file.
This structure already works, I attach the files below. However, what I
would like is to be able to say, e.g., "before applying patch-tmp,
patch-src must be applied" (because they have some files in common). And
with this dependency, it is clear that edit-patch-src is a prerequisite
to edit-patch-tmp (the latter taking proper care to move
edit-patch-src's copies out of the way), and that create-patch-tmp must
restore the moved-away copies of edit-patch-src and subsequently
recreate patch-src (which should not be modified, but this is needed to
get back to a consistent state).
Currently I do the following, "manually":
# define dependencies between patches
# (needed if some patches act on the same file)
PATCH_TMP_PREREQUISITES = patch-deb patch-src patch-texdoc patch-texdoctk
edit-patch-tmp-prereq = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/edit-$(prereq)-stamp)
apply-patch-tmp-prereq = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/apply-$(prereq)-stamp)
create-patch-tmp-targets = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/create-$(prereq))
unapply-patch-tmp-targets = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/unapply-$(prereq))
edit-patch-tmp: $(edit-patch-tmp-prereq)
apply-patch-tmp: $(apply-patch-tmp-prereq)
create-patch-tmp: after-create-targets += $(create-patch-tmp-targets)
unapply-patch-tmp: after-unapply-targets += $(unapply-patch-tmp-targets)
(the after-*-targets variables are previously initialised to "nothing",
there's a nothing target that does, well, nothing, and the unapply rule
calls
$(MAKE) -f thismakefile $(after-create-targets)
However, I would like it simpler. From a logical point of view, the
first line above,
PATCH_TMP_PREREQUISITES = patch-deb patch-src patch-texdoc patch-texdoctk
should be sufficient to determine all the necessary coherencies and
"write" the following bunch of lines. Furthermore, this is always the
same for all targets (except that mostly the lists will be just empty,
because the patches act on different files).
Is there a way to automatically create these prerequisites and command
variables, similar to the way I create the targets with pattern rules?
I'd appreciate any comments, thank you in advance,
Frank
And here come the files. They are meant to be included in a makefile
that compiles (or whatever) the patched sources, and the variable
DSF-PATCHLIST must be exported in this top Makefile and point to the
filename of the second file, which is meant for user configuration
# file dsf-patch.mk - keeping patches against single files
# $Id$
#
# dsf-patch stands for "Debian single file patch system"
#
# this file is meant to be included from debian/rules,
# and will itself include the file specified in $(DSF-PATCHLIST)
#
# Copyright (C) 2005 by Frank K�ster <[EMAIL PROTECTED]>.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to: The Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#
# On Debian GNU/Linux System you can find a copy of the GNU General Public
# License in "/usr/share/common-licenses/GPL".
# the following can be used to recreate or update the patches.
#
# First the patches should be applied by running debian/rules edit-*
# or edit-patches. Then do the edits, then call debian/rules patches
# or patch-*. Afterwards, clean is a good idea before committing
# define variables, may be overridden in $(DSF-PATCHLIST)
patchdir = debian/patches
patchopts = -p0 -g0 -N
SHELL = /bin/bash
# include the local patch specification
include $(DSF-PATCHLIST)
# compute names for auxiliary targets
apply-patchnames = $(foreach patchname,$(patchnames), apply-$(patchname))
unapply-patchnames = $(foreach patchname,$(patchnames), unapply-$(patchname))
edit-patchnames = $(foreach patchname,$(patchnames), edit-$(patchname))
create-patchnames = $(foreach patchname,$(patchnames), create-$(patchname))
apply-stamps = $(foreach
patchname,$(patchnames),$(patchdir)/apply-$(patchname)-stamp)
unapply-nostamps = $(foreach
patchname,$(patchnames),$(patchdir)/unapply-$(patchname))
edit-stamps = $(foreach
patchname,$(patchnames),$(patchdir)/edit-$(patchname)-stamp)
after-create-targets = nothing
after-unapply-targets = nothing
THISMAKE = $(MAKE) -f debian/rules.d/dsf-patch.mk
# compute dependency prerequesites
## main targets:
# applying a patch
$(apply-patchnames): %: $(patchdir)/%-stamp
# unapplying a patch
$(unapply-patchnames): %: $(patchdir)/%
# for editing patches
$(edit-patchnames): %: $(patchdir)/%-stamp
# for recreating a patch after editing
$(create-patchnames): %: $(patchdir)/%
## auxiliary targets:
# needed for calls of $(THISMAKE) $(somevariable), where somevariable may be
empty
nothing:
true
# applying a patch
$(apply-stamps): $(patchdir)/apply-%-stamp: $(patchdir)/%
patch $(patchopts) -i $<
touch $@
# unapplying a patch
$(unapply-nostamps): $(patchdir)/unapply-%: $(patchdir)/%
$(patchdir)/apply-%-stamp
patch $(patchopts) -R -i $<
rm $(patchdir)/apply-$*-stamp
$(THISMAKE) $(after-unapply-targets)
# edit a patch
$(patchdir)/setup-edit-patches-stamp:
$(THISMAKE) clean
touch $@
$(edit-stamps): $(patchdir)/edit-%-stamp: $(patchdir)/%.files
$(patchdir)/setup-edit-patches-stamp
for file in `cat $<`; do cp $$file{,.orig}; done
$(THISMAKE) apply-$*
touch $@
# recreate a patch
$(patchdir)/create-%: $(patchdir)/%.files $(patchdir)/edit-%-stamp
-mv $(patchdir)/$* $(patchdir)/$*.old
for file in `cat $<`; do echo "comparing $$file"; diff -u
$$file{.orig,} >> $(patchdir)/$*; done || true
patch $(patchopts) -Ri $(patchdir)/$*
rm $(patchdir)/edit-$*-stamp $(patchdir)/apply-$*-stamp
$(THISMAKE) $(after-create-targets)
# for the general clean target
clean-patches:
test ! -f $(patchdir)/edit-*-stamp || $(patchclean-error)
-rm $(patchdir)/setup-edit-patches-stamp
for patch in $(patchnames); do \
patch $(patchopts) -Ri $(patchdir)/$$patch || true; \
rm -f $(patchdir)/apply-$$patch-stamp; \
done
# patch -p0 -NRi debian/patches/patch-tmp || true
# patch -g0 -p0 -NRi debian/patches/patch-deb || true
# patch -p0 -NRi debian/patches/patch-src || true
# patch -p0 -NRi debian/patches/patch-texdoctk || true
# patch -p0 -NRi debian/patches/patch-texdoc || true
# -rm $(apply-stamps)
define patchclean-error
(echo;\
echo 'Found edit-*-stamp file in $(patchdir)'; \
echo 'Please recreate patches before cleaning the source tree!'; \
echo; \
exit 1)
endef
# to be included from dsf-patch
# define variables
# e.g.
# patchdir = debian/patches
# patchopts = -p0 -N
patchopts += -g0
# define patches
patchnames = patch-deb patch-src patch-texdoc patch-texdoctk patch-tmp
# define dependencies between patches
# (needed if some patches act on the same file)
PATCH_TMP_PREREQUISITES = patch-deb patch-src patch-texdoc patch-texdoctk
edit-patch-tmp-prereq = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/edit-$(prereq)-stamp)
apply-patch-tmp-prereq = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/apply-$(prereq)-stamp)
create-patch-tmp-targets = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/create-$(prereq))
unapply-patch-tmp-targets = $(foreach prereq,$(PATCH_TMP_PREREQUISITES),
$(patchdir)/unapply-$(prereq))
edit-patch-tmp: $(edit-patch-tmp-prereq)
apply-patch-tmp: $(apply-patch-tmp-prereq)
echo $(apply-patch-tmp-prereq)
create-patch-tmp: after-create-targets += $(create-patch-tmp-targets)
unapply-patch-tmp: after-unapply-targets += $(unapply-patch-tmp-targets)
--
Frank K�ster
Inst. f. Biochemie der Univ. Z�rich
Debian Developer
_______________________________________________
Help-make mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-make