projects/aports·blob master · refs

309 lines · 7.4 KiB

1#!/bin/sh
2
3# apk add \
4# abuild apk-tools alpine-conf busybox fakeroot syslinux xorriso cmd:mksquashfs mtools
5# (for efi:) grub
6# (for s390x:) s390-tools
7# (for ppc64le:) grub
8# (for pi:) sfdisk dosfstools
9
10# FIXME: clean workdir out of unneeded sections
11# FIXME: --release: cp/mv images to REPODIR/$ARCH/releases/
12# FIXME: --update-latest: rewrite latest-releases.yaml with this build
13
14set -e
15
16# get abuild configurables
17. "${ABUILD_SHAREDIR:-/usr/share/abuild}"/functions.sh
18
19scriptdir="$(dirname "$0")"
20git=$(command -v git) || git=true
21
22set_source_date() {
23 # dont error out if we're not in git
24 if ! $git rev-parse --show-toplevel >/dev/null 2>&1; then
25 git=true
26 fi
27 # set time stamp for reproducible builds
28 if [ -z "$SOURCE_DATE_EPOCH" ] && [ $($git -C "$scriptdir" status -s | wc -l) -ne 0 ]; then
29 SOURCE_DATE_EPOCH=$($git -C "$scriptdir" log -1 --format=%cd --date=unix)
30 fi
31 if [ -z "$SOURCE_DATE_EPOCH" ]; then
32 SOURCE_DATE_EPOCH=$(date -u "+%s")
33 fi
34 export SOURCE_DATE_EPOCH
35}
36
37set_source_date
38
39#
40all_sections=""
41all_profiles=""
42all_checksums="sha256 sha512"
43all_dirs=""
44build_date="$(date -u +%y%m%d -d "@$SOURCE_DATE_EPOCH")"
45default_arch="$(apk --print-arch)"
46_hostkeys=""
47_simulate=""
48_checksum=""
49
50OUTDIR="$PWD"
51RELEASE="${build_date}"
52
53
54msg() {
55 if [ -n "$quiet" ]; then return 0; fi
56 local prompt="$GREEN>>>${NORMAL}"
57 local name="${BLUE}mkimage${ARCH+-$ARCH}${NORMAL}"
58 printf "${prompt} ${name}: %s\n" "$1" >&2
59}
60
61list_has() {
62 local needle="$1"
63 local i
64 shift
65 for i in $@; do
66 [ "$needle" != "$i" ] || return 0
67 done
68 return 1
69}
70
71usage() {
72 cat <<EOF
73
74$0 [--tag RELEASE] [--outdir OUTDIR] [--workdir WORKDIR]
75 [--arch ARCH] [--profile PROFILE] [--hostkeys] [--simulate]
76 [--repository REPO [--repository REPO]]
77 [--repositories-file REPO_FILE] [--yaml FILE]
78$0 --help
79
80options:
81--arch Specify which architecture images to build
82 (default: $default_arch)
83--hostkeys Copy system apk signing keys to created images
84--outdir Specify directory for the created images
85--profile Specify which profiles to build
86--repositories-file List of repositories to use for the image create
87--repository Package repository to use for the image create
88--simulate Don't execute commands
89--tag Build images for tag RELEASE
90--workdir Specify temporary working directory (cache)
91--yaml
92
93known profiles: $(echo $all_profiles | sort -u)
94
95EOF
96}
97
98# helpers
99load_plugins() {
100 local f
101 [ -e "$1" ] || return 0
102 for f in "$1"/mkimg.*.sh; do
103 [ -e "$f" ] || return 0
104 break
105 done
106 all_profiles="$all_profiles $(sed -n -e 's/^profile_\(.*\)() {$/\1/p' $1/mkimg.*.sh)"
107 all_sections="$all_sections $(sed -n -e 's/^section_\(.*\)() {$/\1/p' $1/mkimg.*.sh)"
108 for f in "$1"/mkimg.*.sh; do
109 . $f
110 done
111}
112
113checksum() {
114 sha1sum | cut -f 1 -d ' '
115}
116
117build_section() {
118 local section="$1"
119 local args="$@"
120 local _dir="${args//[^a-zA-Z0-9]/_}"
121 shift
122 local args="$@"
123
124 if [ -z "$_dir" ]; then
125 return 1
126 fi
127
128 if [ ! -e "$WORKDIR/${_dir}" ]; then
129 DESTDIR="$WORKDIR/${_dir}.work"
130 msg "--> $section $args"
131 if [ -z "$_simulate" ]; then
132 rm -rf "$DESTDIR"
133 mkdir -p "$DESTDIR"
134 build_${section} "$@"
135 mv "$DESTDIR" "$WORKDIR/${_dir}"
136 _dirty="yes"
137 fi
138 fi
139 unset DESTDIR
140 all_dirs="$all_dirs $_dir"
141 _my_sections="$_my_sections $_dir"
142}
143
144build_profile() {
145 local _id _dir _spec
146 _my_sections=""
147 _dirty="no"
148
149 profile_$PROFILE
150 list_has $ARCH $arch || return 0
151
152 msg "Building $PROFILE"
153
154 # Collect list of needed sections, and make sure they are built
155 for SECTION in $all_sections; do
156 section_$SECTION
157 done
158
159 # Defaults
160 [ -n "$image_name" ] || image_name="alpine-${PROFILE}"
161 [ -n "$output_filename" ] || output_filename="${image_name}-${RELEASE}-${ARCH}.${image_ext}"
162 local output_file="${OUTDIR:-.}/$output_filename"
163
164 # Construct final image
165 local _imgid=$(echo -n $_my_sections | sort | checksum)
166 DESTDIR=$WORKDIR/image-$_imgid-$ARCH-$PROFILE
167 if [ "$_dirty" = "yes" -o ! -e "$DESTDIR" ]; then
168 msg "Creating $output_filename"
169 if [ -z "$_simulate" ]; then
170 # Merge sections
171 rm -rf "$DESTDIR"
172 mkdir -p "$DESTDIR"
173 for _dir in $_my_sections; do
174 for _fn in $WORKDIR/$_dir/*; do
175 [ ! -e "$_fn" ] || cp -Lrs $_fn $DESTDIR/
176 done
177 done
178 echo "${image_name}-${RELEASE} ${build_date}" > "$DESTDIR"/.alpine-release
179 fi
180 fi
181
182 if [ "$_dirty" = "yes" -o ! -e "$output_file" ]; then
183 # Create image
184 [ -n "$output_format" ] || output_format="${image_ext//[:\.]/}"
185 create_image_${output_format}
186
187 if [ "$_checksum" = "yes" ]; then
188 for _c in $all_checksums; do
189 echo "$(${_c}sum "$output_file" | cut -d' ' -f1) ${output_filename}" > "${output_file}.${_c}"
190 done
191 fi
192 fi
193 if [ -n "$_yaml_out" ]; then
194 $mkimage_yaml --release $RELEASE \
195 --title "$title" \
196 --desc "$desc" \
197 "$output_file" >> "$_yaml_out"
198 fi
199}
200
201# load plugins
202load_plugins "$scriptdir"
203if [ -n "$HOME" ]; then
204 load_plugins "$HOME/.mkimage"
205fi
206
207mkimage_yaml="$(dirname $0)"/mkimage-yaml.sh
208
209# parse parameters
210while [ $# -gt 0 ]; do
211 opt="$1"
212 shift
213 case "$opt" in
214 --repositories-file) REPOS_FILE="$1"; shift ;;
215 --repository)
216 if [ -z "$REPOS" ]; then
217 REPOS="$1"
218 else
219 REPOS=$(printf '%s\n%s' "$REPOS" "$1");
220 fi
221 shift ;;
222 --extra-repository)
223 warning "--extra-repository is deprecated. Use multiple --repository"
224 EXTRAREPOS="$EXTRAREPOS $1"
225 shift ;;
226 --workdir) WORKDIR="$1"; shift ;;
227 --outdir) OUTDIR="$1"; shift ;;
228 --tag) RELEASE="$1"; shift ;;
229 --arch) req_arch="$1"; shift ;;
230 --profile) req_profiles="$1"; shift ;;
231 --hostkeys) _hostkeys="--hostkeys";;
232 --simulate) _simulate="yes";;
233 --checksum) _checksum="yes";;
234 --yaml) _yaml="yes";;
235 --help) usage; exit 0;;
236 --) break ;;
237 -*) usage; exit 1;;
238 esac
239done
240
241if [ -z "$RELEASE" ]; then
242 if git describe --exact-match >/dev/null 2>&1; then
243 RELEASE=$(git describe --always)
244 RELEASE=${RELEASE#v}
245 else
246 RELEASE="${build_date}"
247 fi
248fi
249
250if [ -z "$REPOS" ]; then
251 echo "Must provide --repository"
252 exit 2
253fi
254
255# setup defaults
256if [ -z "$WORKDIR" ]; then
257 WORKDIR="$(mktemp -d -t mkimage.XXXXXX)"
258 trap 'rm -rf $WORKDIR' INT EXIT
259fi
260req_profiles=${req_profiles:-${all_profiles}}
261req_arch=${req_arch:-${default_arch}}
262[ "$req_arch" != "all" ] || req_arch="${all_arch}"
263[ "$req_profiles" != "all" ] || req_profiles="${all_profiles}"
264
265mkdir -p "$OUTDIR"
266
267# get abuild pubkey used to sign the apkindex
268# we need inject this to the initramfs or we will not be able to use the
269# boot repository
270_pub=${PACKAGER_PRIVKEY:+${PACKAGER_PRIVKEY}.pub}
271_abuild_pubkey="${PACKAGER_PUBKEY:-$_pub}"
272
273# create images
274for ARCH in $req_arch; do
275 APKROOT="$WORKDIR/apkroot-$ARCH"
276 if [ ! -e "$APKROOT" ]; then
277 # create root for caching packages
278 mkdir -p "$APKROOT/etc/apk/cache" "$APKROOT"/etc/apk/keys
279 if [ -d /usr/share/apk/keys/"$ARCH" ]; then
280 cp /usr/share/apk/keys/"$ARCH"/* "$APKROOT"/etc/apk/keys
281 fi
282 if [ -n "$_hostkeys" ]; then
283 cp /etc/apk/keys/* "$APKROOT"/etc/apk/keys
284 fi
285 if [ -n "$_abuild_pubkey" ]; then
286 cp "$_abuild_pubkey" "$APKROOT"/etc/apk/keys
287 fi
288 apk --arch "$ARCH" --root "$APKROOT" add --initdb --no-chown
289
290 _repositories="$APKROOT/etc/apk/repositories"
291 if [ -n "$REPOS_FILE" ]; then
292 cat "$REPOS_FILE" > "$_repositories"
293 fi
294 echo "$REPOS" >> "$_repositories"
295 for repo in $EXTRAREPOS; do
296 echo "$repo" >> "$_repositories"
297 done
298 fi
299 apk update --root "$APKROOT"
300
301 if [ "$_yaml" = "yes" ]; then
302 _yaml_out=${OUTDIR:-.}/latest-releases.yaml
303 echo "---" > "$_yaml_out"
304 fi
305 for PROFILE in $req_profiles; do
306 (set -eo pipefail; build_profile)
307 done
308done
309echo "Images generated in $OUTDIR"