[Buildroot] [PATCH 13/13] toolchain/external: support merged-bin
Yann E. MORIN
yann.morin.1998 at free.fr
Wed May 14 16:58:25 UTC 2025
When an external toolchain does not have a merged-bin, we can end up
with a situation where the toolchain installs an staging/usr/sbin/
directory, overriding the sbin symlink with an actual directory. When
not using PPD, this does not cause any harm.
However, with PPD, the build fails when preparing the staging (the
host/) for packages when the skeleton is eventually rsynced, e.g.:
$ cat defconfig
BR2_aarch64=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_BOOTLIN=y
BR2_PER_PACKAGE_DIRECTORIES=y
BR2_INIT_NONE=y
BR2_ROOTFS_MERGED_USR=y
BR2_ROOTFS_MERGED_SBIN=y
# BR2_PACKAGE_BUSYBOX is not set
BR2_PACKAGE_ZLIB=y
# BR2_TARGET_ROOTFS_TAR is not set
$ make zlib
[...]
>>> zlib Configuring
mkdir -p [...]/per-package/zlib/host
rsync -a --hard-links --link-dest=[...]/per-package/host-skeleton/host/ [...]/per-package/host-skeleton/host/ [...]/per-package/zlib/host
rsync -a --hard-links --link-dest=[...]/per-package/libzlib/host/ [...]/per-package/libzlib/host/ [...]/per-package/zlib/host
rsync -a --hard-links --link-dest=[...]/per-package/skeleton/host/ [...]/per-package/skeleton/host/ [...]/per-package/zlib/host
could not make way for new symlink: aarch64-buildroot-linux-gnu/sysroot/usr/sbin
cannot delete non-empty directory: aarch64-buildroot-linux-gnu/sysroot/usr/sbin
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.3.0]
make[1]: *** [package/pkg-generic.mk:256: [...]/build/zlib/.stamp_configured] Error 23
make: *** [Makefile:23: _all] Error 2
The root cause is that, in the skeleton, we end up with
[staging]/usr/sbin as a synlink to bin, but when the external toolchain
gets installed, the symlinbk is replaced by a directory. Later, when we
aggregate the PPD before configuring a package, it often happens that a
dependant package be rsynced before the toolchain and the skeleton, as
seen above, in which case the sbin directory from the toolchain, by way
of the dependency to a package, is already present when rsync wants to
create a symlink as rsynced from the skeleton.
In the example above, this plays in this order:
1. skeleton gets installed, provides a symlink
2. toolchain-external-bootlin rsyncs from skeleton, gets a symlink
3. toolchain-external-bootlin gets installed, replaces symlink with a
directory
4. libzlib rsyncs from skeleton, gets a ymlink, then rsyncs from
toolchain-e-b, gets a directory
5. zlib rsyncs from libzlib first (because alphabetical ordering), gets
a directory, then rsyncs from skeleton, which rsyncs from a symlink,
but the dstination is a non-empty directory, so rsync fails.
It is perfectly legit that an external toolchain does not use a
merged-bin setup, so we must accept that as input. We do so by treating
the /usr/sbin entry specially, like we already do for a few others, of
which /sbin itself for example.
Note that the merged-usr setup has no issue, because we already handle
the lib dirctories speically too.
Signed-off-by: Yann E. MORIN <yann.morin.1998 at free.fr>
Cc: Giulio Benetti <giulio.benetti at benettiengineering.com>
Cc: Romain Naour <romain.naour at gmail.com>
Cc: Thomas Petazzoni <thomas.petazzoni at bootlin.com>
---
toolchain/helpers.mk | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/toolchain/helpers.mk b/toolchain/helpers.mk
index f3fdaaec07..21c710d0fb 100644
--- a/toolchain/helpers.mk
+++ b/toolchain/helpers.mk
@@ -96,6 +96,10 @@ copy_toolchain_lib_root = \
# Note that the 'locale' directories are not copied. They are huge
# (400+MB) in CodeSourcery toolchains, and they are not really useful.
#
+# usr/sbin may be a directory in the source toolchain, but a symlink
+# in the destination sysroot, when we are using a merged-bin. Account
+# for that.
+#
# $1: main sysroot directory of the toolchain
# $2: arch specific sysroot directory of the toolchain
# $3: arch specific subdirectory in the sysroot
@@ -109,13 +113,13 @@ copy_toolchain_sysroot = \
ARCH_SUBDIR="$(strip $3)"; \
ARCH_LIB_DIR="$(strip $4)" ; \
SUPPORT_LIB_DIR="$(strip $5)" ; \
- for i in etc $${ARCH_LIB_DIR} sbin usr usr/$${ARCH_LIB_DIR}; do \
+ for i in etc $${ARCH_LIB_DIR} sbin usr usr/$${ARCH_LIB_DIR} usr/sbin; do \
if [ ! -d $${ARCH_SYSROOT_DIR}/$$i ] ; then \
continue ; \
fi ; \
if [ "$$i" = "usr" ]; then \
rsync -au --chmod=u=rwX,go=rX --exclude 'locale/' \
- --include '/libexec*/' --exclude '/lib*/' \
+ --include '/libexec*/' --exclude '/lib*/' --exclude '/sbin' \
$${ARCH_SYSROOT_DIR}/$$i/ $(STAGING_DIR)/$$i/ ; \
else \
rsync -au --chmod=u=rwX,go=rX --exclude 'locale/' \
--
2.47.0
More information about the buildroot
mailing list