aboutsummaryrefslogtreecommitdiffci
path: root/build.sh
blob: 88b1ca886cd735adc507b20477d9131836109ad2 (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
#!/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
	}
} >&2
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