#!/bin/bash # $Id$ # Copyright 2024 Eric Hameleers, Eindhoven, NL # All rights reserved. # # Permission to use, copy, modify, and distribute this software for # any purpose with or without fee is hereby granted, provided that # the above copyright notice and this permission notice appear in all # copies. # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # ----------------------------------------------------------------------------- # # Build the llvm/rust toolchain from Google's customized sources # # By: Eric Hameleers # For: chromium # Needs: # Changelog: # 123-1 21/mar/2024 by Eric Hameleers # * First version, targeting Chromium 123. # # ----------------------------------------------------------------------------- SRCNAM="chromium" PRGNAM="${SRCNAM}-compiler-toolchain" SRCVER=${SRCVER:-124.0.6367.60} VERSION=$(echo $SRCVER |cut -d. -f1) BUILD=${BUILD:-1} TAG=${TAG:-alien} # Cross-compiling 32bit binaries on 64bit Slackware; set to "YES": CROSS32=${CROSS32:-"NO"} # Debug build (disabled by default): USE_DEBUG=${USE_DEBUG:-0} # Where do we look for sources? SRCDIR=$(cd $(dirname $0); pwd) # Place to build (TMP) package (PKG) and output (OUTPUT) the program: TMP=${TMP:-/tmp/build} PKG=$TMP/package-$PRGNAM OUTPUT=${OUTPUT:-/tmp} # Visible directory listing of anything Chrome related is: # http://gsdview.appspot.com/ # Official location (non-browsable) of the above is: # https://commondatastorage.googleapis.com/ ## ## --- with a little luck, you won't have to edit below this point --- ## ## # Automatically determine the architecture we're building on: MARCH=$( uname -m ) if [ -z "$ARCH" ]; then case "$MARCH" in i?86) export ARCH=i586 ;; armv7*) export ARCH=$MARCH ;; arm*) export ARCH=arm ;; # Unless $ARCH is already set, use uname -m for all other archs: *) export ARCH=$MARCH ;; esac fi case "$ARCH" in i?86) SLKCFLAGS="-O2 -march=${ARCH} -mtune=i686" LIBDIRSUFFIX="" SYSROOT_ARCH="i386" SYSROOT_TARGET="i386-linux-gnu" PKGARCH="$ARCH" ;; x86_64) # Ensure that 32bit libraries are found first if we cross-compile: if [ "${CROSS32}" = "YES" ]; then SLKCFLAGS="-O2" LIBDIRSUFFIX="" SLKLDFLAGS="-L/usr/lib" SYSROOT_ARCH="i386" SYSROOT_TARGET="i386-linux-gnu" PKGARCH="i586" else SLKCFLAGS="-O2 -fPIC" LIBDIRSUFFIX="64" SYSROOT_ARCH="amd64" SYSROOT_TARGET="x86_64-linux-gnu" PKGARCH="$ARCH" fi ;; armv7*) SLKCFLAGS="-O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard" SLKLDFLAGS="-Wl,-z,notext" LIBDIRSUFFIX="" SYSROOT_ARCH="arm" SYSROOT_TARGET="arm-linux-gnueabihf" PKGARCH="$ARCH" ;; *) SLKCFLAGS=${SLKCFLAGS:-"O2"} SLKLDFLAGS=${SLKLDFLAGS:-""} LIBDIRSUFFIX=${LIBDIRSUFFIX:-""} SYSROOT_ARCH="$ARCH" SYSROOT_TARGET="$ARCH-linux-gnu" PKGARCH="$ARCH" ;; esac case "$ARCH" in armv7*) TARGET=$ARCH-slackware-linux-gnueabi ;; arm*) TARGET=${SYSROOT_ARCH}-slackware-linux-gnueabihf ;; *) TARGET=$ARCH-slackware-linux ;; esac # Exit the script on errors: set -e trap 'echo "$0 FAILED at line ${LINENO}" | tee $OUTPUT/error-${PRGNAM}.log' ERR # Catch unitialized variables: set -u P1=${1:-1} # Save old umask and set to 0022: _UMASK_=$(umask) umask 0022 # Source locations: SOURCE[0]="$SRCDIR/${SRCNAM}-${SRCVER}.tar.xz" SRCURL[0]="https://commondatastorage.googleapis.com/${SRCNAM}-browser-official/${SRCNAM}-${SRCVER}.tar.xz" # Create working directories: mkdir -p $OUTPUT # place for the package to be saved mkdir -p $TMP/tmp-$PRGNAM # location to build the source mkdir -p $PKG # place for the package to be built rm -rf $PKG/* # always erase old package's contents rm -rf $TMP/tmp-$PRGNAM/* # remove the remnants of previous build rm -rf $OUTPUT/{configure,make,install,error,makepkg,patch}-$PRGNAM.log # remove old log files # Source file availability: for (( i = 0; i < ${#SOURCE[*]}; i++ )) ; do if ! [ -f ${SOURCE[$i]} ]; then echo "Source '$(basename ${SOURCE[$i]})' not available yet..." # Check if the $SRCDIR is writable at all - if not, download to $OUTPUT [ -w "$SRCDIR" ] || SOURCE[$i]="$OUTPUT/$(basename ${SOURCE[$i]})" if [ -f ${SOURCE[$i]} ]; then echo "Ah, found it!"; continue; fi if ! [ "x${SRCURL[$i]}" == "x" ]; then echo "Will download file to $(dirname $SOURCE[$i])" wget --no-check-certificate -nv -T 20 -O "${SOURCE[$i]}" "${SRCURL[$i]}" || true if [ $? -ne 0 -o ! -s "${SOURCE[$i]}" ]; then echo "Fail to download '$(basename ${SOURCE[$i]})'. Aborting the build." mv -f "${SOURCE[$i]}" "${SOURCE[$i]}".FAIL exit 1 fi else echo "File '$(basename ${SOURCE[$i]})' not available. Aborting the build." exit 1 fi fi done if [ "$P1" == "--download" ]; then echo "Download complete." exit 0 fi # --- PACKAGE BUILDING --- echo "++" echo "|| $PRGNAM-$VERSION" echo "++" echo Building ... echo "Extracting the source archive(s) for $PRGNAM..." cd $TMP/tmp-$PRGNAM tar -xf ${SOURCE[0]} cd ${SRCNAM}-${SRCVER} # Fix the link on 32bit: sed -e '/ldflags /s/-m32/&", "-Wl,-z,notext/' \ -i build/config/compiler/BUILD.gn \ 2>&1 | tee -a $OUTPUT/patch-${PRGNAM}.log # Prevent an error 'Looking for xmlReadMemory - not found ' building clang: sed \ -i tools/clang/scripts/build.py \ -e "s%'lib'%'lib$LIBDIRSUFFIX'%g" sed \ -i third_party/libxml/src/libxml2-config.cmake.in \ -e 's%set(LIBXML2_LIBRARY_DIR *${_libxml2_rootdir}/lib%&'${LIBDIRSUFFIX}'%' # Prevent an error: # 'c-index-test.c:679:3: error: unknown type name xmlRelaxNGPtr' building clang: sed \ -i tools/clang/scripts/build.py \ -e "/DLLVM_ENABLE_LIBXML2=FORCE_ON/a '-DCLANG_ENABLE_LIBXML2=OFF'," # Do not embed a tensorflow model: sed \ -i tools/clang/scripts/build.py \ -e "s/default='default' if sys.platform.startswith('linux') else ''/default=''/" # Slackware specific: # When compiling google's clang on 32bit Slackware or on ARM, add our triplets. # I am a python noob so this is clumsy, better implementation is welcome :-) cp $SRCDIR/patches/clang.toolchains.slackware.triple.diff . cat $SRCDIR/patches/chromium_slackware_triplet.patch | patch -p1 --verbose \ 2>&1 | tee -a $OUTPUT/patch-${PRGNAM}.log # When compiling google's clang, we want 32bit too - don't limit us, devs: sed -i tools/clang/scripts/build.py -e "s/x86_64-unknown-linux-gnu/${SYSROOT_TARGET}/g" if [ "$ARCH" == "i586" ] || [ "${CROSS32}" = "YES" ]; then sed -i tools/clang/scripts/build.py \ -e "s/sysroot_amd64\([,)]\)/sysroot_i386\1/" # \ #-e "s/LLVM_ENABLE_LLD=ON/LLVM_ENABLE_LLD=OFF/" # Non-functional vpython in the 32bit depot_tools: export VPYTHON_BYPASS="manually managed python not supported by chrome operations" fi # And fix the 32bit compilation while we are at it: sed -i tools/clang/scripts/build.py -e "s/ldflags = \[\]/ldflags = \['-latomic','-lpthread'\]/" # ARM platform specifics: if [[ "$ARCH" =~ arm.* ]]; then # Fix the hard-coded bootstrap target 'X86': sed -i tools/clang/scripts/build.py \ -e "s/bootstrap_targets = 'X86'/bootstrap_targets = 'ARM'/" # Compile only the relevant back-ends (ARM, AArch64 and X86): sed -i tools/clang/scripts/build.py \ -e "s/\(^ *targets = \).*$/\1'ARM;X86;AArch64'/" else # Compile only the relevant back-end (X86): sed -i tools/clang/scripts/build.py \ -e "s/\(^ *targets = \).*$/\1'X86'/" fi # We require a 32bit gn binary, devs! sed -i BUILD.gn \ -e 's/target_os != "linux" || /target_os == "linux" || /' export PATH="$TMP/tmp-$PRGNAM/${SRCNAM}-${SRCVER}/third_party/depot_tools:$PATH" # Checking out LLVM demands that we tell git who we are: cat <$TMP/tmp-$PRGNAM/chromium_gitconfig [user] email = alien@slackware.com name = Eric Hameleers [safe] directory = $TMP/tmp-$PRGNAM/${SRCNAM}-${SRCVER}/third_party/rust-src EOT export GIT_CONFIG_GLOBAL=$TMP/tmp-$PRGNAM/curomium_gitconfig # --- Compile --- # # Final link uses lots of file descriptors. ulimit -n 4096 echo "-- Building google's clang toolchain." # Uses a sysroot image always for building LLVM, but since Chromium 121 the # sysroot has some includes in a wrong place. # So, let's download it ourselves and fix it before calling the build: pushd tools/clang/scripts SYSROOT_LOC=$(python3 -c "import build; loc = build.DownloadDebianSysroot('${SYSROOT_ARCH}') ; print(loc)" |tail -1) popd SYSROOTDIR=$(basename $(ls third_party/llvm-build-tools/ |grep ${SYSROOT_ARCH}_sysroot)) # Copy missing includes: rsync -Ha \ third_party/llvm-build-tools/${SYSROOTDIR}/usr/include/${SYSROOT_TARGET}/ \ third_party/llvm-build-tools/${SYSROOTDIR}/usr/include/ # Fix the script so that it does not again download and mangle the sysroot: sed \ -e "s%sysroot_${SYSROOT_ARCH} = DownloadDebianSysroot.*%sysroot_${SYSROOT_ARCH} = '"${SYSROOT_LOC}"'%" \ -i tools/clang/scripts/build.py unset SYSROOTDIR HDR2REM="" if [ "$ARCH" == "i586" ]; then # Actually 32bit compilation fails by not finding 'bits/c++config.h'. # I could only work around this using a kludge: # Keep a list of the symlinks we'll be creating: for HDR in /usr/include/c++/$(gcc -dumpversion)/${TARGET}/bits/*.h ; do if [ ! -f /usr/include/c++/$(gcc -dumpversion)/bits/$(basename $HDR) ]; then ln -s $HDR /usr/include/c++/$(gcc -dumpversion)/bits/ HDR2REM="$(basename $HDR) $HDR2REM" fi done fi export CFLAGS="" export CXXFLAGS="" export LDFLAGS="" python3 tools/clang/scripts/build.py \ --bootstrap \ --skip-checkout \ --pic \ --disable-asserts \ --host-cc /usr/bin/gcc \ --host-cxx /usr/bin/g++ \ --use-system-cmake \ --no-tools \ --without-android \ --without-fuchsia \ --without-zstd \ 2>&1 | tee $OUTPUT/clang_build-${PRGNAM}.log #--gcc-toolchain /usr \ # Output will be in: # third_party/llvm-build/Release+Asserts/ # Building gn for Chromium 110 fails when this file is not present: if [ ! -f third_party/llvm-build/Release+Asserts/cr_build_revision ]; then CLANG_REVISION=$(grep ^CLANG_REVISION tools/clang/scripts/update.py |cut -d= -f2 |tr -d " '") CLANG_SUB_REVISION=$(grep ^CLANG_SUB_REVISION tools/clang/scripts/update.py |cut -d= -f2 |tr -d " '") echo "${CLANG_REVISION}-${CLANG_SUB_REVISION}" > third_party/llvm-build/Release+Asserts/cr_build_revision fi ##### Ensure that only this new clang is used, ignoring the system version: ####MYCLANG_PATH="$TMP/tmp-$PRGNAM/${SRCNAM}-${SRCVER}/third_party/llvm-build/Release+Asserts/bin" ####export PATH="$MYCLANG_PATH:$PATH" #### ####echo "-- Building google's rust toolchain." #### ####### NOTE ### ##### Google does not even consider 32bit Linux as a valid target, so we have to ##### hack support for 'i386' into the build infrastructure ourselves. ##### High-over: ##### - add i386 target to ./tools/rust/build*.py ##### - compile openssl as *static* libraries and install bin, include and lib ##### into ./third_party/llvm-build-tools/openssl/ ##### - add ./third_party/llvm-build-tools/openssl/.cipdpkg/manifest.json ##### containing: ##### { ##### "format_version": "1.1", ##### "package_name": "infra/3pp/static_libs/openssl/linux-i386", ##### "install_mode": "copy" ##### } ##### - disable removing that openssl directory in build_rust.py ##### - ... and possibly lots more crap to fix ####### END NOTE ### #### ###### Next. build Rust against our custom compiler: ####LDFLAGS="$LDFLAGS" \ ####python3 tools/rust/build_rust.py \ #### --skip-llvm-build \ #### --use-system-cmake \ #### 2>&1 | tee $OUTPUT/rust_build-${PRGNAM}.log #### ##### Ensure that only this new rust is used, ignoring the system version: ####MYRUST_PATH="$TMP/tmp-$PRGNAM/${SRCNAM}-${SRCVER}/third_party/rust-toolchain" ####export PATH="$MYRUST_PATH:$PATH" ####