#!/bin/sh set -e # Example cross compile for x86_64, multilib-enabled # This can be adapted for different architectures, but do note that some # architectures will need more recent versions of gcc/glibc/tools. # The version of gcc in /bootstrap should be able to build any such newer # versions, at least as of right now (GCC 10.2). # To homogenize build instructions across both multilib and non-multilib # installs, and because some applications require heavy patches to install # in alternate libdirs (cough cough python), the lib directory will contain # native libraries, while lib32 whill contain 32-bit libraries. # GCC will be patched slightly, and configured to achieve this, as by default # it uses lib64 and lib. # To initialize/enter chroot: # mkdir dev tmp # mknod dev/null c 1 3 # ./bootstrap/bin/chroot . /bootstrap/bin/env -i NPROC="$(nproc)" /bootstrap/bin/sh /sources/build_cross.sh # Amount of make threads, configure this to your liking. # This can be obtained using `getconf _NPROCESSORS_ONLN`, but requires /proc # to be mounted, which we avoid. export MAKEFLAGS="-j${NPROC:-4}" cd /sources #### Make a cross-compiler export PATH=/cross/bin:/bootstrap/bin rm -rf /cross /system # kernel headers rm -rf linux-4.14 tar zxf linux-4.14.tar.gz ( cd linux-4.14 make mrproper make ARCH=x86_64 INSTALL_HDR_PATH="$PWD/install" headers_install find install -type f ! -name "*.h" -exec rm {} + mkdir -p /system/bootstrap/ cp -a install/include /system/bootstrap/ ) rm -rf linux-4.14 # Install cross binutils rm -rf binutils-2.20.1 tar jxf binutils-2.20.1a.tar.bz2 ( cd binutils-2.20.1 ./configure \ --build=i686-pc-linux-gnu \ --target=x86_64-pc-linux-gnu \ --prefix=/cross \ --with-sysroot=/system \ --disable-shared \ --disable-nls \ --disable-werror make make install ) rm -rf binutils-2.20.1 # Configure the gcc source rm -rf gcc-4.9.4 tar jxf gcc-4.9.4.tar.bz2 ( cd gcc-4.9.4 tar jxf ../gmp-4.3.2.tar.bz2 mv gmp-4.3.2 gmp tar jxf ../mpfr-2.4.2.tar.bz2 mv mpfr-2.4.2 mpfr tar zxf ../mpc-1.0.3.tar.gz mv mpc-1.0.3 mpc # Set up the location of target glibc cat >> gcc/config/i386/t-linux64 << 'EOF' MULTILIB_OSDIRNAMES = m64=../lib MULTILIB_OSDIRNAMES+= m32=../lib32 EOF cat >> gcc/config/i386/linux64.h << 'EOF' #undef GLIBC_DYNAMIC_LINKER32 #undef GLIBC_DYNAMIC_LINKER64 #undef STANDARD_STARTFILE_PREFIX_1 #undef STANDARD_STARTFILE_PREFIX_2 #define GLIBC_DYNAMIC_LINKER32 "/bootstrap/lib32/ld-linux.so.2" #define GLIBC_DYNAMIC_LINKER64 "/bootstrap/lib/ld-linux-x86-64.so.2" #define STANDARD_STARTFILE_PREFIX_1 "/bootstrap/lib/" #define STANDARD_STARTFILE_PREFIX_2 "" EOF mkdir build && cd build # Build breaks without a build directory ../configure \ --build=i686-pc-linux-gnu \ --target=x86_64-pc-linux-gnu \ --prefix=/cross \ --with-sysroot=/system \ --with-native-system-header-dir=/bootstrap/include \ --with-local-prefix=/bootstrap \ --with-host-libstdcxx=-lsupc++ \ --enable-multilib \ --enable-languages=c,c++ \ --disable-nls ) # Install the compiler make -C gcc-4.9.4/build all-gcc make -C gcc-4.9.4/build install-gcc # Configure the glibc source rm -rf glibc-2.16.0 tar jxf glibc-2.16.0.tar.bz2 ( cd glibc-2.16.0 # Fix hardcode of /bin/pwd sed -i -e 's@/bin/pwd@pwd@g' configure # Fix building cross-rpcgen without host rpc headers sed -i -e 's/$(ALL_BUILD_CFLAGS)/-I. &/' sunrpc/Makefile mkdir build && cd build ../configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --prefix=/bootstrap \ libc_cv_ssp=no \ libc_cv_forced_unwind=yes cd .. mkdir build32 && cd build32 ../configure \ CC='x86_64-pc-linux-gnu-gcc -m32' \ CXX='x86_64-pc-linux-gnu-g++ -m32' \ --build=i686-bootstrap-linux-gnu \ --host=i686-pc-linux-gnu \ --prefix=/bootstrap \ --libdir=/bootstrap/lib32 \ libc_cv_slibdir=/bootstrap/lib32 \ libc_cv_ssp=no \ libc_cv_forced_unwind=yes ) # Installing libgcc by using --without-headers --with-newlib in the gcc config # would avoid having to install csu+headers before building libgcc, # thereby simplifying the instructions slightly. # I don't think that simplification is particularly worth it, however. # Do the whole gcc/glibc song and dance... # DESTDIR set to a different dir since glibc makefile breaks otherwise... make -C glibc-2.16.0/build DESTDIR=/system csu/subdir_install make -C glibc-2.16.0/build32 DESTDIR=/system csu/subdir_install make -C glibc-2.16.0/build DESTDIR=/system install-bootstrap-headers=yes install-headers touch /system/bootstrap/include/gnu/stubs.h x86_64-pc-linux-gnu-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /system/bootstrap/lib/libc.so x86_64-pc-linux-gnu-gcc -m32 -nostdlib -nostartfiles -shared -x c /dev/null -o /system/bootstrap/lib32/libc.so make -C gcc-4.9.4/build all-target-libgcc make -C gcc-4.9.4/build install-target-libgcc make -C glibc-2.16.0/build all make -C glibc-2.16.0/build32 all make -C glibc-2.16.0/build32 DESTDIR="$PWD/glibc_install" install make -C glibc-2.16.0/build DESTDIR="$PWD/glibc_install" install # TODO: Would running force-install instead work? cp -a glibc_install/bootstrap /system/ rm -rf glibc_install make -C gcc-4.9.4/build all-target-libstdc++-v3 make -C gcc-4.9.4/build install-target-libstdc++-v3 rm -rf glibc-2.16.0 rm -rf gcc-4.9.4/build #### Cross-compile the compiler for the target # Binutils rm -rf binutils-2.20.1 tar jxf binutils-2.20.1a.tar.bz2 ( cd binutils-2.20.1 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --prefix=/bootstrap \ --with-lib-path=/bootstrap/lib \ --with-sysroot \ --disable-shared \ --disable-nls \ --disable-werror make make DESTDIR=/system install ) rm -rf binutils-2.20.1 # GCC (using the unpacked+patched archive from before) rm -rf gcc-4.9.4/build ( cd gcc-4.9.4 mkdir build && cd build ../configure \ CC_FOR_TARGET=x86_64-pc-linux-gnu-gcc \ CXX_FOR_TARGET=x86_64-pc-linux-gnu-g++ \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --prefix=/bootstrap \ --with-native-system-header-dir=/bootstrap/include \ --with-local-prefix=/bootstrap \ --enable-multilib \ --enable-languages=c,c++ \ --disable-nls make all-gcc all-target-libgcc all-target-libstdc++-v3 make DESTDIR=/system install-gcc install-target-libgcc install-target-libstdc++-v3 ) rm -rf gcc-4.9.4 #### Install a bunch of tools for the target rm -rf coreutils-5.0 tar jxf coreutils-5.0.tar.bz2 ( cd coreutils-5.0 # Fix conflicting type errors sed -i -e '/^char \*malloc/d' lib/putenv.c sed -i -e 's/tee /tee_files /g' src/tee.c sed -i -e 's/eaccess/_&/g' src/test.c ./configure \ --prefix=/bootstrap \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls \ ac_cv_func_malloc_0_nonnull=yes \ am_cv_func_working_getline=yes \ utils_cv_sys_open_max=1019 make -C lib make -C src make -C src DESTDIR=/system install-exec # Link chroot statically (optional if you can use the host's chroot) x86_64-pc-linux-gnu-gcc -static -O2 -o /system/bootstrap/bin/chroot src/chroot.o lib/libfetish.a ) rm -rf coreutils-5.0 rm -rf bash-4.4 tar zxf bash-4.4.tar.gz ( cd bash-4.4 # The configure script can't run a lot of tests when cross-compiling, # so a lot of the tests are specified manually to match a native build. # This fixes some otherwise-broken scripts when building Gentoo for example. # It uses the following test: [[ $(< <(echo foo) ) == foo ]] # to check for a sane bash. # Xz also has issues building with a cross-compiled bash. # I encourage you to compare the config.h with a native build! ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls \ ac_cv_func_chown_works=yes \ ac_cv_func_mmap_fixed_mapped=yes \ ac_cv_func_strcoll_works=yes \ bash_cv_func_sigsetjmp=present \ bash_cv_getcwd_malloc=yes \ bash_cv_job_control_missing=no \ bash_cv_printf_a_format=yes \ bash_cv_sys_named_pipes=yes \ bash_cv_sys_siglist=yes \ bash_cv_ulimit_maxfds=yes \ bash_cv_under_sys_siglist=yes \ bash_cv_unusable_rtsigs=no \ bash_cv_wcwidth_broken=yes \ bash_cv_wexitstatus_offset=8 make bash install -Dm755 bash /system/bootstrap/bin/bash ln -sf bash /system/bootstrap/bin/sh ) rm -rf bash-4.4 rm -rf gzip-1.2.4 tar zxf gzip-1.2.4.tar.gz ( cd gzip-1.2.4 # -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DDIRENT=1 # Such an old configure script doesn't support cross-compiling... set -x x86_64-pc-linux-gnu-gcc -DSTDC_HEADERS=1 -w -O2 -o gzip gzip.c zip.c deflate.c trees.c bits.c unzip.c inflate.c util.c crypt.c lzw.c unlzw.c unpack.c unlzh.c getopt.c CC=x86_64-pc-linux-gnu-gcc ./configure make gzip install -Dm755 gzip /system/bootstrap/bin/gzip ln -sf gzip /system/bootstrap/bin/gunzip ln -sf gzip /system/bootstrap/bin/zcat ) rm -rf gzip-1.2.4 rm -rf bzip2-1.0.8 tar zxf bzip2-1.0.8.tar.gz ( cd bzip2-1.0.8 make \ CC=x86_64-pc-linux-gnu-gcc \ AR=x86_64-pc-linux-gnu-ar \ bzip2 install -Dm755 bzip2 /system/bootstrap/bin/bzip2 ln -sf bzip2 /system/bootstrap/bin/bunzip2 ln -sf bzip2 /system/bootstrap/bin/bzcat ) rm -rf bzip2-1.0.8 rm -rf tar-1.22 tar jxf tar-1.22.tar.bz2 ( cd tar-1.22 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls make -C lib make -C src install -Dm755 src/tar /system/bootstrap/bin/tar ) rm -rf tar-1.22 rm -rf grep-2.0 tar zxf grep-2.0.tar.gz ( cd grep-2.0 # -DGREP -DSTDC_HEADERS=1 -DHAVE_STRING_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ALLOCA_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MEMCHR=1 -DHAVE_STRERROR=1 -DHAVE_VALLOC=1 -DHAVE_WORKING_MMAP=1 # Such an old configure script doesn't support cross-compiling... set -x x86_64-pc-linux-gnu-gcc -DSTDC_HEADERS=1 -DHAVE_MEMCHR=1 -DHAVE_STRERROR=1 -w -O2 -o grep grep.c getopt.c regex.c dfa.c kwset.c obstack.c search.c install -Dm755 grep /system/bootstrap/bin/grep ln -sf grep /system/bootstrap/bin/egrep ln -sf grep /system/bootstrap/bin/fgrep ) rm -rf grep-2.0 # Optional, rationale for inclusion same as in build_bootstrap.sh rm -rf findutils-4.6.0 tar zxf findutils-4.6.0.tar.gz ( cd findutils-4.6.0 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls make -C gl make -C lib make -C find make -C xargs install -Dm755 find/find /system/bootstrap/bin/find install -Dm755 xargs/xargs /system/bootstrap/bin/xargs ) rm -rf findutils-4.6.0 rm -rf diffutils-2.7 tar zxf diffutils-2.7.tar.gz ( cd diffutils-2.7 CC=x86_64-pc-linux-gnu-gcc \ ac_cv_func_closedir_void=no \ ac_cv_header_stdc=yes \ ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu make cmp diff install -Dm755 cmp /system/bootstrap/bin/cmp install -Dm755 diff /system/bootstrap/bin/diff ) rm -rf diffutils-2.7 rm -rf sed-4.0.6 tar zxf sed-4.0.6.tar.gz ( cd sed-4.0.6 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls \ am_cv_func_working_getline=yes make -C lib make -C sed install -Dm755 sed/sed /system/bootstrap/bin/sed ) rm -rf sed-4.0.6 rm -rf patch-2.5.9 tar zxf patch-2.5.9.tar.gz ( cd patch-2.5.9 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu make patch install -Dm755 patch /system/bootstrap/bin/patch ) rm -rf patch-2.5.9 rm -rf gawk-3.1.8 tar jxf gawk-3.1.8.tar.bz2 ( cd gawk-3.1.8 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls make gawk install -Dm755 gawk /system/bootstrap/bin/gawk ln -sf gawk /system/bootstrap/bin/awk ) rm -rf gawk-3.1.8 rm -rf make-3.82 tar jxf make-3.82.tar.bz2 ( cd make-3.82 ./configure \ --build=i686-pc-linux-gnu \ --host=x86_64-pc-linux-gnu \ --disable-nls make make install -Dm755 make /system/bootstrap/bin/make ) rm -rf make-3.82 # Add /bin/sh symlink mkdir -p /system/bin ln -sf ../bootstrap/bin/bash /system/bin/bash ln -sf bash /system/bin/sh # Strip everything (saves hundreds of MB) find /system/bootstrap/lib /system/bootstrap/lib32 -type f -name '*.a' | xargs x86_64-pc-linux-gnu-strip --strip-debug || true find /system/bootstrap/lib /system/bootstrap/lib32 -type f -name '*.so*' | xargs x86_64-pc-linux-gnu-strip --strip-unneeded || true find /system/bootstrap/bin /system/bootstrap/sbin /system/bootstrap/libexec -type f | xargs x86_64-pc-linux-gnu-strip --strip-all || true # Clean up #rm -rf /cross rm -rf /system/bootstrap/share /system/bootstrap/var /system/bootstrap/etc rm -f /system/bootstrap/lib/*.la /system/bootstrap/lib32/*.la /system/bootstrap/lib/libstdc++.so.*-gdb.py /system/bootstrap/lib32/libstdc++.so.*-gdb.py # Back it up cd /system # Too many files to fit on single xargs command... rm -f cross.tar find bootstrap bin/sh bin/bash -type f -o -type l | LC_ALL=C sort | xargs tar --mtime=@0 --numeric-owner --owner=0 --group=0 -rf cross.tar gzip -nv cross.tar # Now you should reboot into a system with a kernel supporting the target architecture. # Building a kernel+utilities for such a system is outside the scope of this script. # Enter cross-chroot: # ./bootstrap/bin/chroot . /bootstrap/bin/env -i PATH=/bootstrap/bin /bootstrap/bin/sh -l