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
|
#!/usr/bin/env bash
#
# Rebuild Fedora's libcamera with this board's patches on top.
#
# libcamera has no plugin mechanism for CameraSensorHelper: the per-sensor gain
# models are compiled into libcamera.so, so teaching the software ISP about the
# Surface Pro 12"'s front sensor means shipping a rebuilt package. The patches
# in patches/ are held against Fedora's source RPM rather than an upstream git
# checkout, so the result stays a drop-in replacement for the distribution
# package -- same name, same subpackages, same soname.
#
# Usage: ./build.sh [-o OUTPUT_DIR] [-w WORK_DIR] [-n]
#
# -o where the built binary RPMs are copied (default: ./RPMS)
# -w scratch directory, reused between runs (default: ./.libcamera-build)
# -n resolve only: print the binary RPM file names the build would produce,
# one per line, and exit without building. Lets a caller check whether
# the packages are already published before paying for a build.
#
# Environment:
#
# RELEASE_SUFFIX what to append to Fedora's release (default: sp12in1)
set -euo pipefail
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
patch_dir="${script_dir}/patches"
suffix=${RELEASE_SUFFIX:-sp12in1}
output_dir="$(pwd)/RPMS"
work_dir="$(pwd)/.libcamera-build"
resolve_only=false
while getopts ':o:w:nh' opt; do
case "${opt}" in
o) output_dir=${OPTARG} ;;
w) work_dir=${OPTARG} ;;
n) resolve_only=true ;;
h) sed -n '2,30p' "${BASH_SOURCE[0]}"; exit 0 ;;
*) echo "unknown option -${OPTARG}" >&2; exit 2 ;;
esac
done
topdir="${work_dir}/rpmbuild"
spec="${topdir}/SPECS/libcamera.spec"
if [[ ! -f ${spec} ]]; then
rm -rf "${work_dir}"
mkdir -p "${work_dir}" "${topdir}"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
( cd "${work_dir}" && dnf download --source libcamera )
srpm=$(echo "${work_dir}"/libcamera-*.src.rpm)
[[ -f ${srpm} ]] || { echo "no libcamera source RPM was downloaded" >&2; exit 1; }
rpm --define "_topdir ${topdir}" -i "${srpm}"
shopt -s nullglob
patches=("${patch_dir}"/*.patch)
shopt -u nullglob
[[ ${#patches[@]} -gt 0 ]] || { echo "no patches in ${patch_dir}" >&2; exit 1; }
# The spec uses %autosetup -p1, so a PatchNN: line is the whole of it --
# nothing has to call %patch. Number them after the last one Fedora ships.
last_num=$(grep -oE '^Patch[0-9]+:' "${spec}" | grep -oE '[0-9]+' | sort -n | tail -1)
last_num=${last_num:-0}
last_line=$(grep -nE '^Patch[0-9]+:' "${spec}" | tail -1 | cut -d: -f1)
[[ -n ${last_line} ]] || { echo "no Patch lines in ${spec} to append after" >&2; exit 1; }
insert="${work_dir}/patch-lines"
: > "${insert}"
for patch in "${patches[@]}"; do
cp "${patch}" "${topdir}/SOURCES/"
last_num=$((10#${last_num} + 1))
printf 'Patch%02d: %s\n' "${last_num}" "$(basename "${patch}")" >> "${insert}"
done
sed -i "${last_line}r ${insert}" "${spec}"
sed -i -E "0,/^Release:/s/^(Release:[[:space:]]*[^%]*)(%\{\?dist\})/\1.${suffix}\2/" "${spec}"
grep -qE "^Release:.*\.${suffix}%\{\?dist\}" "${spec}" || {
echo "failed to add the .${suffix} release suffix to ${spec}" >&2
exit 1
}
fi
mapfile -t rpm_files < <(rpmspec -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm\n' "${spec}")
[[ ${#rpm_files[@]} -gt 0 ]] || { echo "rpmspec -q produced no packages" >&2; exit 1; }
if [[ ${resolve_only} == true ]]; then
printf '%s\n' "${rpm_files[@]}"
exit 0
fi
dnf --assumeyes builddep "${spec}"
rpmbuild --define "_topdir ${topdir}" -bb "${spec}"
mkdir -p "${output_dir}"
for rpm_file in "${rpm_files[@]}"; do
built=$(find "${topdir}/RPMS" -type f -name "${rpm_file}" -print -quit)
[[ -n ${built} ]] || { echo "rpmbuild did not produce ${rpm_file}" >&2; exit 1; }
cp "${built}" "${output_dir}/"
echo "${output_dir}/${rpm_file}"
done
|