#!/bin/bash # # linux kernel CROSS make wrapper # # It will download/unpack the cross tool chain if necessary, # then invoke make with suitable options. # # It detects ARCH in 4 ways. # # - make.i386 # make it a symlink to this script # - make.cross ARCH=i386 # - cd obj-i386; make.cross # - export ARCH=i386; make.cross # # Specify compiler and version (default is gcc): # - COMPILER=gcc-9.3.0 make.cross ARCH=arm64 # - COMPILER=clang make.cross ARCH=arm64 # # Copyright (c) 2014, Intel Corporation. # Author: Fengguang Wu # Credit: Tony Breeds for crosstool COMPILER=${COMPILER:-"gcc"} if [[ ! "$0" =~ 'make.cross' && "$0" =~ make\.([a-z0-9_]+) ]]; then export ARCH="${BASH_REMATCH[1]}" elif [[ "$*" =~ ARCH=([a-z0-9_]+) ]]; then export ARCH="${BASH_REMATCH[1]}" elif [[ ${PWD##*-} =~ ^(i386|x86_64|alpha|arc|arm|arm64|avr32|blackfin|c6x|cris|frv|h8300|hexagon|ia64|m32r|m68k|microblaze|mips|mn10300|openrisc|parisc|powerpc|s390|score|sh|sh64|sparc|sparc32|sparc64|tile|tilepro|tilegx|um|unicore32|xtensa)$ ]]; then export ARCH=${PWD##*-} elif [[ ! $ARCH ]]; then export ARCH=x86_64 fi [[ "$*" =~ ARCH=([a-z0-9_]+) ]] && [[ $ARCH != ${BASH_REMATCH[1]} ]] && { echo "Conflicting ARCH specified! $ARCH ${BASH_REMATCH[1]}" exit 1 } shopt -s nullglob is_clang_worker() { [[ "$COMPILER" =~ "clang" ]] } check_install_path() { if [[ $COMPILER_INSTALL_PATH ]]; then echo "Compiler will be installed in $COMPILER_INSTALL_PATH" else return 1 fi } install_packages() { [[ -x /usr/bin/xz && -x /usr/bin/lftp ]] || { echo Please install: xz-utils lftp return 1 } } download_extract() { local URL="$1" local file="$(basename $URL)" local dir="$(basename $(dirname $URL))" mkdir -p $dir || return cd $dir echo lftpget -c $URL lftpget -c $URL || return cd .. mkdir -p $COMPILER_INSTALL_PATH || return [[ -w "$COMPILER_INSTALL_PATH" ]] || { echo "Can't use $COMPILER_INSTALL_PATH as compiler install path, please choose a different COMPILER_INSTALL_PATH" return 1 } echo tar Jxf $dir/$file -C $COMPILER_INSTALL_PATH tar Jxf $dir/$file -C $COMPILER_INSTALL_PATH } install_crosstool_clang() { local URL='https://download.01.org/0day-ci/cross-package' local list=/tmp/0day-ci-crosstool-files local file='clang.tar.xz' lftp -c "open $URL && find -d 3 > $list" || return file=$(grep $file $list | tail -1) [[ $file ]] || { echo "Cannot find $file under $URL check $list" return 1 } rm $list download_extract "$URL/$file" || { echo "Failed to download $URL/$file" return 1 } } install_crosstool_gcc() { local URL='https://download.01.org/0day-ci/cross-package' local list=/tmp/0day-ci-crosstool-files lftp -c "open $URL && find -d 3 > $list" || return local file local gcc_arch_pattern=$(echo "${gcc_arch}" | sed 's/*/.*/g') local gcc_version [[ $COMPILER =~ - ]] && gcc_version=${COMPILER##*-} if [[ $gcc_version ]]; then # for arch has more than 1 cross tool available, like x86_64-gcc-9.3.0-nolibc_arm-linux-gnueabi.tar.xz # and x86_64-gcc-9.3.0-nolibc_arm-linux-gnueabihf.tar.xz for arm, match "arm-linux-gnueabi." instead of # "arm-linux-gnueabi" to get single tool package which match exactly. file=$(grep "${gcc_arch_pattern}\." $list | grep "${gcc_version}" | tail -1) else file=$(grep "${gcc_arch_pattern}\." $list | tail -1) fi [[ $file ]] || { echo "Cannot find $gcc_arch_pattern under $URL check $list" return 1 } rm $list download_extract "$URL/$file" || { echo "Failed to download $URL/$file" return 1 } } install_crosstool() { if is_clang_worker; then install_crosstool_clang || { echo "clang crosstool install failed" return 1 } else install_crosstool_gcc || { echo "gcc crosstool install failed" return 1 } fi } install_cross_compiler() { install_packages && install_crosstool } setup_compiler_for_xtensa() { local variant variant=$(grep -s -h '^CONFIG_XTENSA_VARIANT_CUSTOM_NAME=' .config | head -n1 | cut -f2 -d'"') if [[ "$variant" = 'fsf' ]]; then gcc_arch=$ARCH-linux elif [[ $variant ]]; then gcc_arch=xtensa-${variant}-linux else gcc_arch=$ARCH-linux fi } setup_crosstool_gcc() { local gcc_arch local gcc_exec case $ARCH in i386|x86_64) gcc_arch= ;; arc|c6x) gcc_arch=$ARCH-elf ;; um) gcc_arch= ;; arm) gcc_arch=arm-linux-gnueabi ;; arm64) gcc_arch=aarch64-linux* ;; powerpc) gcc_arch=powerpc64-linux ;; blackfin) gcc_arch=bfin-uclinux ;; sh) gcc_arch=sh4-linux ;; parisc) if grep -s -q 'CONFIG_64BIT=y' $SRC_ROOT/arch/parisc/configs/$config; then gcc_arch=hppa64-linux else gcc_arch=hppa-linux fi ;; openrisc) gcc_arch=or1k-linux ;; riscv) gcc_arch=riscv64-linux ;; s390) gcc_arch=s390-linux ;; tile|tilegx) gcc_arch=tilegx-linux ;; mn10300) gcc_arch=am33_2.0-linux ;; nds32) gcc_arch=nds32le-linux ;; xtensa) setup_compiler_for_xtensa ;; *) gcc_arch=$ARCH-linux ;; esac if [[ $gcc_arch ]]; then gcc_exec=($COMPILER_INSTALL_PATH/${COMPILER}*/${gcc_arch}/bin/${gcc_arch}-gcc) [[ -x $gcc_exec ]] || install_cross_compiler || { echo "Install gcc cross compiler failed" return 1 } gcc_exec=($COMPILER_INSTALL_PATH/${COMPILER}*/${gcc_arch}/bin/${gcc_arch}-gcc) [[ -x $gcc_exec ]] || { echo "No cross compiler for $ARCH" return 1 } # use highest available version gcc_exec=${gcc_exec[-1]} opt_cross="CROSS_COMPILE=${gcc_exec%gcc}" # load build-in depends libs local deplibs_path=($COMPILER_INSTALL_PATH/${COMPILER}*/${gcc_arch}/libexec/gcc/${gcc_arch}/*) deplibs_path=${deplibs_path[-1]} [[ -d $deplibs_path ]] && export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$deplibs_path else opt_cross= fi return 0 } setup_crosstool_clang() { local cross_clang=("$COMPILER_INSTALL_PATH"/clang-latest/bin/clang) [[ -x $cross_clang ]] || install_cross_compiler || { echo "Install clang compiler failed" return 1 } local cross_clang_path=$(dirname $cross_clang) local opt_ldd="LD=${cross_clang_path}/ld.lld HOSTLD=${cross_clang_path}/ld.lld" [[ $ARCH =~ arm ]] && grep -q 'CONFIG_CPU_BIG_ENDIAN=y' .config && opt_ldd= [[ $ARCH = s390 ]] && opt_ldd= # https://www.kernel.org/doc/html/latest/kbuild/llvm.html opt_cross="HOSTCC=$cross_clang CC=$cross_clang $opt_ldd \ AR=${cross_clang_path}/llvm-ar NM=${cross_clang_path}/llvm-nm \ STRIP=${cross_clang_path}/llvm-strip OBJDUMP=${cross_clang_path}/llvm-objdump \ OBJSIZE=${cross_clang_path}/llvm-size READELF=${cross_clang_path}/llvm-readelf \ HOSTCXX=${cross_clang_path}/clang++ HOSTAR=${cross_clang_path}/llvm-ar" if [[ $ARCH = "arm64" ]]; then opt_cross="$opt_cross CROSS_COMPILE=aarch64-linux-gnu-" elif [[ $ARCH = "arm" ]]; then opt_cross="$opt_cross CROSS_COMPILE=arm-linux-gnueabi-" elif [[ $ARCH = "s390" ]]; then opt_cross="$opt_cross CROSS_COMPILE=s390x-linux-gnu-" else opt_cross="$opt_cross CROSS_COMPILE=$ARCH-linux-gnu-" fi } setup_crosstool() { if is_clang_worker; then setup_crosstool_clang else setup_crosstool_gcc fi } check_install_path || { echo "Please set COMPILER_INSTALL_PATH to specify compiler install path" echo "E.g. COMPILER_INSTALL_PATH=\$HOME/0day COMPILER=clang make.cross ARCH=x86_64" echo exit 1 } setup_crosstool || { echo "setup_crosstool failed" exit 1 } [[ "$*" =~ (-j|--jobs) ]] || { nr_cpu=$(getconf _NPROCESSORS_CONF) opt_jobs="--jobs=$((nr_cpu * 2))" } [[ "$*" =~ "ARCH=$ARCH" ]] || { opt_arch="ARCH=$ARCH" } if [ -d obj-$ARCH ]; then export KBUILD_OUTPUT=obj-$ARCH O=KBUILD_OUTPUT=obj-$ARCH fi [[ -f arch/$ARCH/boot/dts/Makefile ]] && make_dts="CONFIG_OF_ALL_DTBS=y CONFIG_DTC=y" [[ -f .make-env ]] && source ./.make-env if [[ -d source && -L source ]]; then echo make W=1 -C source O=$PWD $make_dts $opt_arch $opt_cross $subarch $opt_jobs "$@" exec make W=1 -C source O=$PWD $make_dts $opt_arch $opt_cross $subarch $opt_jobs "$@" else echo make W=1 $O $make_dts $opt_arch $opt_cross $subarch $opt_jobs "$@" exec make W=1 $O $make_dts $opt_arch $opt_cross $subarch $opt_jobs "$@" fi