#!/bin/bash ulimit -s unlimited shopt -s extglob ########################################################################################### # Build cross binutils for use with 'distcc' for ARM targets # by Stuart Winter ########################################################################################### # Some parts are taken from Slackware package build scripts directly. # # References: # http://www.cygwin.com/ml/crossgcc/2006-12/msg00075.html # http://www.linuxfromscratch.org/lfs/view/development/chapter05/glibc.html # http://www.linuxfromscratch.org/lfs/view/development/chapter05/gcc-pass1.html # # The purpose of this is to build enough of a toolchain that I can use # distcc to a fast x86 host from my native ARM build hosts. # This script does not build an entire cross toolchain and the result # in /opt/arm is pretty messy (although could easily be tidied). # # Additional scripts included: # # rc.local-addition: a method of starting distccd on the x86 host machines. # dbuild: used on the ARM hosts as a wrapper for calling the Slackware ARM # build scripts via distcc. Instructions for usage are contained within the script. # # For the original work I did, check out this: # ftp://ftp.arm.slackware.com/loft/oldsource/OLD_CROSS_COMPILE/ARM-compiling-bits-bobs # # If this was to be extended to a full cross compiler, this would be useful: ## http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Environment-Variables.html#Environment-Variables #TD=/devel/build-servers/x86_64/arm/ #export GCC_EXEC_PREFIX=$TD #export COMPILER_PATH=$TD/bin:$TD/libexec/gcc/arm-slackware-linux-gnueabi/4.5.1/ #export C_INCLUDE_PATH=$TD/include/:$TD/lib/gcc/arm-slackware-linux-gnueabi/4.5.1/include/ #export CPLUS_INCLUDE_PATH=$TD/include/:$TD/lib/gcc/arm-slackware-linux-gnueabi/4.5.1/include/ #export OBJC_INCLUDE_PATH=$TD/include/:$TD/lib/gcc/arm-slackware-linux-gnueabi/4.5.1/include/ ########################################################################################### # Notes# ######## # 1. This script is supposed to be run: # [ ] on an x86 running Slackware # [ ] from inside armedslack-current/source/x-toolchain ########################################################################################### # Recent changelog ########################################################################################### # 25-Dec-2012 # * Disabled 'gold' linker for binutils-2.23.51.0.6 because it FTBFS with a powerpc target # Gcc: Removed langs 'ada,fortran,java,objc,lto' as we'll never use x-compile any of them ########################################################################################### # Automatically determine architecture for build & packaging: case "$( uname -m )" in # The i686 here just means "x86". i?86) export LOCALARCH=i686 export LIBDIR=lib export SLKCFLAGS="-O2" ;; x86_64) export LOCALARCH=$( uname -m ) export LIBDIR=lib64 export SLKCFLAGS="-O2 -fPIC" ;; esac #NUMJOBS="-j$(awk '/^processor[[:space:]]*:/{n=$3} END{print n+1}' /proc/cpuinfo)" #NUMJOBS="-j1" NUMJOBS="-j$( nproc )" # Versions of packages: #BINUTILSVER=2.43 BINUTILSVER=2.43.1 #GLIBCVER=2.39 GLIBCVER=2.40 GCCVER=14.2.0 ################## Functions ############################################## # Functions: # # Determine patch level required & apply the patch: function auto_apply_patch () { patchfile=$1 echo echo "***********************************************************" echo "** Working on Patch: $patchfile" echo "***********************************************************" echo # Decompress the patch if it's compressed with a known method: FTYPE=$( file $patchfile ) case "$FTYPE" in *xz*compressed*) xz -dc $patchfile > $TMP/$(basename $patchfile).unpacked patchfile=$TMP/$(basename $patchfile).unpacked ;; *bzip2*compressed*) bzcat -f $patchfile > $TMP/$(basename $patchfile).unpacked patchfile=$TMP/$(basename $patchfile).unpacked ;; *gzip*compressed*) zcat -f $patchfile > $TMP/$(basename $patchfile).unpacked patchfile=$TMP/$(basename $patchfile).unpacked ;; esac # By now the patch is decompressed or wasn't compressed originally. # # Most patches should not require more levels than this: success=0 for (( pl=0 ; pl<=5 ; pl++ )) ; do #****************************************************************************************** echo "Patch : $patchfile , trying patch level $pl" patch -N --fuzz=20 -t --dry-run -p$pl < $patchfile > /dev/null 2>&1 && success=1 && break done if [ $success = 1 ]; then echo "Patch: $patchfile will apply at level $pl" patch -N --fuzz=20 --verbose -p$pl < $patchfile return 0 else echo "Patch: $patchfile failed to apply at levels 0-5" return 1 fi } function build_kernel_headers () { # Kernel architecture name. We keep these as armv7 (ARM 32bit), armv8 (AArch64/ARM 64bit) case ${TARGET%%-*} in arm) SLKKERNELARCH=armv7 LINUXKERNELARCH=arm;; aarch64) SLKKERNELARCH=armv8 LINUXKERNELARCH=arm64;; esac cat << "EOF" ########################################################################### ################## Extract ARM Linux Kernel headers ####################### ########################################################################### EOF echo "Unpacking Linux source" cd $TMP # Cheat and use the ones built when we built the kernel package on a # real ARM box: # tar xf $CWD/sources/kernel/kernel-headers*tar.xz -C $INSTLOC || exit 1 tar xf $CWD/sources/kernel/linux-*.tar.xz cd linux* || exit 1 make mrproper cp -f $CWD/sources/kernel/config-$SLKKERNELARCH .config #make ARCH=$LINUXKERNELARCH headers_check || exit 1 make ARCH=$LINUXKERNELARCH INSTALL_HDR_PATH=$INSTLOC headers_install || exit 1 # We don't want this header - we use glibc's: rm -fv $INSTLOC/include/scsi/scsi.h # Nor this - this conflicts with libdrm. Not that it makes any difference # to us for the cross compiler, but I like to keep things in order: rm -rf $INSTLOC/include/drm } function build_binutils () { cat << "EOF" ########################################################################### ################## Build binutils ######################################### ########################################################################### EOF # Extract source: cd $TMP echo "Unpacking binutils source..." tar xf $CWD/sources/binutils/binutils*.tar.?z cd binutils*/ || exit 1 # Various upstream patches: # ***************************************************************************************** # ***** Remember: we prefix the patch file name with $CWD/sources/binutils/patches/ ******* # ***************************************************************************************** # # These were shipped empty and will need to be regenerated: rm -f binutils/doc/*.1 binutils/doc/*.man gprof/gprof.1 ld/ld.1 gas/doc/as.1 # Export the demangle.h header file (I suspect this is obsolete...): zcat $CWD/sources/binutils/patches/binutils-export-demangle.h.patch.gz | patch -p1 --verbose || exit 1 # Don't check to see if "config.h" was included in the installed headers: zcat $CWD/sources/binutils/patches/binutils-no-config-h-check.patch.gz | patch -p1 --verbose || exit 1 # Set %version to something halfway meaningful: zcat $CWD/sources/binutils/patches/binutils-version.patch.gz | patch -p1 --verbose || exit 1 sed -i -e 's/%''{release}/slack15/g' bfd/Makefile{.am,.in} # Work around a bug caused by binutils using an ancient libtool: zcat $CWD/sources/binutils/patches/binutils-libtool-lib64.patch.gz | patch -p1 --verbose || exit 1 # Various regression fixes: #zcat $CWD/sources/binutils/patches/ zcat $CWD/sources/binutils/patches/binutils-2.27-aarch64-ifunc.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-do-not-link-with-static-libstdc++.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-filename-in-error-messages.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-gold-i386-gnu-property-notes.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-gold-mismatched-section-flags.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-gold-warn-unsupported.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-readelf-other-sym-info.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-special-sections-in-groups.patch.gz | patch -p1 --verbose || exit 1 zcat $CWD/sources/binutils/patches/binutils-testsuite-fixes.patch.gz | patch -p1 --verbose || exit 1 # Thanks to Fedora: # Dependencies are not set up to rebuild the configure files # in the subdirectories. So we just rebuild the ones we care # about after applying the configure patches #pushd libiberty #autoconf #popd #pushd intl #autoconf #popd # Slackware ARM patches: # None presently # #for pf in \ # \ # binutils-2.22.52.0.1-relro-on-by-default.patch \ # binutils-2.26-fix-compile-warnings.patch \ # binutils-2.29-skip-rp14918-test-for-arm.patch \ # binutils-2.29-filename-in-error-messages.patch \ # binutils-2.28-ignore-gold-duplicates.patch \ # \ # ; do # auto_apply_patch $CWD/sources/binutils/${pf}.xz || exit 1 # done # This one needs to be applied in order for the patches lower down in the set to apply under dry-run conditions # so we just apply this manually: #xzcat $CWD/sources/binutils/binutils-2.26-lto.patch.xz | patch -p1 --verbose || exit 1 # The --enable-initfini-array option was added in binutils-2.21.51.0.3. # This option currently causes a world of hurt trying to compile glibc, # and might break static libraries or cause other ill effects. There # is an upstream patch for glibc but it does not avoid all of the known # problems (and there may be some unknown ones, too), so we will avoid # introducing this feature for now. # References: # http://sourceware.org/bugzilla/show_bug.cgi?id=12343 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46770 NO_INITFINI=" --disable-initfini-array " # Uncomment this to include the experimental gold linker: #GOLD=" --enable-gold=yes --enable-ld=default " GOLD=" --enable-gold=no --enable-ld=default " # Set to ld.gold or ld.bfd: DEFAULT_LD=ld.bfd # Added --enable-plugins --enable-threads for binutils-2.20.51.0.11 # --enable-64-bit-bfd \ # as suggested here: http://patchwork.openembedded.org/patch/2178/ # --enable-lto \ # Configure: ./configure $GOLD $NO_INITFINI \ --enable-werror=no \ --prefix=$INSTLOC \ --with-sysroot=$INSTLOC \ --enable-shared \ --disable-libssp \ --enable-gnu-unique-object \ --disable-werror \ --disable-nls \ --enable-plugin \ --enable-plugins \ --enable-threads \ --enable-threads=posix \ --disable-compressed-debug-sections \ --enable-deterministic-archives \ --enable-install-libiberty \ \ --enable-relro=yes \ --enable-lto \ \ --host=$LOCALARCH-slackware-linux \ --build=$LOCALARCH-slackware-linux \ --target=$TARGET || exit 1 # Build: make $NUMJOBS || make || exit 1 # Install into /opt: make install || exit 1 } function build_glibc () { cat << "EOF" ########################################################################### ################## Build glibc headers #################################### ########################################################################### EOF cd $TMP echo "Unpacking glibc source..." tar xf $CWD/sources/glibc/glibc-$GLIBCVER.tar.xz cd glibc*/ || exit 1 # Add ports: # This is bundled with glibc in 2.17. #tar xf $CWD/sources/glibc/glibc-ports-*.tar.* || exit 1 #rm -rf ports #mv glibc-ports* ports || exit 1 # Unpack & apply patches: set -x # Apply Slackware-specific patches -- taken from glibc.SlackBuild: #****************************************************************************** # When pasting from ARMedslack's glibc.SlackBuild, remember to search+replace # $CWD/ with $CWD/sources/glibc/ # and $PORTCWD with $CWD #****************************************************************************** # # Use old-style locale directories rather than a single (and strangely # formatted) /usr/lib/locale/locale-archive file: zcat $CWD/sources/glibc/glibc.locale.no-archive.diff.gz | patch -p1 --verbose || exit 1 # Support ru_RU.CP1251 locale: zcat $CWD/sources/glibc/glibc.ru_RU.CP1251.diff.gz | patch -p1 --verbose || exit 1 # Add a C.UTF-8 locale: zcat $CWD/sources/glibc/glibc-c-utf8-locale.patch.gz | patch -p1 --verbose || exit 1 # Don't use AM/PM format for date(1). That's just plain crazy. zcat $CWD/sources/glibc/glibc-2.32.en_US.no.am.pm.date.format.diff.gz | patch -p1 --verbose || exit 1 # Other regression fixes from git: for git_patch in $CWD/sources/glibc/patches/*.patch.gz ; do zcat $git_patch | patch -p1 --verbose || exit 1 done # We don't apply them to the cross compiler since long ago with the 14.2 soft float release. # They also were not applied during the bootstrapping of the hard float port either. # Apply Debian/Ubuntu's ARM patches: # # tar xvvf $CWD/sources/glibc/glibc_*debian*xz || exit 1 # # # Apply: # for pf in \ # \ # arm/local-arm-futex.diff \ # \ # ; do # auto_apply_patch debian/patches/$pf || exit 1 # done # Configure: mkdir build.dir cd build.dir CFLAGS="-g $SLKCFLAGS -DBOOTSTRAP_GCC" \ ../configure libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes libc_cv_gnu89_inline=yes \ --prefix=$INSTLOC \ --without-cvs \ --disable-sanity-checks \ --disable-profile \ --disable-werror \ --disable-debug \ --without-selinux \ --with-tls \ --enable-kernel=3.2 \ --with-headers=$INSTLOC/include/ \ --enable-hacker-mode \ --host=$LOCALARCH-slackware-linux \ --build=$LOCALARCH-slackware-linux \ --target=$TARGET || exit 1 make cross-compiling=yes install_root=$INSTLOC prefix="" CFLAGS="-g $SLKCFLAGS -DBOOTSTRAP_GCC" install-headers || exit 1 #make -j$(nproc) csu/subdir_lib || exit 1 #install csu/crt1.o csu/crti.o csu/crtn.o $INSTLOC/lib/ #mkdir -p $INSTLOC/include/gnu #touch $INSTLOC/include/gnu/stubs.h #gcc-x86slka -nostdlib -nostartfiles -shared -x c /dev/null -o $INSTLOC/lib/libc.so #make $NUMJOBS sysdeps/gnu/errlist.c || make sysdeps/gnu/errlist.c || exit 1 #mkdir -p stdio-common #touch stdio-common/errlist-compat.c ##make $NUMJOBS cross-compiling=yes install_root=$INSTLOC prefix="" CFLAGS="-g $SLKCFLAGS -DBOOTSTRAP_GCC" install-headers || exit 1 #make cross-compiling=yes install_root=$INSTLOC prefix="" CFLAGS="-g $SLKCFLAGS -DBOOTSTRAP_GCC" install-headers || exit 1 ##cp -vfa bits/stdio_lim.h $INSTLOC/bits/stdio_TARGET_PREFIX #cp -vfa bits/stdio_lim.h $INSTLOC/include/bits/ } function build_gcc () { cat << "EOF" ########################################################################### ################## Build gcc ############################################## ########################################################################### EOF # Extract source: cd $TMP echo "Unpacking gcc source..." tar xf $CWD/sources/gcc/gcc-[0-9]*.tar.!(*sign|*asc|*sig) || exit 1 # Add this symlink to ease application of the patches from debian: mv -fv gcc-* src ln -vfs src gcc-$GCCVER cd src/ || exit 1 ########### Apply patches ################################################# # Apply Debian patches: #tar xvvf $CWD/sources/gcc/patches-*gcc*.xz || exit 1 # Debian switched back to a diff file for gcc 4.9 and changed the dir structure: #( cd $TMP # mkdir gcc-dpatches ; cd gcc-dpatches # [ -f $CWD/sources/gcc/gcc-[0-9]*_*[0-9]*-*diff*z ] && auto_apply_patch $CWD/sources/gcc/gcc-[0-9]*_*[0-9]*-*diff*z || exit 1 # mv */debian ../src/ ) # Go back into the parent directory: needed because Debian's patch set # includes the 'src' parent dir and 'patch' won't let us patch through # symlinks: #cd .. # This list is taken from the Debian Build log for the particular # patch release we're using, with a few redundant ones stripped. #for patchf in \ # \ # svn-updates.diff \ #[..] # \ # ; do auto_apply_patch src/debian/patches/$patchf || exit 1 # done # # Apply Slackware patches: # SLKGCCPATCHPATH=$CWD/sources/gcc/patches # # Apply any required patches: for patch in $SLKGCCPATCHPATH/*.patch $SLKGCCPATCHPATH/*.diff ; do if [ -r "$patch" ]; then cat $patch | patch -p1 --verbose --backup --suffix=.orig || exit 1 fi done for patch in $SLKGCCPATCHPATH/*.patch.gz $SLKGCCPATCHPATH/*.diff.gz ; do if [ -r "$patch" ]; then zcat $patch | patch -p1 --verbose --backup --suffix=.orig || exit 1 fi done # Exit is for when testing if patches apply: Normally should be commented. #exit # ARM patches: ######################################################################################################## # Back into the gcc source directory: cd $TMP/src mkdir gcc.build cd gcc.build # -fstack-protector on gcc 4.2.3 causes segfaults on ARM # so it's best to disable it since many newer packages check for # this option and enable if supported. #STACKPROT="--disable-libssp --disable-sjlj-exceptions" # It works in 4.4.2: STACKPROT="--enable-libssp" # --enable-libffi # --enable-threads=no \ # Architecture configuration options: case ${TARGET%%-*} in arm) SLKCONFARGS_GCC=" --with-arch=armv7-a \ --with-float=hard \ --with-tune=generic-armv7-a \ --with-fpu=vfpv3-d16" ;; aarch64) SLKCONFARGS_GCC="--with-arch=armv8-a" ;; esac echo "GCC configuration options for $TARGET: $SLKCONFARGS_GCC" # Configure - Note that for ARM we add --with-arch=armv7-a --with-float=hard --with-fpu=vfpv3-d16 --with-tune=generic-armv7-a # otherwise you get errors during package building such as: # /usr/lib/gcc/arm-slackware-linux-gnueabi/5.4.0/../../../../arm-slackware-linux-gnueabi/bin/ld: failed to merge target specific data of file libnetutil/libnetutil.a(FragmentHeader.o) # ../configure $STACKPROT \ --verbose \ \ --prefix=$INSTLOC \ --with-local-prefix=$INSTLOC \ \ --enable-threads=posix \ --enable-symvers=gnu \ --enable-lto \ --enable-install-libiberty \ --enable-__cxa_atexit \ --enable-languages=c,c++ \ --enable-shared \ --enable-gnu-unique-object \ --enable-libstdcxx-dual-abi \ --enable-clocale=gnu \ \ --disable-multilib \ --disable-shared \ --disable-nls \ --disable-libstdcxx-pch \ --disable-checking \ --disable-werror \ --disable-libssp \ --disable-libunwind-exceptions \ \ --without-headers \ \ --with-newlib \ --with-isl \ --with-system-zlib \ --with-gnu-ld \ --with-default-libstdcxx-abi=new \ \ $SLKCONFARGS_GCC \ \ --host=$LOCALARCH-slackware-linux \ --build=$LOCALARCH-slackware-linux \ --target=$TARGET || exit 1 # Build: make $NUMJOBS all-gcc || make all-gcc || exit 1 make install-gcc || exit 1 } function finishup() { # Strip binaries: cd $INSTLOC ( find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null ) # Make symlinks: cd $INSTLOC/bin for i in * ; do ln -vfs $i $( echo $i | sed s'?'"$TARGET"-'??' ) done ln -vfs gcc cc ln -vfs $TARGET-{gcc,cc} } ####################################################################### CWD=$PWD # Build toolchain for the supported Slackware platforms: # March 2022: 32bit ARM is retired but we still need a 32bit x-toolchain # to build the ATF, so we'll keep it around until it fails to build then # will store a copy of the old stuff to enable ATF building. for platform in \ arm-slackware-linux-gnueabihf \ aarch64-slackware-linux-gnu ; do # Compiler target: TARGET=$platform echo "Host & build architecture: $LOCALARCH" echo "Target architecture......: $platform" # Installation location #INSTLOC=/opt/devel/build-servers/x86_64/$LOCALARCH # # Here we have i486 & x86_64 so we have arch specific toolchains for these two: INSTLOC=/devel/build-servers/$LOCALARCH/${platform%%-*} rm -rf $INSTLOC mkdir -vpm755 $INSTLOC # Temp build locations: #TMP=/dev/shm/xbuild TMP=/tmp/xbuild rm -rf $TMP mkdir -p $TMP # Create some framework: # needs a lib64 here. Well, it doesn't really. Let's try without first. mkdir -p $INSTLOC/lib mkdir -p $INSTLOC/usr/lib mkdir -p $INSTLOC/include # Use gcc first to test whether the patches apply. Normally this will be # commented out. #build_gcc || exit 1 #exit # Build: build_kernel_headers || exit 1 build_binutils || exit 1 # Our binutils stuff is in here now: export PATH=$PATH:$INSTLOC/bin/:$INSTLOC/$platform/bin/ build_glibc || exit 1 build_gcc || exit 1 finishup done # Clean up: if [ ! -z "$1" ]; then echo "** Leaving temporary build directory '$TMP' in place" else echo "** Removing temporary build directory '$TMP'" rm -rf $TMP fi