aboutsummaryrefslogtreecommitdiffci
path: root/make-sources.sh
blob: b4abb4ba64e0d93803596fcf335698bc45288db0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env bash
#
# Assemble the rpmbuild sources for kernel-surface.spec:
#
#   * kernel-surface-patches-<upstream_ver>-<patchset_ver>.tar.gz, built from the
#     overlay submodule's sys-kernel/vanilla-kernel/files directories listed in
#     patch-order.txt
#   * 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"

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 <name> <value>  ->  <value>
	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

	src="${patch_root}/${dir}"
	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}" "${dir}")
	mkdir -p "${dest}"
	cp "${src}"/*.patch "${dest}/"

	printf '  %02d %-12s %2d patches\n' "${index}" "${dir}" "${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"