mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 13:46:49 +00:00
scripts/create_addon_mt: support building/installing addons with a single plan
This commit is contained in:
parent
7bbad851d7
commit
23c6529978
@ -1216,6 +1216,7 @@ pkg_lock() {
|
|||||||
local pkg="$1" task="$2" parent_pkg="$3"
|
local pkg="$1" task="$2" parent_pkg="$3"
|
||||||
local this_job="${MTJOBID}"
|
local this_job="${MTJOBID}"
|
||||||
local lock_job lock_task lock_pkg
|
local lock_job lock_task lock_pkg
|
||||||
|
local fail_seq
|
||||||
|
|
||||||
exec 98>"${THREAD_CONTROL}/locks/${pkg}.${task}"
|
exec 98>"${THREAD_CONTROL}/locks/${pkg}.${task}"
|
||||||
if ! flock --nonblock --exclusive 98; then
|
if ! flock --nonblock --exclusive 98; then
|
||||||
@ -1229,6 +1230,23 @@ pkg_lock() {
|
|||||||
flock --exclusive 98
|
flock --exclusive 98
|
||||||
fi
|
fi
|
||||||
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"
|
echo "${this_job} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${pkg}.${task}.owner"
|
||||||
|
|
||||||
pkg_lock_status "LOCKED" "${pkg}" "${task}"
|
pkg_lock_status "LOCKED" "${pkg}" "${task}"
|
||||||
@ -1248,6 +1266,14 @@ pkg_lock_status() {
|
|||||||
echo "${line}" >>"${THREAD_CONTROL}/history"
|
echo "${line}" >>"${THREAD_CONTROL}/history"
|
||||||
|
|
||||||
[ "${DASHBOARD}" != "no" ] && update_dashboard "${status}" "${pkg}" "${task}" "${msg}"
|
[ "${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() {
|
update_dashboard() {
|
||||||
@ -1304,14 +1330,14 @@ update_dashboard() {
|
|||||||
acquire_exclusive_lock() {
|
acquire_exclusive_lock() {
|
||||||
[ "${MTWITHLOCKS}" != "yes" ] && return 0
|
[ "${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 this_job="${MTJOBID}"
|
||||||
local lock_job lock_task lock_pkg
|
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
|
if ! flock --nonblock --exclusive 96; then
|
||||||
while [ : ]; do
|
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
|
[ -n "${lock_job}" ] && break || sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -1320,7 +1346,7 @@ acquire_exclusive_lock() {
|
|||||||
flock --exclusive 96
|
flock --exclusive 96
|
||||||
fi
|
fi
|
||||||
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}"
|
pkg_lock_status "MUTEX" "${pkg}" "${task}" "mutex: ${lockfile}"
|
||||||
}
|
}
|
||||||
|
@ -53,26 +53,68 @@ export -f json_worker
|
|||||||
package_worker() {
|
package_worker() {
|
||||||
local slot=$1 job=$2 jobs=$3 args="$4"
|
local slot=$1 job=$2 jobs=$3 args="$4"
|
||||||
local task pkgname result status
|
local task pkgname result status
|
||||||
|
local addon istarget
|
||||||
. config/options ""
|
|
||||||
|
|
||||||
[ -f "${THREAD_CONTROL}/pid" ] || echo "${PARALLEL_PID}" >"${THREAD_CONTROL}/pid"
|
|
||||||
|
|
||||||
export MTJOBID=${slot} MTMAXJOBS=${jobs}
|
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
|
${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
|
flock --exclusive 95
|
||||||
|
[ ${result} -eq 0 ] && status="DONE" || status="FAIL"
|
||||||
num=$(($(cat "${THREAD_CONTROL}/progress") + 1))
|
num=$(($(cat "${THREAD_CONTROL}/progress") + 1))
|
||||||
mv "${THREAD_CONTROL}/progress" "${THREAD_CONTROL}/progress.prev"
|
mv "${THREAD_CONTROL}/progress" "${THREAD_CONTROL}/progress.prev"
|
||||||
echo ${num} >"${THREAD_CONTROL}/progress"
|
echo ${num} >"${THREAD_CONTROL}/progress"
|
||||||
printf "[%0*d/%0*d] [%-4s] %-7s %s\n" ${#jobs} ${num} ${#jobs} ${jobs} "${status}" "${task}" "${pkgname}" >&2
|
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
|
if [ ${result} -eq 0 ]; then
|
||||||
pkg_lock_status "IDLE"
|
pkg_lock_status "IDLE"
|
||||||
@ -97,7 +139,7 @@ EOF
|
|||||||
export -f package_worker
|
export -f package_worker
|
||||||
|
|
||||||
start_multithread_build() {
|
start_multithread_build() {
|
||||||
local logbuffer withlocks
|
local singlethread buildopts
|
||||||
|
|
||||||
# init thread control folder
|
# init thread control folder
|
||||||
rm -fr "${THREAD_CONTROL}"
|
rm -fr "${THREAD_CONTROL}"
|
||||||
@ -112,16 +154,19 @@ start_multithread_build() {
|
|||||||
$SCRIPTS/build parallel:host 2>&1 || die "Unable to bootstrap parallel package"
|
$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
|
# 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
|
# 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
|
if [ "${singlethread}" = "yes" -a "${ONELOG,,}" != "no" ] || [ "${ONELOG,,}" = "yes" ]; then
|
||||||
logbuffer="--ungroup"
|
buildopts+=" --ungroup"
|
||||||
else
|
else
|
||||||
mkdir -p "${THREAD_CONTROL}/logs"
|
mkdir -p "${THREAD_CONTROL}/logs"
|
||||||
logbuffer="--group --results ${THREAD_CONTROL}/logs/{#}/"
|
buildopts+=" --group --results ${THREAD_CONTROL}/logs/{#}/"
|
||||||
fi
|
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
|
# pipefail: return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
@ -130,8 +175,8 @@ start_multithread_build() {
|
|||||||
${SCRIPTS}/genbuildplan.py --no-reorder --show-wants --build ${@} > "${THREAD_CONTROL}"/plan || return
|
${SCRIPTS}/genbuildplan.py --no-reorder --show-wants --build ${@} > "${THREAD_CONTROL}"/plan || return
|
||||||
|
|
||||||
cat "${THREAD_CONTROL}"/plan | awk '{print $1 " " $2}' | \
|
cat "${THREAD_CONTROL}"/plan | awk '{print $1 " " $2}' | \
|
||||||
MTBUILDSTART=$(date +%s) MTWITHLOCKS=${withlocks} ${TOOLCHAIN}/bin/parallel \
|
MTBUILDSTART=$(date +%s) MTWITHLOCKS=yes ${TOOLCHAIN}/bin/parallel \
|
||||||
--plain --no-notice --max-procs ${THREADCOUNT} --joblog="${THREAD_CONTROL}/joblog" ${logbuffer} --halt now,fail=1 --plus \
|
--plain --no-notice --max-procs ${THREADCOUNT} --joblog="${THREAD_CONTROL}/joblog" --plus ${buildopts} \
|
||||||
package_worker {%} {#} {##} {} || return
|
package_worker {%} {#} {##} {} || return
|
||||||
|
|
||||||
set +o pipefail
|
set +o pipefail
|
||||||
|
@ -102,69 +102,6 @@ function find_addons() {
|
|||||||
echo $_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() {
|
not_supported_arch() {
|
||||||
build_msg "CLR_WARNING" "*** SKIP: ${PKG_ADDON_ID} '${TARGET_ARCH}' not supported ***"
|
build_msg "CLR_WARNING" "*** SKIP: ${PKG_ADDON_ID} '${TARGET_ARCH}' not supported ***"
|
||||||
exit 0
|
exit 0
|
||||||
@ -220,10 +157,10 @@ build_addon() {
|
|||||||
if [ -n "$MULTI_ADDONS" ] ; then
|
if [ -n "$MULTI_ADDONS" ] ; then
|
||||||
for _ADDON in $MULTI_ADDONS ; do
|
for _ADDON in $MULTI_ADDONS ; do
|
||||||
PKG_ADDON_ID=$_ADDON
|
PKG_ADDON_ID=$_ADDON
|
||||||
pack_addon
|
${SCRIPTS}/install_addon $PKG_NAME $PKG_ADDON_ID
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
pack_addon
|
${SCRIPTS}/install_addon $PKG_NAME $PKG_ADDON_ID
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
184
scripts/create_addon_mt
Executable file
184
scripts/create_addon_mt
Executable 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
|
@ -203,6 +203,14 @@ def get_build_steps(args, nodes, trigger_pkgs, built_pkgs):
|
|||||||
resolved = []
|
resolved = []
|
||||||
unresolved = []
|
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]:
|
for pkgname in [x for x in trigger_pkgs if x]:
|
||||||
if pkgname.find(":") == -1:
|
if pkgname.find(":") == -1:
|
||||||
pkgname = "%s:target" % pkgname
|
pkgname = "%s:target" % pkgname
|
||||||
@ -221,7 +229,7 @@ def get_build_steps(args, nodes, trigger_pkgs, built_pkgs):
|
|||||||
for pkg in resolved:
|
for pkg in resolved:
|
||||||
if pkg.fqname not in built_pkgs:
|
if pkg.fqname not in built_pkgs:
|
||||||
built_pkgs.append(pkg.fqname)
|
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)
|
yield(task, pkg.fqname)
|
||||||
|
|
||||||
# Reduce the complete list of packages to a map of those packages that will
|
# Reduce the complete list of packages to a map of those packages that will
|
||||||
|
@ -93,7 +93,7 @@ for directory in etc dev proc run sys tmp usr var flash storage; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Build image contents
|
# 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
|
echo "Successful build, creating image..." >&2
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
. config/options $1
|
. config/options $1
|
||||||
|
|
||||||
|
# Make sure we have a value for STRIP
|
||||||
|
setup_toolchain target
|
||||||
|
|
||||||
[ -n "$2" ] && PKG_ADDON_ID=$2
|
[ -n "$2" ] && PKG_ADDON_ID=$2
|
||||||
|
|
||||||
ADDON_DIRECTORY="$ADDON_BUILD/$PKG_ADDON_ID"
|
ADDON_DIRECTORY="$ADDON_BUILD/$PKG_ADDON_ID"
|
||||||
@ -14,3 +17,62 @@ mkdir -p "$ADDON_DIRECTORY"
|
|||||||
install_addon_files "$ADDON_DIRECTORY"
|
install_addon_files "$ADDON_DIRECTORY"
|
||||||
|
|
||||||
debug_strip "$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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user