Makefile: Don't insist on `/usr/lib/.../coreutils/'.
[distorted-chroot] / Makefile
index a3ff7b6..fb888c0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -38,13 +38,9 @@ CONFIG_VARS           =
 ## Level of pickiness to aspire to.
 NOTIFY_FATAL            = 1
 
-## Path to this working tree.
-CONFIG_VARS            += HERE
-HERE                    = $(abspath .)
-
 ## Volume group from which to allocate chroot volumes and snapshots.
 CONFIG_VARS            += VG LVPREFIX
-VG                      = vg-$(shell hostname)
+VG                     := vg-$(shell hostname)
 LVPREFIX                =
 
 ## Logical volume size, as an LVM option.
@@ -62,15 +58,14 @@ APTSRC                       = etc/aptsrc.conf $(wildcard etc/aptsrc.local.conf)
 
 ## APT configuration fragment names.  These will be linked into
 ## `/etc/apt/apt.conf.d' in each chroot.  To put a fragment f in a surprising
-## place, set $($f_APTCONFSRC).
-CONFIG_VARS            += APTCONF
-APTCONF_DIR             = etc/apt-conf.d
-APTCONF                         = $(notdir $(wildcard $(APTCONF_DIR)/[0-9]*[!~]))
+## place, set $(_$f_APTCONFSRC).
+CONFIG_VARS            += APTCONF $(foreach f,$(APTCONF),_$f_APTCONFSRC)
+APTCONF                         = $(notdir $(wildcard etc/apt-conf.d/[0-9]*[!~]))
 
 ## Proxy setting.
 CONFIG_VARS            += PROXY
-PROXY                  := $(shell \
-       eval $$(apt-config $(foreach a,$(APTCONF), -c$(APTCONF_DIR)/$a) \
+PROXY                   = $(shell \
+       eval $$(apt-config $(foreach a,$(APTCONF),-cetc/apt-conf.d/$a) \
                shell proxy Acquire::http::proxy); \
        case $${proxy+t} in (t) echo "$$proxy" ;; (*) echo nil ;; esac)
 
@@ -81,8 +76,8 @@ DISTS                  = $(PRIMARY_DIST) buster bullseye sid
 
 ## Host's native architecture(s).
 CONFIG_VARS            += MYARCH NATIVE_ARCHS
-MYARCH                  = $(shell dpkg --print-architecture)
-OTHERARCHS              = $(shell dpkg --print-foreign-architectures)
+MYARCH                 := $(shell dpkg --print-architecture)
+OTHERARCHS             := $(shell dpkg --print-foreign-architectures)
 NATIVE_ARCHS            = $(MYARCH) $(OTHERARCHS)
 
 ## Foreign (emulated) architectures to support.
@@ -90,6 +85,7 @@ CONFIG_VARS           += FOREIGN_ARCHS
 FOREIGN_ARCHS           =
 
 ## Master lists of chroots to build and maintain.
+CONFIG_VARS            += NATIVE_CHROOTS FOREIGN_CHROOTS
 NATIVE_CHROOTS          = $(foreach a,$(NATIVE_ARCHS), \
                                $(foreach d,$(or $($a_DISTS) $(DISTS)), \
                                        $d-$a))
@@ -97,18 +93,77 @@ FOREIGN_CHROOTS              = $(foreach a,$(FOREIGN_ARCHS), \
                                $(foreach d,$(or $($a_DISTS) $(DISTS)), \
                                        $d-$a))
 
-## Extra packages to be installed in chroots.
-CONFIG_VARS            += BASE_PACKAGES NATIVE_BASE_PACKAGES FOREIGN_BASE_PACKAGES
-BASE_PACKAGES           = ccache
-BASE_PACKAGES          += eatmydata fakeroot
-BASE_PACKAGES          += locales tzdata
-BASE_PACKAGES          += libfile-fcntllock-perl
-NATIVE_BASE_PACKAGES    = build-essential
-FOREIGN_BASE_PACKAGES   =
+## Extra packages to be installed in chroots.  `BASE_PACKAGES' are installed
+## through `debootstrap'; `EXTRA_PACKAGES' are installed later, using Apt,
+## which is faster in foreign chroots.
+CONFIG_VARS            += BASE_PACKAGES EXTRA_PACKAGES
+BASE_PACKAGES           = eatmydata
+EXTRA_PACKAGES          = build-essential
+EXTRA_PACKAGES         += ccache
+EXTRA_PACKAGES         += fakeroot
+EXTRA_PACKAGES         += libfile-fcntllock-perl
+EXTRA_PACKAGES         += locales
+
+## Extra packages from which to install the cross tools.
+CONFIG_VARS            += CROSS_PACKAGES
+CROSS_PACKAGES          = bash coreutils dash findutils
+CROSS_PACKAGES         += gzip m4 mawk sed tar xz-utils
+CROSS_PACKAGES         += apt ccache eatmydata fakeroot make
+CROSS_PACKAGES         += qemu-user-static
+CROSS_PACKAGES         += $(foreach a,$(FOREIGN_GNUARCHS),\
+                               gcc-$a g++-$a binutils-$a)
+
+## Native files to install in place of the foreign versions.  `MULTI' here
+## stands for the donor's GNU multiarch name.
+CONFIG_VARS            += CROSS_PATHS
+CROSS_PATHS            += \
+       $(addprefix /usr/bin/, \
+               apt apt-cache apt-config apt-get apt-key apt-mark) \
+       $(addprefix /usr/lib/apt/, \
+               methods/ solvers/) \
+       $(addprefix /bin/, \
+               cat chgrp chown cp date dd df dir echo false ln ls mkdir \
+               mknod mktemp mv pwd readlink rm rmdir sleep stty sync touch \
+               true uname vdir) \
+       $(addprefix /usr/bin/, \
+               [ arch b2sum base32 base64 basename chcon cksum comm \
+               csplit cut dircolors dirname du env expand expr factor fmt \
+               fold groups head hostid id install join link logname md5sum \
+               mkfifo nice nl nohup nproc numfmt od paste pathchk pinky pr \
+               printenv printf ptx realpath runcon seq sha1sum sha224sum \
+               sha256sum sha384sum sha512sum shred shuf sort split stat \
+               stdbuf sum tac tail tee test timeout tr truncate tsort tty \
+               unexpand uniq unlink users wc who whoami yes) \
+       ?/usr/lib/MULTI/coreutils/ \
+       $(addprefix /lib/MULTI/, \
+               libnsl.so.* libnss_*.so.*) \
+       /usr/bin/gpgv \
+       /usr/bin/qemu-*-static \
+       $(addprefix /bin/, \
+               bash dash gzip sed tar) \
+       $(addprefix /usr/bin/, \
+               ccache find m4 make mawk xargs xz) \
+       $(addprefix /usr/lib/MULTI/, \
+               libeatmydata.so* libfakeroot/) \
+       $(addprefix /etc/ld.so.conf.d/, \
+               MULTI.conf fakeroot*.conf) \
+       $(foreach a,$(FOREIGN_GNUARCHS), \
+               $(addprefix /usr/bin/$a-, \
+                       addr2line ar as c++filt dwp elfedit gprof ld ld.* \
+                       nm objcopy objdump ranlib readelf size strings \
+                       strip) \
+               $(addprefix /usr/bin/$a-, \
+                       cpp gcc g++ gcov gcov-dump gcov-tool gprof \
+                       gcc-ar gcc-nm gcc-ranlib) \
+               /usr/lib/gcc-cross/$a/ \
+               /usr/$a/include/c++)
 
 ## Local packages to be compiled and installed in chroots.  Archives can be
 ## found in `pkg/'.
+CONFIG_VARS            += LOCALPKGS $(foreach p,$(LOCALPKGS),$p_DEPS)
 LOCALPKGS               = mLib checkpath
+mLib_DEPS               =
+checkpath_DEPS          = mLib
 
 ## Which host architecture to use for foreign architectures.  It turns out
 ## that it's best to use a Qemu with the same host bitness as the target
@@ -117,16 +172,20 @@ LOCALPKGS          = mLib checkpath
 32BIT_QEMUHOST          = $(or $(filter i386,$(NATIVE_ARCHS)),$(TOOLSARCH))
 64BIT_QEMUHOST          = $(or $(filter amd64,$(NATIVE_ARCHS)),$(TOOLSARCH))
 
-CONFIG_VARS            += $(foreach a,$(FOREIGN_ARCHS), $a_QEMUHOST)
+CONFIG_VARS            += $(foreach a,$(FOREIGN_ARCHS),$a_QEMUHOST)
 armel_QEMUHOST          = $(32BIT_QEMUHOST)
 armhf_QEMUHOST          = $(32BIT_QEMUHOST)
 arm64_QEMUHOST          = $(64BIT_QEMUHOST)
 i386_QEMUHOST           = $(32BIT_QEMUHOST)
 amd64_QEMUHOST          = $(64BIT_QEMUHOST)
 
+## Which distribution of Qemu to use.
+CONFIG_VARS            += $(foreach d,$(DISTS),$d_QEMUDIST)
+stretch_QEMUDIST        = buster
+
 ## Qemu architecture names.  These tell us which Qemu binary to use for a
 ## particular Debian architecture.
-CONFIG_VARS            += $(foreach a,$(FOREIGN_ARCHS), $a_QEMUARCH)
+CONFIG_VARS            += $(foreach a,$(FOREIGN_ARCHS),$a_QEMUARCH)
 armel_QEMUARCH          = arm
 armhf_QEMUARCH          = arm
 arm64_QEMUARCH          = aarch64
@@ -134,10 +193,10 @@ i386_QEMUARCH              = i386
 amd64_QEMUARCH          = x86_64
 
 ## Alias mapping for chroots.
-CONFIG_VARS            += $(foreach d,$(DISTS), $d_ALIASES)
+CONFIG_VARS            += $(foreach d,$(DISTS),$d_ALIASES)
 stretch_ALIASES                 = oldstable
 buster_ALIASES          = stable
-bullseye_ALIASE                 = testing
+bullseye_ALIASES        = testing
 sid_ALIASES             = unstable
 
 ## Which host architecture to use for commonly used tools in foreign chroots.
@@ -150,10 +209,12 @@ STATE                      = state
 
 ## A directory which will be spliced into chroots as `/usr/local.schroot/'.
 ## This will be our primary point of contact with the chroot.
-CONFIG_VARS            += LOCAL
+CONFIG_VARS            += LOCAL ABSLOCAL
 LOCAL                   = local.schroot
+ABSLOCAL                = $(abspath $(LOCAL))
 
 ## How to run a command as a privileged user.
+CONFIG_VARS            += ROOTLY
 ROOTLY                  = sudo
 
 ## Files to be copied into a chroot from the host.
@@ -168,6 +229,12 @@ CONFIG_VARS                += ALL_ARCHS ALL_CHROOTS
 ALL_ARCHS               = $(NATIVE_ARCHS) $(FOREIGN_ARCHS)
 ALL_CHROOTS             = $(NATIVE_CHROOTS) $(FOREIGN_CHROOTS)
 
+## GNU names for foreign architectures.
+CONFIG_VARS            += FOREIGN_GNUARCHS
+FOREIGN_GNUARCHS       := $(foreach a,$(FOREIGN_ARCHS),\
+                               $(shell dpkg-architecture -A$a \
+                                       -qDEB_TARGET_GNU_TYPE))
+
 ###--------------------------------------------------------------------------
 ### Utilities.
 
@@ -198,6 +265,11 @@ CLEANFILES         += log/*.log
 SILENCE_LVM             = \
        LVM_SUPPRESS_FD_WARNINGS=1; export LVM_SUPPRESS_FD_WARNINGS
 
+##     $(call definedp,VAR)
+##
+## Expand non-empty if and only if VAR is defined (but possibly empty).
+definedp                = $(filter-out undefined,$(origin $1))
+
 ##     $(call catchrc,...$(call throwrc,CMD)...)
 ##
 ## Catch the exit status of some subpart of a complicated shell rune.
@@ -207,7 +279,8 @@ throwrc                      = { $1; echo $$? >&4; }
 ##     $(call squote,TXT)
 ##
 ## Single-quote TXT.
-squote                  = '$(subst ','\\'',$1)'
+squote                  = '$(subst ','\'',$1)'
+#'
 
 ##     $(call chroot-dist,D-A) -> D
 ##     $(call chroot-arch,D-A) -> A
@@ -351,9 +424,8 @@ $(PYMODULES): $(STATE)/lib/python/%.so: $$(call c-object,$$($$*_SOURCES))
 ###--------------------------------------------------------------------------
 ### Scripts.
 
-SCRIPTS                        += mkbuildchroot
+SCRIPTS                        += chroot-maint
 SCRIPTS                        += mkchrootconf
-SCRIPTS                        += install-cross-tools update-cross-tools
 
 SUBST_SCRIPTS           = $(addprefix $(STATE)/bin/,$(SCRIPTS))
 all:: $(SUBST_SCRIPTS)
@@ -397,7 +469,7 @@ CLEANFILES          += $(APT_SOURCES)
 APT_CONFIGS           = $(addprefix $(LOCAL)/etc/apt/apt.conf.d/,$(APTCONF))
 all:: $(APT_CONFIGS)
 $(APT_CONFIGS): $(LOCAL)/etc/apt/apt.conf.d/%: \
-               $$(or $$($$*_APTCONFSRC) $$(APTCONF_DIR)/$$*)
+               $$(or $$(_$$*_APTCONFSRC) etc/apt-conf.d/$$*)
        $(V_AT)mkdir -p $(dir $@)
        $(call v_tag,COPY)cp $< $@.new && mv $@.new $@
 clean::; rm -f $(APT_CONFIGS)
@@ -437,7 +509,8 @@ check::; $(call check-symlink,ERR,/schroot,/run/schroot/mount)
 
 %print-varlist          = { \
        echo "\#\#\# -*-sh-*- GENERATED by distorted-chroot: do not edit"; \
-       $(foreach v,$1, echo $v=\'$(call squote,$($v))\';) \
+       $(foreach v,$1,$(if $(call definedp,$v),\
+               echo $v=\'$(call squote,$($v))\';)) \
 }
 schroot-config_HASH    := \
        $(shell $(call %print-varlist,$(CONFIG_VARS)) | \
@@ -446,7 +519,7 @@ schroot-config_FILE  = $(STATE)/config.sh-$(schroot-config_HASH)
 $(schroot-config_FILE):
        $(V_AT)mkdir -p $(STATE)
        $(V_AT)rm -f $(STATE)/config.sh-*
-       $(call v_tag,STAMP)$(call %print-varlist,$(CONFIG_VARS)) \
+       $(call v_tag,GEN)$(call %print-varlist,$(CONFIG_VARS)) \
                >$@.new && mv $@.new $@
 
 schroot-config:: $(STATE)/config.sh
@@ -459,7 +532,7 @@ $(LOCAL)/etc/schroot/sbuild.schroot: $(STATE)/bin/mkchrootconf
        $(call v_tag,GEN)$(STATE)/bin/mkchrootconf >$@.new && \
                $(ROOTLY) chown root:root $@.new && mv $@.new $@
 CLEANFILES             += $(LOCAL)/etc/schroot/sbuild.schroot
-check::; $(call check-symlink,WARN,/etc/schroot/chroot.d/sbuild,$(HERE)/$(LOCAL)/etc/schroot/sbuild.schroot)
+check::; $(call check-symlink,WARN,/etc/schroot/chroot.d/sbuild,$(ABSLOCAL)/etc/schroot/sbuild.schroot)
 
 schroot-config:: $(LOCAL)/etc/schroot/sbuild.profile/copyfiles
 $(LOCAL)/etc/schroot/sbuild.profile/copyfiles: $(schroot-config_STAMP)
@@ -487,7 +560,7 @@ $(LOCAL)/etc/schroot/sbuild.profile/fstab: \
                <$< >$@.new && mv $@.new $@
 CLEANFILES             += $(LOCAL)/etc/schroot/sbuild.profile/fstab
 
-check::; $(call check-symlink,WARN,/etc/schroot/sbuild,$(HERE)/$(LOCAL)/etc/schroot/sbuild.profile)
+check::; $(call check-symlink,WARN,/etc/schroot/sbuild,$(ABSLOCAL)/etc/schroot/sbuild.profile)
 
 schroot-config:: $(LOCAL)/etc/sbuild.conf
 $(LOCAL)/etc/sbuild.conf: etc/sbuild.conf.in $(schroot-config_STAMP)
@@ -495,7 +568,7 @@ $(LOCAL)/etc/sbuild.conf: etc/sbuild.conf.in $(schroot-config_STAMP)
        $(call v_tag,SUBST)$(call subst-file,### -*-perl-*-) \
                <$< >$@.new && mv $@.new $@
 CLEANFILES             += $(LOCAL)/etc/sbuild.conf
-check::; $(call check-symlink,WARN,/etc/sbuild/sbuild.conf,$(HERE)/$(LOCAL)/etc/sbuild.conf)
+check::; $(call check-symlink,WARN,/etc/sbuild/sbuild.conf,$(ABSLOCAL)/etc/sbuild.conf)
 check::; $(call check-executable,WARN,/usr/local.schroot/hacks/apt-get)
 
 SCHROOT_SCRIPTS                += 11private
@@ -512,19 +585,32 @@ CLEANFILES                += $(COPY_SCHROOT_SCRIPTS)
 CHECK_SCHROOT_SCRIPTS   = $(addprefix check-script/,$(SCHROOT_SCRIPTS))
 check:: $(CHECK_SCHROOT_SCRIPTS)
 $(CHECK_SCHROOT_SCRIPTS): check-script/%:
-       $(call check-symlink,WARN,/etc/schroot/setup.d/$*,$(HERE)/$(LOCAL)/etc/schroot/setup.d/$*)
+       $(call check-symlink,WARN,/etc/schroot/setup.d/$*,$(ABSLOCAL)/etc/schroot/setup.d/$*)
 .PHONY: $(addprefix check-script/,$(SCHROOT_SCRIPTS))
 
 ###--------------------------------------------------------------------------
+### Ccache setup.
+
+CCACHE_CONFIGS          = $(foreach r,$(ALL_CHROOTS), \
+       /var/lib/sbuild/build/.ccache/$(LVPREFIX)$r/ccache.conf)
+all:: $(CCACHE_CONFIGS)
+$(CCACHE_CONFIGS): /var/lib/sbuild/build/.ccache/$(LVPREFIX)%/ccache.conf: \
+               etc/ccache.conf
+       $(V_AT)mkdir -p $(dir $@)
+       $(call v_tag,COPY)cp $< $@.new && mv $@.new $@
+
+###--------------------------------------------------------------------------
 ### `/usr/local/' structure.
 
 LOCAL_COMMON_DIRS       = share/ src/
-all:: $(foreach d,$(LOCAL_COMMON_DIRS),$(LOCAL)/$d)
-$(foreach d,$(LOCAL_COMMON_DIRS),$(LOCAL)/$d):
+LOCAL_EXTRA_DIRS        = share/man/
+all:: $(foreach d,$(LOCAL_COMMON_DIRS) $(LOCAL_EXTRA_DIRS),$(LOCAL)/$d)
+$(foreach d,$(LOCAL_COMMON_DIRS) $(LOCAL_EXTRA_DIRS),$(LOCAL)/$d):
        $(V_AT)mkdir -p $(dir $(patsubst %/,%,$@))
        $(call v_tag,MKDIR)mkdir $@
 
-LOCAL_ARCH_DIRS                 = bin/ etc/ games/ include/ lib/ libexec/ sbin/
+LOCAL_ARCH_DIRS                 = bin/ etc/ games/ include/ include.aside/
+LOCAL_ARCH_DIRS                += lib/ libexec/ sbin/
 LOCAL_ARCH_LINKS        = man
 man_LINKDEST            = share/man
 all:: $(foreach a,$(ALL_ARCHS),\
@@ -551,139 +637,34 @@ $(foreach a,$(ALL_ARCHS),\
        $(call v_tag,SYMLINK)ln -sf ../$(notdir $(patsubst %/,%,$@)) $(patsubst %/,%,$@)
 
 ###--------------------------------------------------------------------------
-### Constructing chroots.
-
-chroot-stamp            = $(addprefix $(STATE)/stamp/chroot.,$1)
-BUILD_CHROOTS           = $(addprefix chroot/,$(ALL_CHROOTS))
-CHROOT_STAMPS           = $(call chroot-stamp,$(ALL_CHROOTS))
-setup-chroots: $(BUILD_CHROOTS)
-$(BUILD_CHROOTS): chroot/%: $(STATE)/stamp/chroot.%
-.PHONY: setup-chroots $(BUILD_CHROOTS)
-
-$(CHROOT_STAMPS): $(STATE)/stamp/chroot.%:
-       $(V_AT)mkdir -p $(dir $@) log/
-       $(MAKE) \
-               $(STATE)/bin/mkbuildchroot $(STATE)/bin/install-cross-tools \
-               $(STATE)/etc/schroot/sbuild.schroot \
-               $$(call chroot-deps,$(STATE)/stamp/cross-tools.,$$*)
-       $(call v_tag,CHROOT)$(call v_log,setup-chroot.$*, \
-               $(SILENCE_LVM); \
-               $(ROOTLY) $(STATE)/bin/mkbuildchroot \
-                       $(call chroot-dist,$*) $(call chroot-arch,$*))
-       $(V_AT)touch $@
-
-UPDATE_CHROOTS          = $(addprefix update/,$(ALL_CHROOTS))
-update-chroots: $(UPDATE_CHROOTS)
-$(UPDATE_CHROOTS): update/%: $(STATE)/stamp/chroot.%
-       $(V_AT)mkdir -p log/
-       $(MAKE) $(STATE)/bin/install-cross-tools
-       $(call v_tag,UPDATE)$(call v_log,update-chroot.$*, { \
-               schroot -uroot -csource:$(LVPREFIX)$* -- \
-                       apt-get update && \
-               schroot -uroot -csource:$(LVPREFIX)$* -- \
-                       apt-get -y dist-upgrade && \
-               schroot -uroot -csource:$(LVPREFIX)$* -- \
-                       apt-get -y autoremove && \
-               schroot -uroot -csource:$(LVPREFIX)$* -- \
-                       apt-get -y clean && \
-               $(if $(filter $*,$(FOREIGN_CHROOTS)), \
-                       $(ROOTLY) $(STATE)/bin/install-cross-tools \
-                               $(call chroot-dist,$*) \
-                               $(call chroot-arch,$*), \
-                       :); \
-       })
-.PHONY: update-chroots $(UPDATE_CHROOTS)
-
-cross-tools-stamp       = $(addprefix $(STATE)/stamp/cross-tools.,$1)
-CROSS_TOOLS             = $(addprefix cross-tools/,$(NATIVE_CHROOTS))
-UPDATE_CROSS_TOOLS      = $(addprefix update-cross-tools/,$(NATIVE_CHROOTS))
-cross-tools: $(CROSS_TOOLS)
-update-cross-tools: $(UPDATE_CROSS_TOOLS)
-$(CROSS_TOOLS): cross-tools/%: $(STATE)/stamp/cross-tools.%
-define updcross
-       $(V_AT)mkdir -p log/
-       $(MAKE) $(STATE)/bin/update-cross-tools
-       $(call v_tag,UPDCROSS)$(call v_log,update-cross-tools.$*, \
-               $(STATE)/bin/update-cross-tools \
-                       $(call chroot-dist,$*) \
-                       $(call chroot-arch,$*))
-       $(V_AT)touch $(call cross-tools-stamp,$*)
-endef
-$(call cross-tools-stamp,$(NATIVE_CHROOTS)): $(STATE)/stamp/cross-tools.%: \
-               $$(call chroot-stamp,$$*)
-       $(V_AT)mkdir -p $(dir $@)
-       $(updcross)
-$(UPDATE_CROSS_TOOLS): update-cross-tools/%: \
-               $$(call chroot-stamp,$$*) _force
-       $(updcross)
-.PHONY: cross-tools update-cross-tools $(CROSS_TOOLS) $(UPDATE_CROSS_TOOLS)
+### Main chroot maintenance.
+
+OPTS                    =
+FRESH                   = 1w
+JOBS                    = chroot cross-tools pkg-build
+
+MAINTQ_                         = -q
+MAINTQ_0                = -q
+MAINT                   = +$(call v_tag,MAINT)\
+       PYTHONPATH=$(STATE)/lib/python $(STATE)/bin/chroot-maint \
+               $(MAINTQ_$V) $(OPTS)
+
+maint: all check
+       $(MAINT) -f$(FRESH) $(JOBS)
+.PHONY: maint
 
 ###--------------------------------------------------------------------------
-### Installing basic custom software.
-
-$(foreach p,$(LOCALPKGS), $(eval $p_VERSION := $(shell \
-       set -- pkg/$p-[0-9]*.tar.gz; \
-       case $$#,$$1 in \
-         (1,*\**) echo "NOT-FOUND"; exit 2 ;; \
-         (1,*) v=$${1#pkg/$p-}; v=$${v%.tar.gz}; echo "$$v" ;; \
-         (*) echo "AMBIGUOUS"; exit 2 ;; \
-       esac)))
-
-pkg-stamp               = \
-       $(foreach p,$1,$(STATE)/stamp/package.$p-$($p_VERSION).$2)
-unpack-pkg-stamp        = \
-       $(foreach p,$1,$(STATE)/stamp/unpack.$p-$($p_VERSION))
-PACKAGE_STAMPS          = \
-       $(foreach a,$(ALL_ARCHS),$(call pkg-stamp,$(LOCALPKGS),$a))
-INSTALL_PACKAGES        = $(addprefix install/,$(LOCALPKGS))
-install-packages: $(INSTALL_PACKAGES)
-$(INSTALL_PACKAGES): install/%: \
-       $$(foreach a,$$(ALL_ARCHS),$$(call pkg-stamp,$$*,$$a))
-
-$(foreach p,$(LOCALPKGS),$(call unpack-pkg-stamp,$p)): \
-               $(STATE)/stamp/unpack.%: pkg/%.tar.gz
-       $(V_AT)mkdir -p $(dir $@) $(LOCAL)/src/
-       $(call v_tag,UNPACK){ \
-               set -e; \
-               p=$(call package-dir-name,$*); \
-               v=$(call package-dir-version,$*); \
-               cd $(LOCAL)/src/; \
-               $(ROOTLY) rm -rf $$p-*; \
-               mkdir $$p-$$v.unpack; \
-               (cd $$p-$$v.unpack && tar xf $(HERE)/$<); \
-               mv $$p-$$v.unpack/$$p-$$v $$p-$$v; \
-               rmdir $$p-$$v.unpack/; \
-               cd $(HERE); \
-               touch $@; \
-       }
-
-$(PACKAGE_STAMPS): $(STATE)/stamp/package.%: \
-               $$(call unpack-pkg-stamp,$$(call package-name,$$*)) \
-               $$(call chroot-stamp,$$(PRIMARY_DIST)-$$(call package-arch,$$*))
-       $(V_AT)mkdir -p $(dir $@) log/
-       $(call v_tag,BUILD)$(call v_log,install-package.$*, { \
-               $(SILENCE_LVM); \
-               schroot -uroot -c$(LVPREFIX)$(PRIMARY_DIST)-$(call package-arch,$*) -- \
-               sh -exc ' \
-                       mount -oremount$(comma)rw /usr/local.schroot; \
-                       eatmydata apt-get update; \
-                       eatmydata apt-get -y install pkg-config; \
-                       p=$(call package-name,$*); \
-                       v=$(call package-version,$*); \
-                       a=$(call package-arch,$*); \
-                       cd /usr/local/src/$$p-$$v/; \
-                       rm -rf build.$$a/; \
-                       mkdir build.$$a/; \
-                       cd build.$$a/; \
-                       ../configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig.hidden; \
-                       make -j4; \
-                       make install; \
-                       mkdir -p /usr/local/lib/pkgconfig.hidden; \
-                       mv /usr/local/lib/pkgconfig/*.pc /usr/local/lib/pkgconfig.hidden || :' && \
-               schroot -uroot -csource:$(LVPREFIX)$(PRIMARY_DIST)-$(call package-arch,$*) -- \
-                       ldconfig; \
-       })
-       $(V_AT)touch $@
+### Running random commands.
+
+CMD                     = echo %d %a
+subst-command           = $(subst %d,$(call chroot-dist,$1), \
+                               $(subst %a,$(call chroot-arch,$1), \
+                                       $(subst %r,$1, $(CMD))))
+
+run: $(foreach c,$(ALL_CHROOTS),run/$c)
+$(foreach c,$(ALL_CHROOTS),run/$c): run/%:
+       $(V_AT)$(call v_print,RUN,$(call subst-command,$*))\
+               $(call subst-command,$*)
 
 ###--------------------------------------------------------------------------
 ### Other maintenance targets.