Scripts for bootstrapping various programming languages
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

370 lines
13 KiB

# vim:set ft=sh:
# Changelog:
# - 2025:
# - Upstreamed portage patch
# - Cross-compile all packages in packages.build for the profile
# (this simplifies the steps afterwards significantly)
# - Pin to GCC 13 (gcc 14 isn't working...)
# - Future proofing by ignoring HTTPs certificates
# (portage verifies the checksums anyway)
# - Avoid using wget (need to set FETCHCOMMAND anyway...)
# - Future proofing by not hardcoding a python version
# - 2024.8:
# - Rewrite bootstrap to avoid using LFS
# - Pin the repository version
# - 2024:
# - Initial version
# Overview of bootstrap:
# step 0: Build live-bootstrap as a starting point
# step 1: Update python, install portage and extra dependencies for later stages
# step 2: Create an x86_64 cross-toolchain in /cross
# step 3: Cross-compile a minimal x86_64 system in /gentoo
# step 4: Boot into the final system and finish installation
# Build live-bootstrap
git clone -b 1.0 --depth=1 --recursive https://github.com/fosslinux/live-bootstrap
cd live-bootstrap
./download-distfiles.sh
./rootfs.py -c --external-sources --cores $(nproc)
umount target/dev/shm # double mounted?
umount target/dev/shm target/sys target/proc target/tmp
# Optional: Back up the system
env -i chroot target tar --exclude='/external' --sort=name -cf /target.tar /
env -i chroot target bzip2 -9v /target.tar
mv target/external/repo .
mv target/target.tar.bz2 .
rm -rf target/external
# Optional: Keep distfiles in one place
mkdir -p target/var/cache/distfiles
mount --bind distfiles target/var/cache/distfiles
# Chroot into the live-bootstrap system
cd target
mount -t proc proc proc
mount -t sysfs sysfs sys
mount -t devtmpfs devtmpfs dev
mount -t devpts devpts dev/pts
env -i TERM="$TERM" chroot . /bin/bash -l
umask 022
source /steps/env
mkdir -p /var/cache/distfiles; cd /var/cache/distfiles
curl -LO http://gitweb.gentoo.org/proj/portage.git/snapshot/portage-3.0.66.1.tar.bz2
curl -LO http://distfiles.gentoo.org/snapshots/squashfs/gentoo-20250101.xz.sqfs
curl -LO https://github.com/plougher/squashfs-tools/archive/refs/tags/4.6.1/squashfs-tools-4.6.1.tar.gz
cd /tmp
# Build squashfs-tools to extract the ::gentoo tree
tar xf /var/cache/distfiles/squashfs-tools-4.6.1.tar.gz
cd squashfs-tools-4.6.1
make -C squashfs-tools install \
INSTALL_PREFIX=/usr \
XZ_SUPPORT=1
cd ..
rm -rf squashfs-tools-4.6.1
# Unpack the ::gentoo tree
unsquashfs /var/cache/distfiles/gentoo-20250101.xz.sqfs
mkdir -p /var/db/repos
rm -rf /var/db/repos/gentoo
mv squashfs-root /var/db/repos/gentoo
# Install temporary copy of portage
tar xf /var/cache/distfiles/portage-3.0.66.1.tar.bz2
ln -sf portage-3.0.66.1 portage
# Add portage user/group
echo 'portage:x:250:250:portage:/var/tmp/portage:/bin/false' >> /etc/passwd
echo 'portage::250:portage' >> /etc/group
# Configure portage
mkdir -p /etc/portage/make.profile
cat > /etc/portage/make.profile/make.defaults << 'EOF'
FETCHCOMMAND="curl -k --retry 3 -m 60 --ftp-pasv -o \"\${DISTDIR}/\${FILE}\" -L \"\${URI}\""
RESUMECOMMAND="curl -C - -k --retry 3 -m 60 --ftp-pasv -o \"\${DISTDIR}/\${FILE}\" -L \"\${URI}\""
FEATURES="-news -sandbox -usersandbox -pid-sandbox -parallel-fetch"
BINPKG_COMPRESS="bzip2"
ARCH="x86"
ABI="$ARCH"
DEFAULT_ABI="$ARCH"
ACCEPT_KEYWORDS="$ARCH"
CHOST="i386-unknown-linux-musl"
LIBDIR_x86="lib/$CHOST"
PKG_CONFIG_PATH="/usr/lib/$CHOST/pkgconfig"
IUSE_IMPLICIT="kernel_linux elibc_glibc elibc_musl prefix prefix-guest"
IUSE_IMPLICIT="$IUSE_IMPLICIT x86 amd64" # dev-libs/gmp
IUSE_IMPLICIT="$IUSE_IMPLICIT sparc" # sys-libs/zlib
USE_EXPAND="PYTHON_TARGETS PYTHON_SINGLE_TARGET"
USE="kernel_linux elibc_musl build"
SKIP_KERNEL_CHECK=y # linux-info.eclass
EOF
cat > /etc/portage/package.use << 'EOF'
dev-lang/python -ensurepip -ncurses -readline -sqlite -ssl
EOF
grep '^PYTHON_TARGETS=\|^PYTHON_SINGLE_TARGET=' \
/var/db/repos/gentoo/profiles/base/make.defaults \
>> /etc/portage/make.profile/make.defaults
# Specify what packages may or may not be installed in the live-bootstrap system
mkdir -p /etc/portage/profile
echo '*/*' > /etc/portage/package.mask
cat > /etc/portage/package.unmask << 'EOF'
app-alternatives/bzip2
app-alternatives/ninja
app-arch/bzip2 # replaces files, live-bootstrap doesn't build libbz2
app-arch/lzip
app-arch/unzip
app-misc/pax-utils
app-portage/elt-patches
dev-build/autoconf
dev-build/autoconf-wrapper # replaces files
dev-build/automake # replaces files
dev-build/automake-wrapper # replaces files
dev-build/make # replaces files
dev-build/meson
dev-build/meson-format-array
dev-build/ninja
dev-lang/python
dev-lang/python-exec # replaces files
dev-lang/python-exec-conf
dev-libs/expat
dev-libs/mpdecimal
dev-python/flit-core
dev-python/gentoo-common
dev-python/gpep517
dev-python/installer
dev-python/jaraco-collections
dev-python/jaraco-context
dev-python/jaraco-functools
dev-python/jaraco-text
dev-python/more-itertools
dev-python/packaging
dev-python/setuptools
dev-python/wheel
dev-util/pkgconf # replaces files, dev-lang/python ebuild requires "--keep-system-libs" option when cross-compiling
net-misc/rsync
sys-apps/findutils # replaces files, portage requires 4.9, live-bootstrap provides 4.2.33
sys-apps/gentoo-functions
sys-apps/portage
sys-devel/binutils-config
sys-devel/gcc-config
sys-devel/gnuconfig
virtual/pkgconfig
EOF
cat > /etc/portage/profile/package.provided << 'EOF'
acct-user/portage-0
app-alternatives/awk-0
app-alternatives/gzip-0
app-alternatives/lex-0
app-alternatives/yacc-0
app-arch/tar-1.27
app-arch/xz-utils-5.4.0
app-arch/zstd-0
app-crypt/libb2-0
app-crypt/libbz2-0
dev-build/autoconf-archive-0
dev-build/libtool-2.4.7-r3
dev-lang/perl-5.38.2-r3
dev-libs/libffi-0
dev-libs/popt-1.5
dev-python/platformdirs-4.2.2
dev-python/setuptools-scm-0
dev-python/trove-classifiers-2024.10.16
dev-util/re2c-0
sys-apps/baselayout-2.9
sys-apps/help2man-0
sys-apps/locale-gen-0
sys-apps/sandbox-2.2
sys-apps/sed-4.0.5
sys-apps/texinfo-7.1
sys-apps/util-linux-0
sys-devel/binutils-2.27
sys-devel/bison-3.5.4
sys-devel/flex-2.5.4
sys-devel/gcc-6.2
sys-devel/gettext-0
sys-devel/m4-1.4.16
sys-devel/patch-0
sys-libs/zlib-1.2.12
virtual/libcrypt-0
virtual/libintl-0
EOF
# Turn /bin/bzip2 into a symlink to avoid failures in app-arch/bzip2
if [ ! -h /bin/bzip2 ]; then
mv /bin/bzip2 /bin/bzip2-reference
ln -s bzip2-reference /bin/bzip2
fi
# For some reason, make hangs when used in parallel, rebuild it first.
MAKEOPTS=-j1 ./portage/bin/emerge -D1n app-arch/lzip dev-build/make
# Upgrade python and install portage
./portage/bin/emerge -D1n sys-apps/portage
# Install BDEPENDs for cross-toolchain
emerge -D1n sys-devel/binutils-config # sys-devel/binutils
emerge -D1n sys-devel/gcc-config # sys-devel/gcc
emerge -D1n net-misc/rsync # sys-kernel/linux-headers
# Add cross compiler to PATH
cat > /etc/env.d/50baselayout << 'EOF'
PATH=/cross/usr/bin:/usr/bin
EOF
env-update
# Set up cross compiler
mkdir -p /cross/etc/portage
ln -sf /etc/portage/make.profile /cross/etc/portage/make.profile
cat > /cross/etc/portage/make.conf << 'EOF'
USE="prefix multilib"
CTARGET="x86_64-bootstrap-linux-gnu"
LIBDIR_x86="lib"
LIBDIR_amd64="lib64"
DEFAULT_ABI="amd64"
MULTILIB_ABIS="amd64 x86"
ACCEPT_KEYWORDS="amd64"
EOF
cat > /cross/etc/portage/package.use << 'EOF'
sys-devel/gcc -sanitize -fortran
EOF
mkdir -p /cross/etc/portage/env/sys-devel
cat > /cross/etc/portage/env/sys-devel/gcc << 'EOF'
EXTRA_ECONF='--with-sysroot=$EPREFIX/usr/$CTARGET --enable-threads'
EOF
cat > /cross/etc/portage/package.mask << 'EOF'
>=sys-devel/gcc-14
EOF
# TODO: Build using gcc 14
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross USE='headers-only' emerge -O1 sys-kernel/linux-headers
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross USE='headers-only -multilib' emerge -O1 sys-libs/glibc
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross emerge -O1 sys-devel/binutils
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross USE='-cxx' emerge -O1 sys-devel/gcc
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross emerge -O1 sys-kernel/linux-headers
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross emerge -O1 sys-libs/glibc
PORTAGE_CONFIGROOT=/cross EPREFIX=/cross emerge -O1 sys-devel/gcc
# Reconfigure cross toolchain for final system
cat > /cross/usr/lib/gcc/x86_64-bootstrap-linux-gnu/specs << 'EOF'
*link:
+ %{!shared:%{!static:%{!static-pie:-dynamic-linker %{m32:/lib/ld-linux.so.2;:/lib64/ld-linux-x86-64.so.2}}}}
EOF
for tool in gcc g++; do
rm -f /cross/usr/bin/x86_64-bootstrap-linux-gnu-$tool
cat > /cross/usr/bin/x86_64-bootstrap-linux-gnu-$tool << EOF
#!/bin/sh
exec /cross/usr/i386-unknown-linux-musl/x86_64-bootstrap-linux-gnu/gcc-bin/*/x86_64-bootstrap-linux-gnu-$tool --sysroot=/gentoo "\$@"
EOF
chmod +x /cross/usr/bin/x86_64-bootstrap-linux-gnu-$tool
done
cat > /cross/usr/bin/x86_64-bootstrap-linux-gnu-pkg-config << 'EOF'
#!/bin/sh
export PKG_CONFIG_SYSROOT_DIR=/gentoo
export PKG_CONFIG_LIBDIR=/gentoo/usr/lib64/pkgconfig:/gentoo/usr/share/pkgconfig
export PKG_CONFIG_SYSTEM_INCLUDE_PATH=/gentoo/usr/include
export PKG_CONFIG_SYSTEM_LIBRARY_PATH=/gentoo/lib64:/gentoo/usr/lib64
exec pkg-config "$@"
EOF
chmod +x /cross/usr/bin/x86_64-bootstrap-linux-gnu-pkg-config
# Configure cross-compilation for final system
mkdir -p /gentoo.cfg/etc/portage
ln -sf ../../../var/db/repos/gentoo/profiles/default/linux/amd64/23.0 /gentoo.cfg/etc/portage/make.profile
cat > /gentoo.cfg/etc/portage/make.conf << 'EOF'
FETCHCOMMAND="curl -k --retry 3 -m 60 --ftp-pasv -o \"\${DISTDIR}/\${FILE}\" -L \"\${URI}\""
RESUMECOMMAND="curl -C - -k --retry 3 -m 60 --ftp-pasv -o \"\${DISTDIR}/\${FILE}\" -L \"\${URI}\""
FEATURES="-news -sandbox -usersandbox -pid-sandbox -parallel-fetch"
BINPKG_COMPRESS="bzip2"
CBUILD="i386-unknown-linux-musl"
CHOST="x86_64-bootstrap-linux-gnu"
CFLAGS_x86="$CFLAGS_x86 -msse" # https://bugs.gentoo.org/937637
CONFIG_SITE="$PORTAGE_CONFIGROOT/etc/portage/config.site"
USE="-* build $BOOTSTRAP_USE -zstd"
SKIP_KERNEL_CHECK=y # linux-info.eclass
EOF
cat > /gentoo.cfg/etc/portage/package.use << 'EOF'
# https://gitweb.gentoo.org/proj/releng.git/tree/releases/portage/stages/profile/package.use.force/releng/alternatives
app-alternatives/lex flex
app-alternatives/yacc bison
app-alternatives/tar gnu
app-alternatives/gzip reference
app-alternatives/bzip2 reference
EOF
cat > /gentoo.cfg/etc/portage/config.site << 'EOF'
if [ "${CBUILD:-${CHOST}}" != "${CHOST}" ]; then
# https://gitweb.gentoo.org/proj/crossdev.git/tree/wrappers/site/linux
ac_cv_file__dev_ptmx=yes
ac_cv_file__dev_ptc=no
fi
EOF
cat > /gentoo.cfg/etc/portage/package.mask << 'EOF'
>=sys-devel/gcc-14
EOF
# TODO: Build using gcc 14
# TODO: USE=zstd causes binutils to try to link with target zstd instead of
# host. zstd cannot be built for host due to lack of libatomic in gcc.
# Cross-compile a basic system
pkgs_build="$(PORTAGE_CONFIGROOT=/gentoo.cfg python3 -c 'import portage
print(*portage.util.stack_lists([portage.util.grabfile_package("%s/packages.build"%x)for x in portage.settings.profiles],incremental=1))')"
PORTAGE_CONFIGROOT=/gentoo.cfg ROOT=/gentoo SYSROOT=/gentoo emerge -O1n \
sys-apps/baselayout \
sys-kernel/linux-headers \
sys-libs/glibc
PORTAGE_CONFIGROOT=/gentoo.cfg ROOT=/gentoo SYSROOT=/gentoo emerge -D1n $pkgs_build
# Set up final system
mkdir -p /gentoo/etc/portage
ln -sf ../../var/db/repos/gentoo/profiles/default/linux/amd64/23.0 /gentoo/etc/portage/make.profile
echo 'nameserver 1.1.1.1' > /gentoo/etc/resolv.conf
echo 'C.UTF8 UTF-8' > /gentoo/etc/locale.gen
# This is the point where you have to move from the x86 system to an x86_64 system.
# Make sure that you are running a x86_64 kernel before chrooting, or booting it.
exit
umount dev/pts dev sys proc
umount var/cache/distfiles
# Optional: Back up the system
env -i chroot gentoo tar --sort=name -cf /gentoo.tar /
env -i chroot gentoo bzip2 -9v /gentoo.tar
mv gentoo/gentoo.tar.bz2 .
# Copy ::gentoo repo and distfiles
rsync -a var/db/repos/ gentoo/var/db/repos
rsync -a var/cache/distfiles/ gentoo/var/cache/distfiles
# Enter the final, x86_64 system
cd gentoo
mount -t proc proc proc
mount -t sysfs sysfs sys
mount -t devtmpfs devtmpfs dev
mount -t devpts devpts dev/pts
env -i TERM="$TERM" chroot . /bin/bash -l
umask 022
# Sandbox fails to rebuild itself at first until it's built without sandbox...
# TODO: Why, though?
FEATURES='-sandbox -usersandbox' emerge -1 sys-apps/sandbox
# Change CHOST and build OpenMP support (stage2-ish)
emerge -1 sys-devel/binutils
emerge -o sys-devel/gcc
EXTRA_ECONF=--disable-bootstrap emerge -1 sys-devel/gcc
emerge -1 dev-lang/perl # https://bugs.gentoo.org/937918
# USE flag rationale:
# https://gitweb.gentoo.org/proj/releng.git/tree/releases/portage/stages/package.use/releng/no-filecaps
# https://gitweb.gentoo.org/proj/releng.git/tree/releases/portage/stages/package.use/releng/circular
# Rebuild everything (stage3)
USE='-filecaps -http2 -http3 -quic -curl_quic_openssl' emerge -e @system
emerge -c