#!/bin/bash # SPDX-License-Identifier: GPL-2.0+ set -e kbuild_root=$(dirname $(readlink -f "$0")) kernel_root="${PWD}" kernel_output="${kernel_root}/output" declare -A cross_compile declare -A extra_kcflags declare -A target_root if [[ -r $kbuild_root/config.sh ]] ; then source $kbuild_root/config.sh || exit 1 fi #kbuild_options='CONFIG_DEBUG_SECTION_MISMATCH=y' #kbuild_options='C=1' kbuild_options="KALLSYMS_EXTRA_PASS=0" get_kernel_version() { local version=$(cat Makefile | grep '^VERSION = ' | sed 's/.* = //') local patchlevel=$(cat Makefile | grep '^PATCHLEVEL = ' | sed 's/.* = //') local sublevel=$(cat Makefile | grep '^SUBLEVEL = ' | sed 's/.* = //') echo "$version.$patchlevel.$sublevel" } version=$(get_kernel_version) # # Options parsing # usage() { echo "Usage: $(basename $1) [options] platform [make options]" echo "" echo "Supported options:" echo "--bootloader file Boot loader file (CrOS images only)" echo "--build components List of components to build: image, modules, dt (default: all)" echo "--cmdline Command line arguments file (CrOS images only)" echo "--config Run menuconfig" echo "--deb Create Debian packages" echo "--defconfig file Generate a new .config with defaults from file" echo "--doc[=dir] Compile the documentation (for the specified dir only)" echo "--dt-check file Run DT bindings checks" echo "-h, --help Print this help text" echo "-- End options parsing, next argument is the platform" echo "" echo "Supported platforms:" for f in $kbuild_root/platforms/*.sh ; do echo "- $(basename -s .sh $f)" done } declare -A do_build do_menu_config=0 do_package_deb=0 opt_bootloader= opt_build="image,modules,dt" opt_cmdline_file= opt_defconfig= opt_doc_dirs='.' opt_dt_bindings='' opt_make_opts= while [[ $# != 0 ]] ; do option=$1 shift case $option in --bootloader) opt_bootloader=$1 if [[ ! -r $opt_bootloader ]] ; then echo "Boot loader file $opt_bootloader is not readable" exit 1 fi shift ;; --build) opt_build="$1" shift ;; --cmdline) opt_cmdline_file=$1 if [[ ! -r $opt_cmdline_file ]] ; then echo "Command line file $opt_cmdline_file is not readable" exit 1 fi shift ;; --config) do_menu_config=1 ;; --deb) do_package_deb=1 ;; --defconfig) opt_defconfig=$1 if [[ ! -r $opt_defconfig ]] ; then echo "defconfig file $opt_defconfig is not readable" exit 1 fi shift ;; --doc) do_build[doc]=1 ;; --doc=*) do_build[doc]=1 opt_doc_dirs="${option/--doc=/}" ;; --dt-check) opt_dt_bindings="$1" shift ;; -h|--help) usage $0 exit 1 ;; --) platform=auto ;; --*) echo "Unrecognized option $option" exit 1 ;; *) if [[ -z "$platform" ]] ; then platform=$option else opt_make_opts="$option $opt_make_opts" fi ;; esac done IFS=',' read -r -a opt_build <<< "$opt_build" for component in ${opt_build[@]} ; do case $component in dt|image|modules) do_build[$component]=1 ;; *) echo "Invalid build component ${component}" exit 1 ;; esac done # # Platform # kcflags="-Werror -Wno-error=cpp" if [[ -z "$platform" || "$platform" == "auto" ]] ; then for f in $kbuild_root/platforms/*.sh ; do pattern=$(cat $f | grep "dir_pattern=" | head -1) pattern=${pattern/#dir_pattern=/} if [[ -n "$pattern" ]] ; then echo "$kernel_root" | grep -q "/$pattern/" || continue platform=$(basename -s .sh $f) break fi done fi if [[ ! -r "$kbuild_root/platforms/$platform.sh" ]] ; then echo "Unknown platform '$platform'. Supported platforms are" for f in $kbuild_root/platforms/*.sh ; do echo "- $(basename -s .sh $f)" done exit 1 fi source "${kbuild_root}/platforms/$platform.sh" || exit 1 # Apply version-specific kcflags, useful to suppress warnings based on the # kernel version. [[ -z "${extra_kcflags[$version]+_}" ]] || kcflags="$kcflags ${extra_kcflags[$version]}" # # Architecture # if [[ ! -r "$kbuild_root/arch/$arch.sh" ]] ; then echo "Unknown architecture '$arch'. Supported architectures are" for f in $kbuild_root/arch/*.sh ; do echo "- $(basename -s .sh $f)" done exit 1 fi source "${kbuild_root}/arch/$arch.sh" || exit 1 # Override the output directory for ARM for historical reasons case $arch in arm) output_dir="$kernel_output/arm32" ;; *) output_dir="$kernel_output/$arch" ;; esac # # Build environment and tools # num_cpus=$(cat /proc/cpuinfo | grep '^processor\b' | wc -l) make="make ARCH=$arch O=$output_dir CROSS_COMPILE=${cross_compile[$arch]} ${extra_make_args}" pmake="$make -j$((num_cpus*2)) $opt_make_opts" echo "Compiling for platform $platform with $num_cpus CPUs" mkdir -p $output_dir/ if [[ -n "$opt_defconfig" ]] ; then mkdir -p $output_dir/arch/$arch/configs/ cp $opt_defconfig $output_dir/arch/$arch/configs/build_defconfig $make build_defconfig rm $output_dir/arch/$arch/configs/build_defconfig fi if [[ $do_menu_config == 1 ]] ; then $make menuconfig exit 0 fi # # Compile documentation if requested # if [[ ${do_build[doc]} == 1 ]] ; then ( if [[ ! -f "$kernel_output/doc/bin/activate" ]] ; then virtualenv "$kernel_output/doc" source "$kernel_output/doc/bin/activate" pip install -r Documentation/sphinx/requirements.txt else source "$kernel_output/doc/bin/activate" fi $pmake SPHINXDIRS="${opt_doc_dirs}" htmldocs ) fi # # Check DT bindings # if [[ ! -z ${opt_dt_bindings} ]] ; then $pmake dt_binding_check DT_CHECKER_FLAGS=-m "DT_SCHEMA_FILES=${opt_dt_bindings}" fi # # Compile the kernel, modules and DTBs # kernel_dtbs= if [[ ${do_build[dt]} == 1 ]] ; then for dtb in ${dtbs[@]} ; do dtb=${dtb/:*/} if [[ "${dtb}" == /* ]] ; then continue fi kernel_dtbs="$kernel_dtbs $dtb" done fi if [[ ${do_build[image]} == 1 ]] ; then $pmake $kbuild_options KCFLAGS="$kcflags" $image_kernel $kernel_dtbs fi grep 'CONFIG_MODULES=y' $output_dir/.config > /dev/null && modules=modules if [[ x$modules == xmodules ]] && [[ ${do_build[modules]} == 1 ]]; then $pmake $kbuild_options KCFLAGS="$kcflags" $modules fi version=$(cat $output_dir/include/generated/utsrelease.h | cut -d '"' -f 2) # # Create the image # _image_type=${image/:*/} if [[ -r "$kbuild_root/images/${_image_type}.sh" ]] ; then source "${kbuild_root}/images/${_image_type}.sh" || exit 1 eval make_${_image_type}_image else _image_file=${_image_type} fi if echo "${image}" | grep -q ':' ; then _image_name=${image/*:/} else _image_name=${_image_file} fi _image_file="$output_dir/arch/$arch/boot/${_image_file}" # # Copy the files to their destination directories. # # The kernel image and DTBs are copied to both $target_dir/boot and $tftp_dir # (if available). When the image format is CrOS, installation to $tftp_dir is # skipped as Chrome OS devices can't boot from TFTP. # # The modules are installed to $target_dir if available, or to # $output_dir/modules otherwise. # target_dir=${target_dir:-${target_root[$arch]}} tftp_dir=${tftp_dir:-$tftp_root/$platform} copy_dtbs() { local dest_dir=$1 local dtb if [[ ${do_build[dt]} != 1 ]] ; then return fi if [[ $_image_type == FIT || $_image_type == CrOS ]] ; then return fi for dtb in ${dtbs[@]} ; do local src=${dtb/:*/} local dst=${dtb/*:/} # If a destination is explicitly specified, don't strip # directory name. This can be used for instance to store .dtbo # files in an overlays/ subdirectory. if ! echo ${dtb} | grep -q ':' ; then dst=$(basename $dst) fi # The destination should never be an absolute path. if [[ "${dst}" == /* ]] ; then echo "Error: DTB destination ${dtb} can't be absolute path" exit 1 fi mkdir -p $(dirname $dest_dir/$dst) cp $output_dir/arch/${arch}/boot/dts/$src* $dest_dir/$dst done } if [[ -d "$target_dir" ]] ; then mkdir -p $target_dir/boot cp ${_image_file} $target_dir/boot/${_image_name} copy_dtbs $target_dir/boot/ fi if [[ $_image_type != CrOS && -d "$tftp_dir" ]] ; then cp ${_image_file} $tftp_dir/${_image_name} copy_dtbs $tftp_dir/ fi if [[ x$modules == xmodules ]] && [[ ${do_build[modules]} == 1 ]]; then mod_path=${target_dir:-$output_dir/modules} mkdir -p $mod_path $pmake INSTALL_MOD_PATH=$mod_path modules_install fi # # Create the Debian package if requested # if [[ $do_package_deb == 1 ]] ; then $pmake $kbuild_options KCFLAGS="$kcflags" DPKG_FLAGS="-d" bindeb-pkg fi # # Print status and terminate # echo "Kernel image available in ${_image_file}" if [[ x$modules == xmodules ]] && [[ ${do_build[modules]} == 1 ]]; then echo "Kernel modules installed to $mod_path/lib/modules/$version" fi echo "Build $version completed at $(date)"