# Changelog: # - 2025.8: # - Set up a proper gentoo install using prefix, by building a bunch of tools # in a temporary prefix, and then cross-compiling a final prefix. # - Use crossdev to build the final system. # - Both of these changes make the instructions significantly more # future-proof, although there's still a lot of bugs to fix upstream, and # ways to lessen the amount of compilation needed. # - 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: Install a temporary copy of portage to /tmp/portage # step 2: Setup a prefix-guest using the live-bootstrap toolchain, build a few additional tools # step 3: Set up a target prefix, build glibc, and a cross compiler targetting it # step 4: Build portage and necessary utilities for the target prefix # step 5: Switch to it and emerge the rest of @world # step 6: Install crossdev and build the final system
# Optional: Back up the system rm -r target/dev/* # allow extracting as non-root 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 cd /tmp
# Optional: Configure additional mirrors for missing/removed distfiles # This is a space-separated list of URLs, but full paths to local directories # can be added as well. export GENTOO_MIRRORS="/mirror http://distfiles.gentoo.org"
mkdir -p /var/cache/distfiles; cd /var/cache/distfiles curl -LO http://gitweb.gentoo.org/proj/portage.git/snapshot/portage-3.0.68.tar.bz2 curl -LO http://distfiles.gentoo.org/snapshots/squashfs/gentoo-20250801.xz.sqfs curl -LO https://github.com/plougher/squashfs-tools/archive/refs/tags/4.7.2/squashfs-tools-4.7.2.tar.gz cd /tmp # TODO: gentoo currently uses squashfs-tools-4.7, but that fails to build, upgraded to 4.7.2
# Build squashfs-tools to extract the ::gentoo tree # TODO: Include in live-bootstrap proper tar xf /var/cache/distfiles/squashfs-tools-4.7.2.tar.gz cd squashfs-tools-4.7.2 make -C squashfs-tools install \ INSTALL_PREFIX=/usr \ LZO_SUPPORT=0 LZ4_SUPPORT=0 ZSTD_SUPPORT=0 cd .. rm -rf squashfs-tools-4.7.2
# Make some additional root modifications cp /usr/include/asm-generic/mman.h /usr/include/asm # needed by dev-libs/openssl
# Unpack the ::gentoo tree unsquashfs /var/cache/distfiles/gentoo-20250801.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.68.tar.bz2 ln -sfT portage-3.0.68 portage
# Build tools missing from/broken in live-bootstrap # TODO: Include in live-bootstrap proper PORTAGE_OVERRIDE_EPREFIX=/cross MAKEOPTS=-j1 ./portage/bin/emerge -D1n dev-build/make # make in live-bootstrap has trouble with parallel builds under portage PORTAGE_OVERRIDE_EPREFIX=/cross ./portage/bin/emerge -D1n net-misc/rsync # https://bugs.gentoo.org/963902
CHOST=i686-cross-linux-gnu ACCEPT_KEYWORDS="-~$ARCH" USE=-nls INSTALL_MASK=/etc/env.d/99host EOF mkdir -p /gentoo/etc/portage/profile cat > /gentoo/etc/portage/profile/package.use << 'EOF' sys-devel/gcc -sanitize -fortran app-arch/gzip pic EOF cat > /gentoo/etc/portage/profile/package.accept_keywords << 'EOF' ~net-misc/curl-8.15.0 # Fix bug that prevents --ftp-pasv from working EOF cat > /gentoo/etc/portage/bashrc << 'EOF' if [ "$CBUILD" = i686-unknown-linux-musl ]; then export BUILD_CFLAGS="-I$BROOT/usr/include" export BUILD_LDFLAGS="-L$BROOT/usr/lib -Wl,--disable-new-dtags,-rpath,$BROOT/usr/lib" export PKG_CONFIG_LIBDIR="$EROOT/usr/lib/pkgconfig:$EROOT/usr/share/pkgconfig" export PKG_CONFIG_SYSTEM_INCLUDE_PATH="$EROOT/usr/include" export PKG_CONFIG_SYSTEM_LIBRARY_PATH="$EROOT/lib:$EROOT/usr/lib" export CONFIG_SITE="$EROOT/etc/portage/config.site" fi EOF cat > /gentoo/etc/portage/config.site << 'EOF' ac_cv_file__dev_ptmx=yes# dev-lang/python ac_cv_file__dev_ptc=no # dev-lang/python gl_cv_func_strcasecmp_works=yes# sys-apps/diffutils EOF mkdir -p /gentoo/etc/portage/env/dev-lang cat > /gentoo/etc/portage/env/dev-lang/python << '_EOF' if [ "$CBUILD" = i686-unknown-linux-musl ]; then pre_src_prepare() { sed -i 's/\[MULTIARCH=\$(.*\]/[MULTIARCH=]/' configure.ac || die } fi _EOF
# Initialize prefix PORTAGE_OVERRIDE_EPREFIX=/gentoo USE=build ./portage/bin/emerge -D1n sys-apps/baselayout echo'man:x:13:15:System user; man:/dev/null:/sbin/nologin' >> /gentoo/etc/passwd echo'man:x:15:' >> /gentoo/etc/group # TODO: The acct-user and acct-group should create the groups honestly
# Build libc and adapt compiler for target prefix # Usually, CC and CXX should be the CHOST compilers, to cross compile. However, they're compatible enough here. # Using --nodeps because the live-bootstrap environment is guaranteed to provide enough to build glibc PORTAGE_OVERRIDE_EPREFIX=/cross PORTAGE_CONFIGROOT=/gentoo EPREFIX=/gentoo CBUILD=i686-unknown-linux-musl CC=i686-unknown-linux-musl-gcc CXX=i686-unknown-linux-musl-g++ BOOTSTRAP_RAP=y ./portage/bin/emerge -O1n sys-kernel/linux-headers PORTAGE_OVERRIDE_EPREFIX=/cross PORTAGE_CONFIGROOT=/gentoo EPREFIX=/gentoo CBUILD=i686-unknown-linux-musl CC=i686-unknown-linux-musl-gcc CXX=i686-unknown-linux-musl-g++ BOOTSTRAP_RAP=y ./portage/bin/emerge -O1n sys-libs/glibc PORTAGE_OVERRIDE_EPREFIX=/cross ./portage/bin/emerge -D1n cross-i686-cross-linux-gnu/glibc # Dummy package to use proper flags in gcc PORTAGE_OVERRIDE_EPREFIX=/cross ./portage/bin/emerge -D1n cross-i686-cross-linux-gnu/binutils # TODO: cross-gcc doesn't depend on the right binutils PORTAGE_OVERRIDE_EPREFIX=/cross ./portage/bin/emerge -D1n cross-i686-cross-linux-gnu/gcc
# Set up final system mkdir -p /target/etc/portage ln -sfT ../../var/db/repos/gentoo/profiles/default/linux/amd64/23.0 /target/etc/portage/make.profile echo'nameserver 1.1.1.1' > /target/etc/resolv.conf echo'C.UTF8 UTF-8' > /target/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 target tar --sort=name -cf /target-gentoo.tar / env -i chroot target bzip2 -9v /target-gentoo.tar mv target/target-gentoo.tar.bz2 ..
# Copy ::gentoo repo and distfiles mkdir -p target/var/db/repos rsync -a var/db/repos/gentoo/ target/var/db/repos/gentoo rsync -a var/cache/distfiles/ target/var/cache/distfiles
# Enter the final, x86_64 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
# Initialize system and break dependency cycles ldconfig USE='-nls' emerge -1n sys-devel/gettext