### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
### USA.
-all::
+all:
clean::
check::
-.PHONY: all clean check
+help::
+.PHONY: all clean check help
.SECONDEXPANSION: #sorry
###--------------------------------------------------------------------------
CONFIG_VARS =
+help::
+ @echo "Configuration variables"
+
+## Make verbosity.
+V = 0
+help::; @echo " V build verbosity"
+
## Level of pickiness to aspire to.
NOTIFY_FATAL = 1
-
-## Path to this working tree.
-CONFIG_VARS += HERE
-HERE = $(abspath .)
+help::
+ @echo " NOTIFY_FATAL report fatal error on ..." && \
+ echo " 1 = error" && \
+ echo " 2 = warning" && \
+ echo " 3 = info"
## 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.
## 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)
## Debian distributions to support.
CONFIG_VARS += PRIMARY_DIST DISTS
PRIMARY_DIST = stretch
-DISTS = $(PRIMARY_DIST) buster bullseye sid
+DISTS = $(PRIMARY_DIST) buster bullseye bookworm 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.
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))
$(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
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
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.
## A directory in which we can maintain private files and state.
CONFIG_VARS += STATE
STATE = state
+help::; @echo " STATE directory for state files"
## 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))
+help::; @echo " LOCAL directory for chroot /usr/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.
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))
+
+###--------------------------------------------------------------------------
+### Basic help.
+
+help::
+ @echo "Basic targets" && \
+ echo " all build and install the infrastructure" && \
+ echo " clean delete build files" && \
+ echo " check verify correct installation"
+
###--------------------------------------------------------------------------
### Utilities.
comma = ,
## Silent-rules machinery.
-V = 0
V_AT = $(V_AT_$V)
V_AT_0 = @
v_print = $(call v_print_$V,$1,$2)
SILENCE_LVM = \
LVM_SUPPRESS_FD_WARNINGS=1; export LVM_SUPPRESS_FD_WARNINGS
+## $(call file-name,PATH)
+##
+## Strip any trailing `/' from the PATH.
+file-name = $(1:/=)
+
+## $(call base-name,PATH)
+##
+## Expand to the last component of PATH, whether or not it's a directory
+## name with a trailing `/'.
+base-name = $(notdir $(call file-name,$1))
+
+## $(call parent-dir,PATH)
+##
+## Expand to the parent directory of PATH, whether or not it's a directory
+## name with a trailing `/'.
+## `/'.
+parent-dir = $(dir $(call file-name,$1))
+
+## $(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.
## $(call squote,TXT)
##
## Single-quote TXT.
-squote = '$(subst ','\\'',$1)'
+squote = '$(subst ','\'',$1)'
+#'
## $(call chroot-dist,D-A) -> D
## $(call chroot-arch,D-A) -> A
check-symlink = $(call check,$1,"\`$2' is not a link to \`$3'", \
[ -L "$2" ] && [ "$$(readlink "$2")" = "$3" ])
+## DIR/
+##
+## Make a directory. Use as an order-only dependency.
+%/:; $(V_AT)mkdir -p $@
+
+###--------------------------------------------------------------------------
+### Python extensions.
+
+CC = gcc
+CFLAGS = -O2 -g -Wall
+
+LD = $(CC)
+LDFLAGS =
+
+c-source = $(foreach c,$1,src/$c)
+c-object = $(foreach c,$1,$(STATE)/obj/$(basename $c).o)
+
+PYEXT_PKGFLAGS := $(shell pkg-config --cflags python2)
+PYEXT_CFLAGS = -fPIC -fno-strict-aliasing $(PYEXT_PKGFLAGS)
+PYEXT_LDFLAGS = -shared
+
+PYEXTS += jobclient
+jobclient_SOURCES = jobclient.c
+
+PYEXT_ALLSRC = $(foreach x,$(PYEXTS),\
+ $(call c-source,$($x_SOURCES)))
+PYEXT_ALLOBJ = $(foreach x,$(PYEXTS),\
+ $(call c-object,$($x_SOURCES)))
+$(PYEXT_ALLOBJ): $(STATE)/obj/%.o: src/%.c | $$(dir $$@)
+ $(call v_tag,CC)$(CC) -c $(CFLAGS) $(PYEXT_CFLAGS) -o$@ $<
+
+PYMODULES = $(foreach x,$(PYEXTS),$(STATE)/lib/python/$x.so)
+all: $(PYMODULES)
+$(PYMODULES): $(STATE)/lib/python/%.so: \
+ $$(call c-object,$$($$*_SOURCES)) | $$(dir $$@)
+ $(call v_tag,LD)$(LD) $(LDFLAGS) $(PYEXT_LDFLAGS) -o$@ $^
+
###--------------------------------------------------------------------------
### Scripts.
-SCRIPTS += mkbuildchroot
+SCRIPTS += chroot-maint
SCRIPTS += mkchrootconf
-SCRIPTS += install-cross-tools update-cross-tools
SUBST_SCRIPTS = $(addprefix $(STATE)/bin/,$(SCRIPTS))
-all:: $(SUBST_SCRIPTS)
-$(SUBST_SCRIPTS): $(STATE)/bin/%: bin/% $(STATE)/config.sh
- $(V_AT)mkdir -p $(dir $@)
+all: $(SUBST_SCRIPTS)
+$(SUBST_SCRIPTS): $(STATE)/bin/%: bin/% $(STATE)/config.sh | $$(dir $$@)
$(call v_tag,SUBST){ \
sed \
-e '2i### GENERATED by distorted-chroot: do not edit' \
## In a chroot, `/etc/apt/sources.list' links to
## `/usr/local.schroot/etc/apt/sources.$d' for the appropriate distribution.
-APT_SOURCES = $(foreach d,$(DISTS), $(LOCAL)/etc/apt/sources.$d)
-CLEANFILES += $(APT_SOURCES)
-all:: $(APT_SOURCES)
+APT_SOURCES = $(foreach d,$(DISTS),$(LOCAL)/etc/apt/sources.$d)
+all: $(APT_SOURCES)
-$(foreach d,$(DISTS), $(STATE)/etc/apt/aptsrc.$d): $(STATE)/etc/apt/aptsrc.%:
- $(V_AT)mkdir -p $(dir $@)
+$(foreach d,$(DISTS),$(STATE)/etc/apt/aptsrc.$d): \
+ $(STATE)/etc/apt/aptsrc.%: | $$(dir $$@)
$(call v_tag,GEN){ \
echo "### -*-conf-*- GENERATED by distorted-chroot: do not edit"; \
echo "subscribe"; \
} >$@.new && mv $@.new $@
$(APT_SOURCES): $(LOCAL)/etc/apt/sources.%: \
- $$(APTSRC) $$($$*_APTSRC) $$(STATE)/etc/apt/aptsrc.$$*
- $(V_AT)mkdir -p $(dir $@)
+ $$(APTSRC) $$($$*_APTSRC) $$(STATE)/etc/apt/aptsrc.$$* \
+ | $$(dir $$@)
$(call v_tag,GEN)bin/mkaptsrc \
$(APTSRC) $($*_APTSRC) $(STATE)/etc/apt/aptsrc.$* \
>$@.new && mv $@.new $@
+CLEANFILES += $(APT_SOURCES)
## In a chroot, a link `/etc/apt/apt.conf.d/FOO' is created for each file in
## `/usr/local.schroot/etc/apt/apt.conf.d/FOO'.
APT_CONFIGS = $(addprefix $(LOCAL)/etc/apt/apt.conf.d/,$(APTCONF))
-all:: $(APT_CONFIGS)
+all: $(APT_CONFIGS)
$(APT_CONFIGS): $(LOCAL)/etc/apt/apt.conf.d/%: \
- $$(or $$($$*_APTCONFSRC) $$(APTCONF_DIR)/$$*)
- $(V_AT)mkdir -p $(dir $@)
+ $$(or $$(_$$*_APTCONFSRC) etc/apt-conf.d/$$*) | $$(dir $$@)
$(call v_tag,COPY)cp $< $@.new && mv $@.new $@
clean::; rm -f $(APT_CONFIGS)
EATMYDATA_HACKS += apt-get aptitude dpkg
SYMLINK_EATMYDATA_HACKS = $(addprefix $(LOCAL)/hacks/,$(EATMYDATA_HACKS))
-all:: $(SYMLINK_EATMYDATA_HACKS)
+all: $(SYMLINK_EATMYDATA_HACKS)
$(SYMLINK_EATMYDATA_HACKS): $(LOCAL)/hacks/%: \
- $$(if $$(call symlink-ok-p,$$@,/usr/bin/eatmydata),,_force)
- $(V_AT)mkdir -p $(dir $@)
+ $$(if $$(call symlink-ok-p,$$@,/usr/bin/eatmydata),,_force) \
+ | $$(dir $$@)
$(call v_tag,SYMLINK)ln -sf /usr/bin/eatmydata $@.new && mv $@.new $@
clean::; rm -f $(SYMLINK_EATMYDATA_HACKS)
SCRIPT_HACKS += buildwrap
COPY_SCRIPT_HACKS = $(addprefix $(LOCAL)/hacks/,$(SCRIPT_HACKS))
-all:: $(COPY_SCRIPT_HACKS)
-$(COPY_SCRIPT_HACKS): $(LOCAL)/hacks/%: bin/%
- $(V_AT)mkdir -p $(dir $@)
+all: $(COPY_SCRIPT_HACKS)
+$(COPY_SCRIPT_HACKS): $(LOCAL)/hacks/%: bin/% | $$(dir $$@)
$(call v_tag,COPY)cp $< $@.new && mv $@.new $@
clean::; rm -f $(COPY_SCRIPT_HACKS)
###--------------------------------------------------------------------------
### `schroot' and `sbuild' configuration.
-all:: schroot-config
-schroot-config::
+all: schroot-config
+schroot-config:
.PHONY: schroot-config
check::; $(call check-mountpoint,WARN,/var/lib/sbuild/build)
%print-varlist = { \
echo "\#\#\# -*-sh-*- GENERATED by distorted-chroot: do not edit"; \
- $(foreach v,$1, echo $v=\''$(subst ','\'\\\'\'',$($v))'\';) \
-} #'
+ $(foreach v,$1,$(if $(call definedp,$v),\
+ echo $v=\'$(call squote,$($v))\';)) \
+}
schroot-config_HASH := \
$(shell $(call %print-varlist,$(CONFIG_VARS)) | \
sha256sum | cut -c1-32)
schroot-config_FILE = $(STATE)/config.sh-$(schroot-config_HASH)
-$(schroot-config_FILE):
- $(V_AT)mkdir -p $(STATE)
+$(schroot-config_FILE): | $(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
+schroot-config: $(STATE)/config.sh
$(STATE)/config.sh: $(schroot-config_FILE)
- $(call v_tag,SYMLINK)ln -sf $(notdir $<) $@
+ $(call v_tag,SYMLINK)ln -sf $(call base-name,$<) $@
-schroot-config:: $(STATE)/etc/schroot/sbuild.schroot
-$(STATE)/etc/schroot/sbuild.schroot: $(STATE)/bin/mkchrootconf
- $(V_AT)mkdir -p $(dir $@)
+schroot-config: $(LOCAL)/etc/schroot/sbuild.schroot
+$(LOCAL)/etc/schroot/sbuild.schroot: $(STATE)/bin/mkchrootconf | $$(dir $$@)
$(call v_tag,GEN)$(STATE)/bin/mkchrootconf >$@.new && \
$(ROOTLY) chown root:root $@.new && mv $@.new $@
-check::; $(call check-symlink,WARN,/etc/schroot/chroot.d/sbuild,$(HERE)/$(STATE)/etc/schroot/sbuild.schroot)
+CLEANFILES += $(LOCAL)/etc/schroot/sbuild.schroot
+check::; $(call check-symlink,WARN,/etc/schroot/chroot.d/sbuild,$(ABSLOCAL)/etc/schroot/sbuild.schroot)
-schroot-config:: $(STATE)/etc/schroot/sbuild.profile/copyfiles
-$(STATE)/etc/schroot/sbuild.profile/copyfiles: $(schroot-config_STAMP)
- $(V_AT)mkdir -p $(dir $@)
+schroot-config: $(LOCAL)/etc/schroot/sbuild.profile/copyfiles
+$(LOCAL)/etc/schroot/sbuild.profile/copyfiles: \
+ $(schroot-config_STAMP) | $$(dir $$@)
$(call v_tag,GEN){ \
echo "### -*-conf-*- GENERATED by distorted-chroot: do not edit"; \
for i in $(SCHROOT_COPYFILES); do echo "$$i"; done; \
} >$@.new && mv $@.new $@
+CLEANFILES += $(LOCAL)/etc/schroot/sbuild.profile/copyfiles
-schroot-config:: $(STATE)/etc/schroot/sbuild.profile/nssdatabases
-$(STATE)/etc/schroot/sbuild.profile/nssdatabases: $(schroot-config_STAMP)
- $(V_AT)mkdir -p $(dir $@)
+schroot-config: $(LOCAL)/etc/schroot/sbuild.profile/nssdatabases
+$(LOCAL)/etc/schroot/sbuild.profile/nssdatabases: \
+ $(schroot-config_STAMP) | $$(dir $$@)
$(call v_tag,GEN){ \
echo "### -*-conf-*- GENERATED by distorted-chroot: do not edit"; \
for i in $(SCHROOT_NSSDATABASES); do echo "$$i"; done; \
} >$@.new && mv $@.new $@
+CLEANFILES += $(LOCAL)/etc/schroot/sbuild.profile/nssdatabases
-schroot-config:: $(STATE)/etc/schroot/sbuild.profile/fstab
-$(STATE)/etc/schroot/sbuild.profile/fstab: \
- etc/sbuild.fstab.in $(schroot-config_STAMP)
- $(V_AT)mkdir -p $(dir $@)
+schroot-config: $(LOCAL)/etc/schroot/sbuild.profile/fstab
+$(LOCAL)/etc/schroot/sbuild.profile/fstab: \
+ etc/sbuild.fstab.in $(schroot-config_STAMP) | $$(dir $$@)
$(call v_tag,SUBST)$(call subst-file,### -*-conf-*-) \
<$< >$@.new && mv $@.new $@
+CLEANFILES += $(LOCAL)/etc/schroot/sbuild.profile/fstab
-check::; $(call check-symlink,WARN,/etc/schroot/sbuild,$(HERE)/$(STATE)/etc/schroot/sbuild.profile)
+check::; $(call check-symlink,WARN,/etc/schroot/sbuild,$(ABSLOCAL)/etc/schroot/sbuild.profile)
-schroot-config:: $(STATE)/etc/sbuild.conf
-$(STATE)/etc/sbuild.conf: etc/sbuild.conf.in $(schroot-config_STAMP)
- $(V_AT)mkdir -p $(dir $@)
+schroot-config: $(LOCAL)/etc/sbuild.conf
+$(LOCAL)/etc/sbuild.conf: etc/sbuild.conf.in \
+ $(schroot-config_STAMP) | $$(dir $$@)
$(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,$(ABSLOCAL)/etc/sbuild.conf)
+check::; $(call check-executable,WARN,/usr/local.schroot/hacks/apt-get)
SCHROOT_SCRIPTS += 11private
SCHROOT_SCRIPTS += 15binfmt
SCHROOT_SCRIPTS += 51chrootenv
-COPY_SCHROOT_SCRIPTS = $(addprefix $(STATE)/etc/schroot/setup.d/,$(SCHROOT_SCRIPTS))
-schroot-config:: $(COPY_SCHROOT_SCRIPTS)
+COPY_SCHROOT_SCRIPTS = $(addprefix $(LOCAL)/etc/schroot/setup.d/,$(SCHROOT_SCRIPTS))
+schroot-config: $(COPY_SCHROOT_SCRIPTS)
$(COPY_SCHROOT_SCRIPTS): \
- $(STATE)/etc/schroot/setup.d/%: etc/schroot-scripts/%
- $(V_AT)mkdir -p $(dir $@)
+ $(LOCAL)/etc/schroot/setup.d/%: etc/schroot-scripts/% \
+ | $$(dir $$@)
$(call v_tag,COPY)cp $< $@.new && mv $@.new $@
+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)/$(STATE)/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 | $$(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):
- $(V_AT)mkdir -p $(dir $(patsubst %/,%,$@))
- $(call v_tag,MKDIR)mkdir $@
+LOCAL_EXTRA_DIRS = share/man/
+all: $(foreach d,$(LOCAL_COMMON_DIRS) $(LOCAL_EXTRA_DIRS),$(LOCAL)/$d)
-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),\
+all: $(foreach a,$(ALL_ARCHS),\
$(LOCAL)/$a/ \
$(foreach d,$(LOCAL_ARCH_DIRS),$(LOCAL)/$a/$d) \
$(foreach d,$(LOCAL_ARCH_LINKS),$(LOCAL)/$a/$d) \
$(foreach d,$(LOCAL_COMMON_DIRS),$(LOCAL)/$a/$d))
-$(foreach a,$(ALL_ARCHS),$(LOCAL)/$a/):
- $(call v_tag,MKDIR)mkdir $@
-$(foreach a,$(ALL_ARCHS),\
- $(foreach d,$(LOCAL_ARCH_DIRS),$(LOCAL)/$a/$d)):
- $(V_AT)mkdir -p $(dir $(patsubst %/,%,$@))
- $(call v_tag,MKDIR)mkdir $@
$(foreach a,$(ALL_ARCHS),\
$(foreach d,$(LOCAL_ARCH_LINKS),$(LOCAL)/$a/$d)): \
- $$(if $$(call symlink-ok-p,$$@,$$($$(notdir $$@)_LINKDEST)),,_force)
- $(V_AT)mkdir -p $(notdir $@)
- $(call v_tag,SYMLINK)ln -sf $($(notdir $@)_LINKDEST) $@
+ $$(if $$(call symlink-ok-p,$$@,$$($$(call base-name,$$@)_LINKDEST)),,_force) \
+ | $$(dir $$@)
+ $(call v_tag,SYMLINK)ln -sf $($(call base-name,$@)_LINKDEST) $@
$(foreach a,$(ALL_ARCHS),\
$(foreach d,$(LOCAL_COMMON_DIRS),$(LOCAL)/$a/$d)): \
- $$(if $$(call symlink-ok-p,$$@,../$$(notdir $$(patsubst %/,%,$$@))),,_force)
- $(V_AT)mkdir -p $(dir $(patsubst %/,%,$@))
- $(call v_tag,SYMLINK)ln -sf ../$(notdir $(patsubst %/,%,$@)) $(patsubst %/,%,$@)
+ $$(if $$(call symlink-ok-p,$$@,../$$(call base-name,$$@)),,_force) \
+ | $$(call parent-dir,$$@)
+ $(call v_tag,SYMLINK)ln -sf ../$(call base-name,$@) $(call file-name,$@)
###--------------------------------------------------------------------------
-### 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.%: \
- $$(call chroot-deps,$(STATE)/stamp/cross-tools.,$$*)
- $(V_AT)mkdir -p $(dir $@) log/
- $(MAKE) \
- $(STATE)/bin/mkbuildchroot $(STATE)/bin/install-cross-tools \
- $(STATE)/etc/schroot/sbuild.schroot
- $(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
+
+help::
+ @echo "Maintenance targets" && \
+ echo " maint run chroot maintenance" && \
+ echo "Maintenance variables" && \
+ echo " FRESH max time between updates" && \
+ echo " N[smhdw] | create | force" && \
+ echo " JOBS maintenance jobs to run" && \
+ echo " ACT[.PAT,...][/FRESH]" && \
+ echo " OPTS additional options (bin/chroot-maint --help)" && \
+ echo "Maintenance actions" && \
+ echo " chroot create and populate chroot" && \
+ echo " cross-tools build cross-compilation toolchains" && \
+ echo " pkg-source download and unpack local utilities" && \
+ echo " pkg-build compile and install local utilities"
###--------------------------------------------------------------------------
-### 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.