-
Notifications
You must be signed in to change notification settings - Fork 41
/
build.sh
executable file
·599 lines (527 loc) · 20.3 KB
/
build.sh
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
#!/usr/bin/env bash
# Volumio Image Builder
# Copyright Michelangelo Guarise - Volumio.org
#
# TODO: Add gé credits
#
# Dependencies:
# parted squashfs-tools dosfstools multistrap qemu binfmt-support qemu-user-static kpartx
set -eo pipefail
SRC="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
# Load helpers
# shellcheck source=./scripts/helpers.sh
source "${SRC}/scripts/helpers.sh"
export -f log
export -f time_it
export -f isMounted
# Load configs
# shellcheck source=./recipes/configurations/config.sh
source "${SRC}/recipes/configurations/config.sh"
# shellcheck source=./recipes/configurations/buildoptions.sh
source "${SRC}/recipes/configurations/buildoptions.sh"
mapfile -t DEVICE_LIST < <(basename -s .sh "${SRC}"/recipes/devices/*.sh | sort)
log "Running Volumio Image Builder -" "info"
#Help function
function HELP() {
cat <<-EOF
Help documentation for Volumio Image Builder
Basic usage: ./build.sh -b arm -d pi -v 2.0
Switches:
-b <arch> Build a base rootfs with Multistrap.
Options for the target architecture are
'arm' (Raspbian armhf 32bit), 'armv7' (Debian armhf 32bit), 'armv8' (Debian arm64 64bit)
'x64' (Debian amd64 64bit).
-d <device> Create Image for Specific Devices. Supported device names
$(printf "\t\t%s\n" "${DEVICE_LIST[@]}")
-v <version> Version must be a dot separated number. Example <1.102>.
-- Advanced features --
-t <variant> Volumio Variant type.
-p <dir> Optionally patch the builder. <dir> should contain a tree of
files you want to replace within the build tree. Experts only.
Example: Build a Raspberry PI image from scratch, version 2.0 :
./build.sh -b arm -d pi -v 2.0
EOF
exit 1
}
mount_chroot() {
local base=$1
log "Mounting temp devices for chroot at ${base}" "info"
mount /sys "${base}/sys" -t sysfs
mount /proc "${base}/proc" -t proc
mount chdev "${base}/dev" -t devtmpfs || mount --bind /dev "${base}/dev"
mount chpts "${base}/dev/pts" -t devpts
# Lets record this, might come in handy.
CHROOT=yes
export CHROOT
}
unmount_chroot() {
local base=$1
log "Unmounting chroot temporary devices at ${base}"
umount -l "${base}/dev" || log "umount dev failed" "wrn"
umount -l "${base}/proc" || log "umount proc failed" "wrn"
umount -l "${base}/sys" || log "umount sys failed" "wrn"
# Setting up cgmanager under chroot/qemu leaves a mounted fs behind, clean it up
if [[ -d "${base}/run/cgmanager/fs" ]]; then
umount -l "${base}/run/cgmanager/fs" || log "unmount cgmanager failed" "wrn"
fi
CHROOT=no
}
exit_error() {
log "Build script failed!!" "err"
log "Error stack $(printf '[%s] <= ' "${FUNCNAME[@]:1}")" "err" "$(caller)"
# Check if there are any mounts that need cleaning up
# If dev is mounted, the rest should also be mounted (right?)
if isMounted "${ROOTFS}/dev"; then
unmount_chroot "${ROOTFS}"
fi
}
trap 'exit_error ${LINENO}' INT ERR
function check_os_release() {
os_release="${ROOTFS}/etc/os-release"
# This shouldn't be required anymore - we pack the rootfs tarball at base level
if grep "VOLUMIO_VERSION" "${os_release}"; then
# os-release already has a VERSION number
# remove prior version and hardware
log "Removing previous VOLUMIO_VERSION and VOLUMIO_HARDWARE from os-release"
sed -i '/^\(VOLUMIO_VERSION\|VOLUMIO_HARDWARE\)/d' "${os_release}"
fi
# We keep backward compatibly for some cases for devices with ambiguous names
# mainly raspberry -> pi
log "Adding ${VERSION} and ${VOL_DEVICE_ID:-${DEVICE}} to os-release" "info"
cat <<-EOF >>"${os_release}"
VOLUMIO_VERSION="${VERSION}"
VOLUMIO_HARDWARE="${VOL_DEVICE_ID-${DEVICE}}"
EOF
}
## Fetch the NodeJS BE and FE
function fetch_volumio_from_repo() {
log 'Cloning Volumio Node Backend'
[[ -d "${ROOTFS}/volumio" ]] && rm -r "${ROOTFS}/volumio"
mkdir "${ROOTFS}/volumio"
log "Cloning Volumio from ${VOL_BE_REPO} - ${VOL_BE_REPO_BRANCH}"
git clone --depth 10 -b "${VOL_BE_REPO_BRANCH}" --single-branch "${VOL_BE_REPO}" "${ROOTFS}/volumio"
if [[ -n ${VOL_BE_REPO_SHA} ]]; then
log "Setting BE_REPO to commit" "${VOL_BE_REPO_SHA}"
git -C "${ROOTFS}/volumio/" reset --hard "${VOL_BE_REPO_SHA}"
fi
log "Adding precommit hooks"
cat <<-EOF >"${ROOTFS}/volumio/.git/hooks/pre-commit"
#!/bin/bash
# Pre-commit hook, uncomment when finished linting all codebase
#npm run lint-staged
EOF
log "Adding wireless.js"
cp "${SRC}/volumio/bin/wireless.js" "${ROOTFS}/volumio/app/plugins/system_controller/network/wireless.js"
log 'Cloning Volumio UI'
git clone --depth 1 -b dist --single-branch https://github.com/volumio/Volumio2-UI.git "${ROOTFS}/volumio/http/www"
git clone --depth 1 -b dist3 --single-branch https://github.com/volumio/Volumio2-UI.git "${ROOTFS}/volumio/http/www3"
log "Adding Volumio revision information to os-release"
BUILD_VER=$(git rev-parse HEAD)
FE_VER=$(git --git-dir "${ROOTFS}/volumio/http/www/.git" rev-parse HEAD)
FE3_VER=$(git --git-dir "${ROOTFS}/volumio/http/www3/.git" rev-parse HEAD)
BE_VER=$(git --git-dir "${ROOTFS}/volumio/.git" rev-parse HEAD)
if grep -q VOLUMIO_FE_VERSION "${ROOTFS}"/etc/os-release; then
log "Updating Volumio rev"
sed -i -e "s|\(^VOLUMIO_BUILD_VERSION=\).*|\1\"${BUILD_VER}\"|" \
-e "s|\(^VOLUMIO_FE_VERSION=\).*|\1\"${FE_VER}\"|" \
-e "s|\(^VOLUMIO_FE3_VERSION=\).*|\1\"${FE3_VER}\"|" \
-e "s|\(^VOLUMIO_BE_VERSION=\).*|\1\"${BE_VER}\"|" \
"${ROOTFS}"/etc/os-release
else
log "Appending Volumio rev"
cat <<-EOF >>"${ROOTFS}"/etc/os-release
VOLUMIO_BUILD_VERSION="${BUILD_VER}"
VOLUMIO_FE_VERSION="${FE_VER}"
VOLUMIO_FE3_VERSION="${FE3_VER}"
VOLUMIO_BE_VERSION="${BE_VER}"
VOLUMIO_ARCH="${BUILD}"
EOF
fi
cat "${ROOTFS}"/etc/os-release
# Clean up git repo
rm -rf "${ROOTFS}/volumio/http/www/.git"
rm -rf "${ROOTFS}/volumio/http/www3/.git"
log "Cloned Volumio BE" "okay" "$(git --git-dir "${ROOTFS}/volumio/.git" log --oneline -1)"
}
function setup_multistrap() {
log "Setting up Multistrap environment" "info"
log "Preparing rootfs apt-config"
DirEtc="${ROOTFS}"/etc/apt
DirEtcparts=${DirEtc}/apt.conf.d
DirEtctrustedparts=${DirEtc}/trusted.gpg.d
mkdir -p "${DirEtcparts}"
mkdir -p "${DirEtctrustedparts}"
echo -e 'Dpkg::Progress-Fancy "1";\nAPT::Color "1";' > \
"${DirEtcparts}"/01progress
if [[ -n "${APT_CACHE}" ]] && ! curl -sSf "${APT_CACHE}" >/dev/null; then
cat <<-EOF >"${DirEtcparts}/02cache"
Acquire::http { Proxy "${APT_CACHE}"; };
EOF
fi
log "Adding SecureApt keys to rootfs"
for key in "${!SecureApt[@]}"; do
apt-key --keyring "${DirEtctrustedparts}/${key}" \
adv --fetch-keys "${SecureApt[$key]}"
done
if [[ ${ARCH} == $(dpkg --print-architecture) ]]; then
# Some packages need more help, give it to them
log "Creating /dev/urandom for multistrap on native arch"
mkdir "${ROOTFS}/dev/"
mknod "${ROOTFS}/dev/urandom" c 1 9
chmod 640 "${ROOTFS}/dev/urandom"
chown 0:0 "${ROOTFS}/dev/urandom"
fi
}
function patch_multistrap_conf() {
local type="$1"
case "$type" in
arm)
log "Patching multistrap config to point to Raspbian sources" "info"
BASECONF=recipes/base/VolumioBase.conf
export RASPBIANCONF=recipes/base/arm-raspbian.conf
debian_source=http://deb.debian.org/debian
rapsbian_source=http://mirrordirector.raspbian.org/raspbian
cat <<-EOF >"${SRC}/${RASPBIANCONF}"
# Auto generated multistrap configuration for Raspberry Pi
# Please do not edit this file, add extra Raspberry Pi specific packages to <arm.conf> which build upon this base
# Using pi's debian source containing packages built for armhf with ARMv6 ISA (VFP2) instead of Debian's ARMv7 ISA(VFP3)
EOF
sed "s|^source=${debian_source}|source=${rapsbian_source}|g" "${SRC}/${BASECONF}" >>"${SRC}/${RASPBIANCONF}"
log "Raspbian multistrap config created at ${RASPBIANCONF##*/}"
;;
x64)
log "Patching x86 multistrap config for x86_amd64" "info"
log "Nothing to do for now!"
# This is just so we don't need to maintain a x64 multistrap recipe
;;
*)
log "Multistrap patch ${type} is unknown" "error"
exit 1
;;
esac
}
function check_supported_device() {
if [[ -n "${DEVICE}" ]]; then # Device flag was provided
DEV_CONFIG="${SRC}/recipes/devices/${DEVICE}.sh"
if [[ ! -f "${DEV_CONFIG}" ]]; then
log "No configuration found for <${DEVICE}>" "err"
log "Build system currently supports ${#DEVICE_LIST[@]} devices:" "${DEVICE_LIST[*]}"
exit 1
fi
elif [[ -n "${BUILD}" ]]; then # Build flag with no Device
log "No device flag passed to builder, building only ${BASE}" "wrn"
else
log "No Base or Device flag found.." "wrn"
HELP
fi
}
#Check the number of arguments. If none are passed, print help and exit.
[[ "$#" -eq 0 ]] && HELP
while getopts b:v:d:p:t:h: FLAG; do
case ${FLAG} in
b)
BUILD=${OPTARG}
;;
d)
DEVICE=${OPTARG}
;;
v)
VERSION=${OPTARG}
;;
p)
PATCH=${OPTARG}
;;
h) #show help
HELP
;;
t)
VARIANT=${OPTARG}
;;
\?) #unrecognized option - show help
echo -e \\n"Option -${bold}${OPTARG}${normal} not allowed."
HELP
;;
esac
done
# move past our parsed args
shift $((OPTIND - 1))
check_supported_device
log "Checking whether we are running as root"
if [[ "$(id -u)" -ne 0 ]]; then
log "Please run the build script as root" "err"
exit 1
fi
start=$(date +%s)
## Setup logging and dirs
# Look at buildoptions for default locations
#TODO: make this smarter.
LOG_DIR="${OUTPUT_DIR}/debug_$(date +%Y-%m-%d_%H-%M-%S)"
if [[ -z "${SUITE}" ]]; then
SUITE="buster"
log "Defaulting to release" "" "${SUITE^}"
fi
if [[ -n ${BUILD} ]]; then
log "Creating log directory"
mkdir -p "${LOG_DIR}"
# But it's annoying if root needs to delete it, soo
chmod -R 777 "${LOG_DIR}"/
fi
if [[ -z "${VARIANT}" ]]; then
VARIANT="volumio"
log "Setting default variant" "" "${VARIANT}"
fi
if [[ -n "${BUILD}" ]]; then
log "Creating ${BUILD} rootfs" "info"
#TODO Check naming conventions!
BASE="Debian"
MULTISTRAPCONF=${BUILD}
case "${BUILD}" in
arm)
ARCH="armhf"
BASE="Raspbian"
patch_multistrap_conf "${BUILD}"
;;
armv7)
ARCH="armhf"
;;
armv8)
ARCH="arm64"
;;
x64)
ARCH="amd64"
patch_multistrap_conf "${BUILD}"
MULTISTRAPCONF=x86
;;
*)
log "Unsupported build" "wrn" "${BUILD}"
;;
esac
CONF="${SRC}/recipes/base/${MULTISTRAPCONF}.conf"
if [[ ! -f ${CONF} ]]; then
log "No base system configuration file found" "wrn" "$(basename "${CONF}")"
exit 1
fi
# Setup build directory
BUILD_DIR=${BUILD_OUTPUT_DIR}/${SUITE}/${BUILD}
rootfs_tarball=${BUILD_DIR}_rootfs
if [[ -d "${BUILD_DIR}" ]]; then
log "${BUILD} rootfs exists, cleaning it" "wrn" "${BUILD_DIR}"
rm -rf "${BUILD_DIR}"
fi
ROOTFS="${BUILD_DIR}/root"
mkdir -p "${ROOTFS}"
setup_multistrap
log "Building ${BASE} System for ${BUILD} (${ARCH})" "info"
log "Creating rootfs in <${BUILD_DIR}>"
#### Build stage 0 - Multistrap
log "Running multistrap for ${BUILD} (${ARCH})" "" "${CONF##*/}"
multistrap -a "${ARCH}" -d "${ROOTFS}" -f "${CONF}" --simulate >"${LOG_DIR}/multistrap_packages.log"
# shellcheck disable=SC2069
if ! multistrap -a "${ARCH}" -d "${ROOTFS}" -f "${CONF}" 2>&1 >"${LOG_DIR}/multistrap.log"; then # if ! { multistrap -a "${ARCH}" -f "${CONF}" > /dev/null; } 2>&1
log "Multistrap failed. Exiting" "err"
exit 1
else
end_multistrap=$(date +%s)
time_it "${end_multistrap}" "${start}"
# Clean up multistrap
# Incase multistrap's list are left over
if compgen -G "${ROOTFS}/etc/apt/sources.list.d/multistrap-*.list" >/dev/null; then
log "Removing multistrap-*.list" "wrn"
rm "${ROOTFS}"/etc/apt/sources.list.d/multistrap-*.list
fi
[[ -n ${RASPBIANCONF} ]] && [[ -e "${SRC}/${RASPBIANCONF}" ]] && rm "${SRC}/${RASPBIANCONF}"
log "Finished setting up Multistrap rootfs" "okay" "${TIME_STR}"
fi
log "Preparing rootfs before chroot" "info"
# shellcheck source=./scripts/rootfs/prepare.sh
source "${SRC}/scripts/rootfs/prepare.sh"
log "Preparing for Volumio chroot configuration" "info"
start_chroot=$(date +%s)
cp scripts/helpers.sh "${ROOTFS}"
cp scripts/rootfs/volumioconfig.sh "${ROOTFS}"
mount_chroot "${ROOTFS}"
fetch_volumio_from_repo
#TODO: We set a lot of things here that are then copied in later,
# restructure this!
log "Configuring Volumio" "info"
chroot "${ROOTFS}" /volumioconfig.sh
# Copy the dpkg log
mv "${ROOTFS}/dpkg.log" "${LOG_DIR}/dpkg.log"
CUR_DATE=$(date)
# Write some Version information
log "Writing system information"
cat <<-EOF >>"${ROOTFS}"/etc/os-release
VOLUMIO_VARIANT="${VARIANT}"
VOLUMIO_TEST="FALSE"
VOLUMIO_BUILD_DATE="${CUR_DATE}"
EOF
unmount_chroot "${ROOTFS}"
end_chroot=$(date +%s)
time_it "${end_chroot}" "${start_chroot}"
log "Base rootfs Installed" "okay" "${TIME_STR}"
rm -f "${ROOTFS}/volumioconfig.sh"
log "Running Volumio configuration script on rootfs" "info"
# shellcheck source=./scripts/rootfs/configure.sh
source "${SRC}/scripts/rootfs/configure.sh"
log "Volumio rootfs created" "okay"
# Bundle up the base rootfs
log "Creating base system rootfs tarball"
# https://superuser.com/questions/168749/is-there-a-way-to-see-any-tar-progress-per-file/665181#665181
tar cp --xattrs --directory="${ROOTFS}" \
--exclude='./dev/*' --exclude='./proc/*' \
--exclude='./run/*' --exclude='./tmp/*' \
--exclude='./sys/*' . |
pv -p -b -r -s "$(du -sb "${BUILD_DIR}" | cut -f1)" -N "${rootfs_tarball}" | lz4 -c >"${rootfs_tarball}.lz4"
log "Created ${BUILD}_rootfs.lz4" "okay"
else
use_rootfs_tarball=yes
fi
#### Build stage 1 - Device specific image creation
if [[ -n "${DEVICE}" ]]; then
# shellcheck source=/dev/null
source "${DEV_CONFIG}"
log "Preparing an image for ${DEVICE} using ${BASE} - ${BUILD}"
# Parse build directory
BUILD_DIR=${BUILD_OUTPUT_DIR}/${SUITE}/${BUILD}
rootfs_tarball=${BUILD_DIR}_rootfs
if [[ ${use_rootfs_tarball} == yes ]]; then
log "Trying to use prior base system" "info"
if [[ -d ${BUILD_DIR} ]]; then
log "Prior ${BUILD} rootfs dir found!" "dbg" "$(date -r "${BUILD_DIR}" "+%m-%d-%Y %H:%M:%S")"
[[ ${CLEAN_ROOTFS:-yes} == yes ]] &&
log "Cleaning prior rootfs directory" "wrn" && rm -rf "${BUILD_DIR}"
fi
[[ ! -f ${rootfs_tarball}.lz4 ]] && log "Couldn't find prior base system!" "err" && exit 1
log "Using prior Base tarball" "$(date -r "${rootfs_tarball}.lz4" "+%m-%d-%Y %H:%M:%S")"
mkdir -p "${BUILD_DIR}/root"
pv -p -b -r -c -N "[ .... ] ${rootfs_tarball}" "${rootfs_tarball}.lz4" |
lz4 -dc |
tar xp --xattrs -C "${BUILD_DIR}/root"
fi
ROOTFS="${BUILD_DIR}/root"
## Add in our version details
check_os_release
# Patching for advanved Volumio builds
if [[ -n "${PATCH}" ]]; then
log "Copying Patch ${SDK_PATH-.}/${PATCH} to Rootfs"
cp -rp "${SDK_PATH-.}/${PATCH}" "${ROOTFS}/"
else
log "No patches found, defaulting to Volumio rootfs"
PATCH='volumio'
fi
## Testing and debugging
if [[ ${USE_BUILD_TESTS} == yes ]]; then
log "Running Tests for ${BUILD}"
if [[ -d "${SRC}/tests" ]]; then
mkdir -p "${ROOTFS}/tests"
for file in "${SRC}"/tests/*.sh; do
cp "${file}" "${ROOTFS}"/tests/
done
mount_chroot "${ROOTFS}"
for file in "${ROOTFS}"/tests/*.sh; do
chroot "${ROOTFS}" /tests/"$(basename "${file}")"
done
unmount_chroot "${ROOTFS}"
log "Done, exiting"
exit 0
fi
fi
## Update the FE/BE
log "Checking upstream status of Volumio Node BE" "info"
REPO_URL=${VOL_BE_REPO/github.com/api.github.com\/repos}
REPO_URL="${REPO_URL%.*}/branches/${VOL_BE_REPO_BRANCH}"
GIT_STATUS=$(curl --silent "${REPO_URL}")
readarray -t COMMIT_DETAILS <<<"$(jq -r '.commit.sha, .commit.commit.message' <<<"${GIT_STATUS}")"
log "Upstream Volumio BE details" "dbg" "${COMMIT_DETAILS[0]:0:8} ${COMMIT_DETAILS[1]}"
[[ ! "$(git --git-dir "${ROOTFS}/volumio/.git" rev-parse HEAD)" == "${COMMIT_DETAILS[0]}" ]] && log "Rootfs git is not in sync with upstream repo!" "wrn"
# Update only if we are using a prior rootfs -- if we just built one, it should already be up to spec
if [[ ${use_rootfs_tarball} == yes ]] && [[ ${UPDATE_VOLUMIO:-yes} == yes ]]; then
log "Updating Volumio Node BE/FE"
fetch_volumio_from_repo
else
log "Using base tarball's Volumio Node BE/FE" "info" "$(git --git-dir "${ROOTFS}/volumio/.git" log --oneline -1)"
fi
## Copy modules/packages
# TODO: Streamline node versioning!
# Major version modules tarballs should be sufficient.
IFS=\. read -ra NODE_SEMVER <<<"${NODE_VERSION}"
log "Adding custom Packages and Modules" "info"
if [[ ${USE_LOCAL_NODE_MODULES} == yes ]]; then
log "Extracting node_modules for Node v${NODE_VERSION}"
tar xf "${LOCAL_MODULES_DIR}/node_modules_${BUILD}"_v${NODE_VERSION%%.*}.*.tar.xz -C "${ROOTFS}/volumio"
ls "${ROOTFS}/volumio/node_modules"
else
# Current Volumio repo knows only {arm|x86} which is conveniently the same length
# TODO: Consolidate the naming scheme for node modules - %{BUILD}-v${NODE_VERSION}.tar.xz
log "Attempting to fetch node_modules for ${NODE_VERSION} -- ${NODE_SEMVER[*]}"
modules_url="${NODE_MODULES_REPO}/node_modules_${BUILD:0:3}-${NODE_VERSION}.tar.gz"
log "Fetching node_modules from ${modules_url}"
curl -L "${modules_url}" | tar xz -C "${ROOTFS}/volumio" || log "Failed fetching node modules!!" "err"
fi
## Copy custom packages for Volumio
# Default dir is ./customPkgs
if [[ ${USE_LOCAL_PACKAGES} == yes ]]; then
mkdir -p "${ROOTFS}"/volumio/customPkgs
log "Adding packages from dir ${LOCAL_PKG_DIR}"
[[ -d "${LOCAL_PKG_DIR}"/ ]] && cp "${LOCAL_PKG_DIR}"/*"${BUILD}".deb "${ROOTFS}"/volumio/customPkgs/
# Pi's need an armvl6 build of nodejs (for Node > v8)
#if [[ ${DEVICE} == raspberry && ${USE_NODE_ARMV6} == yes && ${NODE_SEMVER[0]} -ge 8 ]]; then
# mkdir -p "${ROOTFS}"/volumio/customNode/ && cp "${LOCAL_PKG_DIR}"/nodejs_${NODE_VERSION%%.*}*-1unofficial_armv6l.deb "$_"
# log "Added custom Node binary:" "" "$(ls "${ROOTFS}"/volumio/customNode)"
#fi
elif [[ ${CUSTOM_PKGS[*]} ]]; then
log "Adding customPkgs from external repo" "info"
for key in "${!CUSTOM_PKGS[@]}"; do
# TODO: Test if key is specific to BUILD or not!
url=${CUSTOM_PKGS[$key]}
[[ "${url}" != *".deb"$ ]] && url="${url}_${BUILD}.deb"
# log "Fetching ${key} from ${url}"
wget -nv "${url}" -P "${ROOTFS}/volumio/customPkgs/" || {
log "${key} wasn't successful for ${BUILD}!" "err"
exit_error ${LINENO} && exit 1
}
done
else
log "No customPkgs added!" "wrn"
fi
# shellcheck disable=SC2012
[[ -d "${ROOTFS}"/volumio/customPkgs ]] && log "Added custom packages:" "" "$(ls -b "${ROOTFS}"/volumio/customPkgs | tr '\n' ' ')"
# Install Volumio ALSA plugins
ALSA_DIR_PARENT=$(dirname "${ROOTFS}/"usr/lib/*/alsa-lib/)
for key in "${!ALSA_PLUGINS[@]}"; do
url=${ALSA_PLUGINS[$key]}${BUILD}-libasound_module_pcm_$key.so
# log "Fetching ${key} from ${url}"
wget -nv "${url}" -O "${ALSA_DIR_PARENT}/alsa-lib/libasound_module_pcm_$key.so" || {
log "${key} ALSA plugin not found for ${BUILD}!" "err"
exit_error ${LINENO} && exit 1
}
done
# Prepare Images
start_img=$(date +%s)
BUILDDATE=$(date -I)
IMG_FILE="${VARIANT^}-${VERSION}-${BUILDDATE}-${DEVICE}.img"
# shellcheck source=scripts/makeimage.sh
source "${SRC}/scripts/makeimage.sh"
end_img=$(date +%s)
time_it "${end_img}" "${start_img}"
log "Image ${IMG_FILE} Created" "okay" "${TIME_STR}"
log "Compressing image"
start_zip=$(date +%s)
ZIP_FILE="${OUTPUT_DIR}/$(basename -s .img "${IMG_FILE}").zip"
zip -j "${ZIP_FILE}" "${IMG_FILE}"*
end_zip=$(date +%s)
time_it "${end_zip}" "${start_zip}"
log "Image ${ZIP_FILE} Created [ ${yellow}${standout}$(du -h "${ZIP_FILE}" | cut -f1)${normal} ]" "okay" "${TIME_STR}"
[[ ${CLEAN_IMAGE_FILE} == yes ]] && rm "${IMG_FILE}"*
else
log "No device specified, only base rootfs created!" "wrn"
fi
end_build=$(date +%s)
time_it "${end_build}" "${start}"
log "Cleaning up rootfs.." "info" "${BUILD_DIR}"
rm -r "${BUILD_DIR:?}" || log "Couldn't clean rootfs" "wrn"
log "Volumio Builder finished: \
$([[ -n ${BUILD} ]] && echo "${yellow}BUILD=${standout}${BUILD}${normal} ")\
$([[ -n ${DEVICE} ]] && echo "${yellow}DEVICE=${standout}${DEVICE}${normal} ")\
$([[ -n ${VERSION} ]] && echo "${yellow}VERSION=${standout}${VERSION}${normal} ")\
${normal}" "okay" "${TIME_STR}"