Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 86 additions & 5 deletions setup-build-env/install_cross_compilation_toolchain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,95 @@ fi

sudo dpkg --add-architecture "$DEB_ARCH"
sudo apt-get update -y

sudo apt-get install -y --no-install-recommends \
binfmt-support qemu-user-static \
"gcc-${GCC_VERSION}-${TARGET_ARCH}-linux-gnu" \
"g++-${GCC_VERSION}-${TARGET_ARCH}-linux-gnu" \
"linux-libc-dev:${DEB_ARCH}" \
"libelf-dev:${DEB_ARCH}" \
"libssl-dev:${DEB_ARCH}" \
"zlib1g-dev:${DEB_ARCH}"
"g++-${GCC_VERSION}-${TARGET_ARCH}-linux-gnu"

# Target libraries are downloaded and unpacked rather than installed as
# :${DEB_ARCH} multiarch packages, so that they never enter the host dpkg
# database. Being in it would subject them to Multi-Arch: same version equality
# against the host-arch copies, and to
# libc6-dev:${DEB_ARCH} Breaks libc6-dev-${DEB_ARCH}-cross (<< <glibc>~)
# which makes the multiarch and cross package sets mutually uninstallable
# whenever the archive's glibc moves ahead of src:cross-toolchain-base.
# See https://bugs.debian.org/1144098 and https://bugs.debian.org/1130544.
#
# ${SYSROOT} is already on the cross gcc's default search path, so the build
# needs no -I/-L/--sysroot. selftests/bpf shares one $(EXTRA_CFLAGS) between the
# host and target bpftool sub-makes, so a target-only flag would have nowhere to
# live anyway.
#
# Both shared objects and static archives are needed: test binaries link
# dynamically, but CI passes EXTRA_LDFLAGS=-static and the cross bpftool is
# linked statically.
SYSROOT="/usr/${TARGET_ARCH}-linux-gnu"
TARGET_LIBS=(
"libelf1t64:${DEB_ARCH}" "libelf-dev:${DEB_ARCH}"
"zlib1g:${DEB_ARCH}" "zlib1g-dev:${DEB_ARCH}"
"libzstd1:${DEB_ARCH}" "libzstd-dev:${DEB_ARCH}"
"libssl3t64:${DEB_ARCH}" "libssl-dev:${DEB_ARCH}"
)

STAGE="$(mktemp -d)"
trap 'rm -rf "${STAGE}"' EXIT
(
cd "${STAGE}"
apt-get download "${TARGET_LIBS[@]}"
mkdir -p x
for deb in *.deb; do
dpkg-deb -x "${deb}" x
done
)

sudo mkdir -p "${SYSROOT}/include" "${SYSROOT}/lib"

# Arch-specific headers are copied second so they win.
if [ -d "${STAGE}/x/usr/include" ]; then
sudo cp -a "${STAGE}/x/usr/include/." "${SYSROOT}/include/"
fi
if [ -d "${STAGE}/x/usr/include/${TARGET_ARCH}-linux-gnu" ]; then
sudo cp -a "${STAGE}/x/usr/include/${TARGET_ARCH}-linux-gnu/." \
"${SYSROOT}/include/"
fi

for libdir in "usr/lib/${TARGET_ARCH}-linux-gnu" "lib/${TARGET_ARCH}-linux-gnu"; do
if [ -d "${STAGE}/x/${libdir}" ]; then
sudo cp -a "${STAGE}/x/${libdir}/." "${SYSROOT}/lib/"
fi
done

# -dev packages may ship .so as absolute symlinks, which dangle once relocated.
for link in "${SYSROOT}"/lib/*; do
if [ ! -L "${link}" ]; then continue; fi
if [ -e "${link}" ]; then continue; fi
linktarget="$(basename "$(readlink "${link}")")"
if [ -e "${SYSROOT}/lib/${linktarget}" ]; then
sudo ln -sfn "${linktarget}" "${link}"
else
echo "WARNING: dangling symlink ${link} -> $(readlink "${link}")"
fi
done

# Surface a stale TARGET_LIBS here rather than as a link error much later.
sysroot_missing=0
for hdr in libelf.h gelf.h zlib.h openssl/evp.h; do
if [ ! -e "${SYSROOT}/include/${hdr}" ]; then
echo "ERROR: missing target header ${SYSROOT}/include/${hdr}"
sysroot_missing=1
fi
done
for lib in libelf.so libelf.a libz.so libz.a libzstd.a libcrypto.so libcrypto.a; do
if [ ! -e "${SYSROOT}/lib/${lib}" ]; then
echo "ERROR: missing target library ${SYSROOT}/lib/${lib}"
sysroot_missing=1
fi
done
if [ "${sysroot_missing}" -ne 0 ]; then
echo "Target sysroot assembly failed; TARGET_LIBS is probably stale."
exit 1
fi

sudo update-alternatives --install \
/usr/bin/${TARGET_ARCH}-linux-gnu-gcc \
Expand Down
Loading