#!/usr/bin/env bash # # Assemble the rpmbuild sources for kernel-surface.spec: # # * kernel-surface-patches--.tar.gz, built from the # directories listed in patch-order.txt: bare names come from the overlay # submodule's sys-kernel/vanilla-kernel/files, "local:" ones from this # repository's patches/ # * the upstream kernel tarball # * the base kernel config and the fragments from config/ # # The versions default to the spec file's, so a plain checkout needs no # arguments. UPSTREAM_VER and PATCHSET_VER override them, which is how the # release pipeline hands over the versions it read out of the git tag; they have # to be passed to rpmbuild as --define too, or the two disagree about what the # Source1 tarball is called. # # Usage: ./make-sources.sh [-o OUTPUT_DIR] [-n] # # -o where to write the sources (default: rpm's %_sourcedir, else ./SOURCES) # -n build the patch tarball only, skip the downloads # # Environment: # # UPSTREAM_VER kernel version to assemble for, overriding the spec's # PATCHSET_VER patchset version to assemble for, overriding the spec's # OVERLAY_DIR the Gentoo overlay checkout (default: ./overlay) set -euo pipefail script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) spec="${script_dir}/kernel-surface.spec" order_file="${script_dir}/patch-order.txt" overlay_dir=${OVERLAY_DIR:-${script_dir}/overlay} patch_root="${overlay_dir}/sys-kernel/vanilla-kernel/files" local_patch_root="${script_dir}/patches" output_dir="" skip_download=false while getopts ':o:nh' opt; do case "${opt}" in o) output_dir=${OPTARG} ;; n) skip_download=true ;; h) sed -n '2,20p' "${BASH_SOURCE[0]}"; exit 0 ;; *) echo "unknown option -${OPTARG}" >&2; exit 2 ;; esac done if [[ -z ${output_dir} ]]; then if command -v rpm >/dev/null 2>&1; then output_dir=$(rpm --eval '%{_sourcedir}') else output_dir="${script_dir}/SOURCES" fi fi spec_global() { # %global -> awk -v key="$1" '$1 == "%global" && $2 == key { print $3; exit }' "${spec}" } upstream_ver=${UPSTREAM_VER:-$(spec_global upstream_ver)} patchset_ver=${PATCHSET_VER:-$(spec_global patchset_ver)} for var in upstream_ver patchset_ver; do [[ -n ${!var} ]] || { echo "${var} is neither set in the environment nor readable as a" >&2 echo "%global from ${spec}" >&2 exit 1 } done echo "Assembling sources for kernel ${upstream_ver}, patchset ${patchset_ver}" if [[ ! -d ${patch_root} ]]; then echo "${patch_root} not found." >&2 echo "Run: git submodule update --init overlay" >&2 exit 1 fi mkdir -p "${output_dir}" #-------------------------------------- # Patch tarball #-------------------------------------- # The directory names inside the tarball carry a numeric prefix so that the # spec's `for patchdir in patches/*/` loop reproduces patch-order.txt without # having to read it. staging=$(mktemp -d) trap 'rm -rf "${staging}"' EXIT index=0 total=0 while read -r dir; do dir=${dir%%#*} dir=${dir//[[:space:]]/} [[ -n ${dir} ]] || continue # "local:foo" is patches/foo in this repository, "foo" is the overlay's # files/foo. The staging name keeps the prefix so the tarball, and the # spec's "Applying ..." log, say where each patch came from. if [[ ${dir} == local:* ]]; then name=${dir#local:} src="${local_patch_root}/${name}" label="local-${name}" else name=${dir} src="${patch_root}/${name}" label=${name} fi if [[ ! -d ${src} ]]; then echo "ERROR: ${src} does not exist (listed in patch-order.txt)" >&2 exit 1 fi count=$(find "${src}" -maxdepth 1 -name '*.patch' | wc -l | tr -d ' ') if [[ ${count} -eq 0 ]]; then echo "ERROR: no patches in ${src}" >&2 exit 1 fi dest=$(printf '%s/patches/%02d-%s' "${staging}" "${index}" "${label}") mkdir -p "${dest}" cp "${src}"/*.patch "${dest}/" printf ' %02d %-18s %2d patches\n' "${index}" "${label}" "${count}" index=$((index + 1)) total=$((total + count)) done < "${order_file}" tarball="${output_dir}/kernel-surface-patches-${upstream_ver}-${patchset_ver}.tar.gz" # COPYFILE_DISABLE stops macOS tar from adding ._ AppleDouble members, which # would show up as bogus patch files in the spec's glob. COPYFILE_DISABLE=1 tar -czf "${tarball}" -C "${staging}" patches echo "${tarball} (${index} directories, ${total} patches)" #-------------------------------------- # Base config and fragments #-------------------------------------- for cfg in base-aarch64 surface live-image no-debug-info; do cp "${script_dir}/config/${cfg}.config" "${output_dir}/${cfg}.config" done echo "${output_dir}/{base-aarch64,surface,live-image,no-debug-info}.config" if [[ ${skip_download} == true ]]; then exit 0 fi #-------------------------------------- # Upstream tarball #-------------------------------------- fetch() { local url=$1 dest=$2 if [[ -s ${dest} ]]; then echo "${dest} (already present)" return fi echo "Fetching ${url}" curl -fL --retry 3 --progress-bar -o "${dest}.part" "${url}" mv "${dest}.part" "${dest}" echo "${dest}" } if [[ ${upstream_ver} == *-rc* ]]; then # Release candidates only exist as a git snapshot, not on cdn.kernel.org. kernel_url="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-${upstream_ver}.tar.gz" else kernel_url="https://cdn.kernel.org/pub/linux/kernel/v${upstream_ver%%.*}.x/linux-${upstream_ver}.tar.gz" fi fetch "${kernel_url}" "${output_dir}/linux-${upstream_ver}.tar.gz"