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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
#!/usr/bin/env bash
#
# Assemble the rpmbuild sources for kernel-surface.spec:
#
# * kernel-surface-patches-<upstream_ver>-<patchset_ver>.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 <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
# "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"
|