scripts/create_addon_mt: support building/installing addons with a single plan

This commit is contained in:
MilhouseVH 2019-02-08 17:17:43 +00:00
parent 7bbad851d7
commit 23c6529978
7 changed files with 347 additions and 85 deletions

View File

@ -1216,6 +1216,7 @@ pkg_lock() {
local pkg="$1" task="$2" parent_pkg="$3"
local this_job="${MTJOBID}"
local lock_job lock_task lock_pkg
local fail_seq
exec 98>"${THREAD_CONTROL}/locks/${pkg}.${task}"
if ! flock --nonblock --exclusive 98; then
@ -1229,6 +1230,23 @@ pkg_lock() {
flock --exclusive 98
fi
fi
# As we now have the lock, if .failed still exists then a previous process must have failed
if [ -f "${THREAD_CONTROL}/locks/${pkg}.${task}.failed" ]; then
fail_seq="$(cat "${THREAD_CONTROL}/locks/${pkg}.${task}.failed")"
print_color CLR_ERROR "FAILURE: ${pkg}.${task}.failed exists, a previous dependency process has failed (seq: ${fail_seq})\n"
if [ -d "${THREAD_CONTROL}/logs" ]; then
cat <<EOF
The following logs for this failure are available:
stdout: ${THREAD_CONTROL}/logs/${fail_seq}/stdout
stderr: ${THREAD_CONTROL}/logs/${fail_seq}/stderr
EOF
fi
return 1
fi
echo "${this_job} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${pkg}.${task}.owner"
pkg_lock_status "LOCKED" "${pkg}" "${task}"
@ -1248,6 +1266,14 @@ pkg_lock_status() {
echo "${line}" >>"${THREAD_CONTROL}/history"
[ "${DASHBOARD}" != "no" ] && update_dashboard "${status}" "${pkg}" "${task}" "${msg}"
if [ "${status}" = "LOCKED" ]; then
echo "${PARALLEL_SEQ}" > "${THREAD_CONTROL}/locks/${pkg}.${task}.failed"
elif [ "${status}" = "UNLOCK" ]; then
rm "${THREAD_CONTROL}/locks/${pkg}.${task}.failed"
fi
return 0
}
update_dashboard() {
@ -1304,14 +1330,14 @@ update_dashboard() {
acquire_exclusive_lock() {
[ "${MTWITHLOCKS}" != "yes" ] && return 0
local pkg="$1" task="$2" lockfile="${3:-.global}"
local pkg="$1" task="$2" lockfile="${3:-global}"
local this_job="${MTJOBID}"
local lock_job lock_task lock_pkg
exec 96>"${THREAD_CONTROL}/locks/${lockfile}"
exec 96>"${THREAD_CONTROL}/locks/.mutex.${lockfile}"
if ! flock --nonblock --exclusive 96; then
while [ : ]; do
read -r lock_job lock_task lock_pkg <<<$(cat "${THREAD_CONTROL}/locks/${lockfile}.owner" 2>/dev/null)
read -r lock_job lock_task lock_pkg <<<$(cat "${THREAD_CONTROL}/locks/.mutex.${lockfile}.owner" 2>/dev/null)
[ -n "${lock_job}" ] && break || sleep 1
done
@ -1320,7 +1346,7 @@ acquire_exclusive_lock() {
flock --exclusive 96
fi
fi
echo "${this_job} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${lockfile}.owner"
echo "${this_job} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/.mutex.${lockfile}.owner"
pkg_lock_status "MUTEX" "${pkg}" "${task}" "mutex: ${lockfile}"
}

View File

@ -53,26 +53,68 @@ export -f json_worker
package_worker() {
local slot=$1 job=$2 jobs=$3 args="$4"
local task pkgname result status
. config/options ""
[ -f "${THREAD_CONTROL}/pid" ] || echo "${PARALLEL_PID}" >"${THREAD_CONTROL}/pid"
local addon istarget
export MTJOBID=${slot} MTMAXJOBS=${jobs}
read -r task pkgname <<<$(echo "${args}")
read -r task pkgname <<< "${args}"
. config/options "${pkgname}"
[ ! -f "${THREAD_CONTROL}/pid" ] && echo "${PARALLEL_PID}" >"${THREAD_CONTROL}/pid"
${SCRIPTS}/${task} ${pkgname} 2>&1 && result=0 || result=1
[ ${result} -eq 0 ] && status="DONE" || status="FAIL"
[[ ${pkgname} =~ :target$ || "${pkgname//:/}" = "${pkgname}" ]] && istarget="yes" || istarget="no"
if [ "${MTADDONBUILD}" = "yes" -a "${PKG_IS_ADDON}" = "yes" -a "${istarget}" = "yes" ]; then
if [ ${result} -eq 0 ]; then
(
pkg_lock "${pkgname}" "packadd"
pkg_lock_status "ACTIVE" "${pkgname}" "packadd"
# cleanup old install path
rm -rf "${ADDON_BUILD}"
# install addon parts
if pkg_call_exists addon; then
pkg_call addon
else
install_binary_addon "${PKG_ADDON_ID}"
fi
# HACK for packages that provide multiple addons like screensavers.rsxs
# addon's addon() in package.mk should take care for exporting
# MULTI_ADDONS="addon.boo1 addon.boo2 addon.boo3"
if [ -n "${MULTI_ADDONS}" ] ; then
for addon in ${MULTI_ADDONS}; do
${SCRIPTS}/install_addon "${PKG_NAME}" "${addon}"
done
else
${SCRIPTS}/install_addon "${PKG_NAME}" "${PKG_ADDON_ID}"
fi
pkg_lock_status "UNLOCK" "${pkgname}" "packadd" "packed"
) 2>&1 || result=1
fi
if [ ${result} -ne 0 ]; then
if [ -d "${THREAD_CONTROL}/logs" ]; then
echo "${PKG_NAME} ${THREAD_CONTROL}/logs/${job}/stdout" >>"${THREAD_CONTROL}/addons.failed"
else
echo "${PKG_NAME}" >>"${THREAD_CONTROL}/addons.failed"
fi
fi
fi
(
flock --exclusive 95
[ ${result} -eq 0 ] && status="DONE" || status="FAIL"
num=$(($(cat "${THREAD_CONTROL}/progress") + 1))
mv "${THREAD_CONTROL}/progress" "${THREAD_CONTROL}/progress.prev"
echo ${num} >"${THREAD_CONTROL}/progress"
printf "[%0*d/%0*d] [%-4s] %-7s %s\n" ${#jobs} ${num} ${#jobs} ${jobs} "${status}" "${task}" "${pkgname}" >&2
) 95>"${THREAD_CONTROL}/progress.lock"
) 95>"${THREAD_CONTROL}/locks/.progress"
if [ ${result} -eq 0 ]; then
pkg_lock_status "IDLE"
@ -97,7 +139,7 @@ EOF
export -f package_worker
start_multithread_build() {
local logbuffer withlocks
local singlethread buildopts
# init thread control folder
rm -fr "${THREAD_CONTROL}"
@ -112,16 +154,19 @@ start_multithread_build() {
$SCRIPTS/build parallel:host 2>&1 || die "Unable to bootstrap parallel package"
# if number of detected slots is 1 then don't bother using inter-process locks as this is a sequential build
[ $(seq 1 32 | ${TOOLCHAIN}/bin/parallel --plain --no-notice --max-procs ${THREADCOUNT} echo {%} | sort -n | tail -1) -eq 1 ] && withlocks=no || withlocks=yes
[ $(seq 1 32 | ${TOOLCHAIN}/bin/parallel --plain --no-notice --max-procs ${THREADCOUNT} echo {%} | sort -n | tail -1) -eq 1 ] && singlethread=yes || singlethread=no
# create a single log file by default if not using locks (single build process), or the builder is a masochist
if [ "${withlocks}" = "no" -a "${ONELOG,,}" != "no" ] || [ "${ONELOG,,}" = "yes" ]; then
logbuffer="--ungroup"
if [ "${singlethread}" = "yes" -a "${ONELOG,,}" != "no" ] || [ "${ONELOG,,}" = "yes" ]; then
buildopts+=" --ungroup"
else
mkdir -p "${THREAD_CONTROL}/logs"
logbuffer="--group --results ${THREAD_CONTROL}/logs/{#}/"
buildopts+=" --group --results ${THREAD_CONTROL}/logs/{#}/"
fi
# When building addons, don't halt on error - keep building all packages/addons
[ "${MTADDONBUILD}" = "yes" ] && buildopts+=" --halt never" || buildopts+=" --halt now,fail=1"
# pipefail: return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status
set -o pipefail
@ -130,8 +175,8 @@ start_multithread_build() {
${SCRIPTS}/genbuildplan.py --no-reorder --show-wants --build ${@} > "${THREAD_CONTROL}"/plan || return
cat "${THREAD_CONTROL}"/plan | awk '{print $1 " " $2}' | \
MTBUILDSTART=$(date +%s) MTWITHLOCKS=${withlocks} ${TOOLCHAIN}/bin/parallel \
--plain --no-notice --max-procs ${THREADCOUNT} --joblog="${THREAD_CONTROL}/joblog" ${logbuffer} --halt now,fail=1 --plus \
MTBUILDSTART=$(date +%s) MTWITHLOCKS=yes ${TOOLCHAIN}/bin/parallel \
--plain --no-notice --max-procs ${THREADCOUNT} --joblog="${THREAD_CONTROL}/joblog" --plus ${buildopts} \
package_worker {%} {#} {##} {} || return
set +o pipefail

View File

@ -102,69 +102,6 @@ function find_addons() {
echo $_addons
}
pack_addon() {
scripts/install_addon $PKG_NAME $PKG_ADDON_ID || exit
if [ "$2" != "-test" ] ; then
ADDON_INSTALL_DIR="$TARGET_IMG/$ADDONS/$ADDON_VERSION/${DEVICE:-$PROJECT}/$TARGET_ARCH/$PKG_ADDON_ID"
ADDONVER="$(xmlstarlet sel -t -v "/addon/@version" $ADDON_BUILD/$PKG_ADDON_ID/addon.xml)"
if [ -f $ADDON_INSTALL_DIR/$PKG_ADDON_ID-$ADDONVER.zip ]; then
if [ "$ADDON_OVERWRITE" = "yes" ]; then
rm $ADDON_INSTALL_DIR/$PKG_ADDON_ID-$ADDONVER.zip
else
build_msg "CLR_WARNING" "*** WARNING: ${PKG_ADDON_ID}-${ADDONVER}.zip already exists. Not overwrittng it. ***"
return 0
fi
fi
cd $ADDON_BUILD
build_msg "CLR_INFO" "*** compressing addon ${PKG_ADDON_ID} ... ***"
$TOOLCHAIN/bin/7za a -l -mx9 -bsp0 -bso0 -tzip $PKG_ADDON_ID-$ADDONVER.zip $PKG_ADDON_ID
cd - &>/dev/null
mkdir -p $ADDON_INSTALL_DIR
cp $ADDON_BUILD/$PKG_ADDON_ID-$ADDONVER.zip $ADDON_INSTALL_DIR
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/changelog.txt ]; then
cp $ADDON_BUILD/$PKG_ADDON_ID/changelog.txt $ADDON_INSTALL_DIR/changelog-$ADDONVER.txt
fi
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/resources/icon.png ]; then
mkdir -p $ADDON_INSTALL_DIR/resources
cp $ADDON_BUILD/$PKG_ADDON_ID/resources/icon.png $ADDON_INSTALL_DIR/resources/icon.png
fi
# workaround for kodi pvr addons
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/icon.png ]; then
cp $ADDON_BUILD/$PKG_ADDON_ID/icon.png $ADDON_INSTALL_DIR/icon.png
fi
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/resources/fanart.png ]; then
mkdir -p $ADDON_INSTALL_DIR/resources
cp $ADDON_BUILD/$PKG_ADDON_ID/resources/fanart.png $ADDON_INSTALL_DIR/resources/fanart.png
fi
for f in $ADDON_BUILD/$PKG_ADDON_ID/resources/screenshot-*.{jpg,png}; do
if [ -f "$f" ]; then
mkdir -p $ADDON_INSTALL_DIR/resources
cp $f $ADDON_INSTALL_DIR/resources
fi
done
# Jenkins add-on build
if [ "$ADDON_JENKINS" = "yes" ]; then
ADDON_JENKINS_DIR="$TARGET_IMG/jenkins"
ADDON_JENKINS_ADDON_NAME="$ADDON_VERSION-${DEVICE:-$PROJECT}-$TARGET_ARCH-$PKG_ADDON_ID-$ADDONVER"
mkdir -p "$ADDON_JENKINS_DIR"
cd $ADDON_INSTALL_DIR
$TOOLCHAIN/bin/7za a -l -mx0 -bsp0 -bso0 -tzip $ADDON_JENKINS_DIR/$ADDON_JENKINS_ADDON_NAME.zip $PKG_ADDON_ID-$ADDONVER.zip resources/
( cd $ADDON_JENKINS_DIR
sha256sum $ADDON_JENKINS_ADDON_NAME.zip > $ADDON_JENKINS_ADDON_NAME.zip.sha256
)
build_msg "CLR_INFO" "*** creating ${ADDON_JENKINS_ADDON_NAME}.zip for Jenkins complete ***"
else
build_msg "CLR_INFO" "*** creating ${PKG_ADDON_ID} complete ***"
fi
fi
}
not_supported_arch() {
build_msg "CLR_WARNING" "*** SKIP: ${PKG_ADDON_ID} '${TARGET_ARCH}' not supported ***"
exit 0
@ -220,10 +157,10 @@ build_addon() {
if [ -n "$MULTI_ADDONS" ] ; then
for _ADDON in $MULTI_ADDONS ; do
PKG_ADDON_ID=$_ADDON
pack_addon
${SCRIPTS}/install_addon $PKG_NAME $PKG_ADDON_ID
done
else
pack_addon
${SCRIPTS}/install_addon $PKG_NAME $PKG_ADDON_ID
fi
}

184
scripts/create_addon_mt Executable file
View File

@ -0,0 +1,184 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv)
. config/options ""
. config/multithread
usage() {
cat - >&2 <<EOF
SYNOPSIS
./script/create_addon_mt [OPTION] [addons]...
DESCRIPTION
create_addon builds one or more addons.
--show-only
output the list of packages, which are intented to build
--help shows this message
[addons]
list of addons to build.
The addons can identified by:
- the name of the addon
- a group name of addons
* all - all addons found under packages and project/*/packages
* official - all addons found under packages/addons
* binary - all addons found under packages/mediacenter/kodi-binary-addons
- a regex term (grep styled), the term is automatic sorounded with string begin and end (^[term]$)
addons can removed from list with a leading minus.
EXAMPLE
build all addons
> ./script/create_addon_mt all
build audio encoders and decoders, only
> ./script/create_addon_mt audioencoder.* audiodecoder.*
build all, but not binary
> ./script/create_addon_mt all -binary
EOF
exit ${1:-0}
}
# Get list of addon packages
get_addons() {
local paths filter
local pkgpath exited
local count=0 validpkg
case $1 in
binary) paths="^$ROOT/packages/mediacenter/kodi-binary-addons/";;
official) paths="^$ROOT/packages/addons/";;
all) paths="^$ROOT/packages/|^$ROOT/projects/.*/packages/";;
*) paths="^$ROOT/packages/|^$ROOT/projects/.*/packages/"; filter="$1";;
esac
exit() { exited=1; }
for pkgpath in $(cat "${_CACHE_PACKAGE_LOCAL}" "${_CACHE_PACKAGE_GLOBAL}" | grep -E "${paths}"); do
if [ -n "${filter}" ]; then
[[ ${pkgpath} =~ ^.*/${filter}@?+?@ ]] || continue
fi
exited=0
source_package "${pkgpath%%@*}/package.mk" &>/dev/null
[ ${exited} -eq 1 ] && continue
validpkg="no"
# Should only build embedded addons when they are explictly specified in the addon list
if [ "${PKG_IS_ADDON}" = "embedded" ]; then
if [ -n "${filter}" ]; then
verify_addon && validpkg="yes"
fi
elif [ "${PKG_IS_ADDON}" = "yes" ]; then
verify_addon && validpkg="yes"
fi
if [ "${validpkg}" = "yes" ]; then
echo "${PKG_NAME}"
count=$((count + 1))
fi
done
unset -f exit
if [ ${count} -eq 0 -a -n "${filter}" ]; then
echo "$(print_color CLR_ERROR "ERROR: no addons matched for filter ${filter}")" >&2
echo "For more information type: ./scripts/create_addon_mt --help" >&2
die
fi
}
# Return 0 if package is a suitable addon, 1 otherwise
verify_addon() {
[ "${PKG_ADDON_TYPE}" = "xbmc.broken" ] && return 1
if [ -n "${PKG_ARCH}" ]; then
listcontains "${PKG_ARCH}" "!${TARGET_ARCH}" && return 1
listcontains "${PKG_ARCH}" "${TARGET_ARCH}" || listcontains "${PKG_ARCH}" "any" || return 1
fi
if [ -n "${PKG_ADDON_PROJECTS}" ]; then
[ "${DEVICE}" = "RPi" ] && _DEVICE="RPi1" || _DEVICE="${DEVICE}"
if listcontains "${PKG_ADDON_PROJECTS}" "!${_DEVICE:-$PROJECT}" ||
listcontains "${PKG_ADDON_PROJECTS}" "!${PROJECT}"; then
return 1
fi
if ! listcontains "${PKG_ADDON_PROJECTS}" "${_DEVICE:-$PROJECT}" &&
! listcontains "${PKG_ADDON_PROJECTS}" "${PROJECT}" &&
! listcontains "${PKG_ADDON_PROJECTS}" "any"; then
return 1
fi
fi
return 0
}
# need parameter
if [ $# -eq 0 ]; then
usage 1
fi
# check environment and configure toolchains
${SCRIPTS}/checkdeps
(setup_toolchain host)
setup_toolchain target
# collect list of addons for building
addons=
addons_drop=
show_only="no"
# read addons from parameter list
while [ $# -gt 0 ]; do
case $1 in
--help) usage 0;;
--show-only) show_only="yes";;
--*) usage 1;;
-*) addons_drop+=" $(get_addons ${1:1})";;
*) addons+=" $(get_addons $1)";;
esac
shift
done
# Build a new list containing only those addons we want to build
wanted_addons=
for addon in $(echo ${addons} | tr ' ' '\n' | sort -u); do
listcontains "${addons_drop}" "${addon}" || wanted_addons+=" ${addon}"
done
if [ "${show_only}" = "yes" ]; then
for addon in ${wanted_addons}; do
echo ${addon}
done
exit 0
fi
# Build all addons at once using a single plan
if MTADDONBUILD=yes start_multithread_build "${wanted_addons:1}"; then
echo
echo "$(print_color CLR_INFO "ALL ADDONS BUILT SUCCESSFULLY")"
exit 0
elif [ -f "${THREAD_CONTROL}/addons.failed" ]; then
echo >&2
print_color CLR_ERROR "FAILED ADDONS:\n" >&2
while read -r addon logfile; do
if [ -n "${addon}" ]; then
if [ -n "${logfile}" ]; then
echo " $(print_color CLR_ERROR "${addon}"): ${logfile}" >&2
else
echo " $(print_color CLR_ERROR "${addon}")" >&2
fi
fi
done < "${THREAD_CONTROL}/addons.failed"
die
else
die "$(print_color CLR_ERROR "UNKNOWN BUILD FAILURE OR INABILITY TO GENERATE PLAN")"
fi

View File

@ -203,6 +203,14 @@ def get_build_steps(args, nodes, trigger_pkgs, built_pkgs):
resolved = []
unresolved = []
# When building the image the :target packages must be installed.
#
# However, if we are not building the image then only build the packages
# and don't install them as it's likely we will be building discrete add-ons
# which are installed outside of the image.
#
install = True if "image" in args.build else False
for pkgname in [x for x in trigger_pkgs if x]:
if pkgname.find(":") == -1:
pkgname = "%s:target" % pkgname
@ -221,7 +229,7 @@ def get_build_steps(args, nodes, trigger_pkgs, built_pkgs):
for pkg in resolved:
if pkg.fqname not in built_pkgs:
built_pkgs.append(pkg.fqname)
task = "build" if pkg.fqname.endswith(":host") else "install"
task = "build" if pkg.fqname.endswith(":host") or not install else "install"
yield(task, pkg.fqname)
# Reduce the complete list of packages to a map of those packages that will

View File

@ -93,7 +93,7 @@ for directory in etc dev proc run sys tmp usr var flash storage; do
done
# Build image contents
start_multithread_build image || die "Parallel build failure - see log for details. Time of failure: $(date)"
MTADDONBUILD=no start_multithread_build image || die "Parallel build failure - see log for details. Time of failure: $(date)"
echo "Successful build, creating image..." >&2

View File

@ -5,6 +5,9 @@
. config/options $1
# Make sure we have a value for STRIP
setup_toolchain target
[ -n "$2" ] && PKG_ADDON_ID=$2
ADDON_DIRECTORY="$ADDON_BUILD/$PKG_ADDON_ID"
@ -14,3 +17,62 @@ mkdir -p "$ADDON_DIRECTORY"
install_addon_files "$ADDON_DIRECTORY"
debug_strip "$ADDON_DIRECTORY"
# pack_addon()
ADDON_INSTALL_DIR="$TARGET_IMG/$ADDONS/$ADDON_VERSION/${DEVICE:-$PROJECT}/$TARGET_ARCH/$PKG_ADDON_ID"
ADDONVER="$(xmlstarlet sel -t -v "/addon/@version" $ADDON_BUILD/$PKG_ADDON_ID/addon.xml)"
if [ -f $ADDON_INSTALL_DIR/$PKG_ADDON_ID-$ADDONVER.zip ]; then
if [ "$ADDON_OVERWRITE" = "yes" ]; then
rm $ADDON_INSTALL_DIR/$PKG_ADDON_ID-$ADDONVER.zip
else
build_msg "CLR_WARNING" "*** WARNING: ${PKG_ADDON_ID}-${ADDONVER}.zip already exists. Not overwrittng it. ***"
exit 0
fi
fi
cd $ADDON_BUILD
build_msg "CLR_INFO" "*** compressing addon ${PKG_ADDON_ID} ... ***"
$TOOLCHAIN/bin/7za a -l -mx9 -bsp0 -bso0 -tzip $PKG_ADDON_ID-$ADDONVER.zip $PKG_ADDON_ID
cd - &>/dev/null
mkdir -p $ADDON_INSTALL_DIR
cp $ADDON_BUILD/$PKG_ADDON_ID-$ADDONVER.zip $ADDON_INSTALL_DIR
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/changelog.txt ]; then
cp $ADDON_BUILD/$PKG_ADDON_ID/changelog.txt $ADDON_INSTALL_DIR/changelog-$ADDONVER.txt
fi
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/resources/icon.png ]; then
mkdir -p $ADDON_INSTALL_DIR/resources
cp $ADDON_BUILD/$PKG_ADDON_ID/resources/icon.png $ADDON_INSTALL_DIR/resources/icon.png
fi
# workaround for kodi pvr addons
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/icon.png ]; then
cp $ADDON_BUILD/$PKG_ADDON_ID/icon.png $ADDON_INSTALL_DIR/icon.png
fi
if [ -f $ADDON_BUILD/$PKG_ADDON_ID/resources/fanart.png ]; then
mkdir -p $ADDON_INSTALL_DIR/resources
cp $ADDON_BUILD/$PKG_ADDON_ID/resources/fanart.png $ADDON_INSTALL_DIR/resources/fanart.png
fi
for f in $ADDON_BUILD/$PKG_ADDON_ID/resources/screenshot-*.{jpg,png}; do
if [ -f "$f" ]; then
mkdir -p $ADDON_INSTALL_DIR/resources
cp $f $ADDON_INSTALL_DIR/resources
fi
done
# Jenkins add-on build
if [ "$ADDON_JENKINS" = "yes" ]; then
ADDON_JENKINS_DIR="$TARGET_IMG/jenkins"
ADDON_JENKINS_ADDON_NAME="$ADDON_VERSION-${DEVICE:-$PROJECT}-$TARGET_ARCH-$PKG_ADDON_ID-$ADDONVER"
mkdir -p "$ADDON_JENKINS_DIR"
cd $ADDON_INSTALL_DIR
$TOOLCHAIN/bin/7za a -l -mx0 -bsp0 -bso0 -tzip $ADDON_JENKINS_DIR/$ADDON_JENKINS_ADDON_NAME.zip $PKG_ADDON_ID-$ADDONVER.zip resources/
( cd $ADDON_JENKINS_DIR
sha256sum $ADDON_JENKINS_ADDON_NAME.zip > $ADDON_JENKINS_ADDON_NAME.zip.sha256
)
build_msg "CLR_INFO" "*** creating ${ADDON_JENKINS_ADDON_NAME}.zip for Jenkins complete ***"
else
build_msg "CLR_INFO" "*** creating ${PKG_ADDON_ID} complete ***"
fi