LibreELEC.tv/scripts/create_addon
Sascha Kuehndel (InuSasha) 58b17b1a74
create_addon now also writes a summary when log writing is used.
on special wish of @cvh
2018-08-22 21:27:53 +02:00

331 lines
10 KiB
Bash
Executable File

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv)
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
. config/options ""
# usage
usage() {
cat - >&2 <<EOUSAGE
SYNOPSIS
./script/create_addon [OPTION] [addons]...
DESCRIPTION
create_addon builds one or more addons.
--show-only
output the list of packages, which are intented to build
--write-logs=[yes,no,errors]
write a log file per addon
yes - write for every addon a log (and keep it)
no - write no logs (default)
errors - only keep logs for failed addons
--log-path
path where the logs are written
default: \$BUILD/logs
--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
* offical - 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 all
build audio encoders and decoders, only
> ./script/create_addon audioencoder.* audiodecoder.*
build all, but not binary
> ./script/create_addon all -binary
EOUSAGE
exit ${1:0}
}
# functions
function find_addons() {
local _paths=""
local _filter="."
case $1 in
binary) _paths="$ROOT/packages/mediacenter/kodi-binary-addons";;
offical) _paths="$ROOT/packages/addons";;
all) _paths="$ROOT/packages $ROOT/projects/*/packages";;
*) _paths="$ROOT/packages $ROOT/projects/*/packages";
_filter="^$1$";;
esac
local _addons=$(
find $_paths -name 'package.mk' \
`# select packages with PKG_IS_ADDON (can yes, no or unset at this moment)` \
| xargs grep -l 'PKG_IS_ADDON' \
`# extract package name from path` \
| sed 's|^.*/\([^/]*\)/package.mk$|\1|g' \
`# filter package list against the given filter` \
| grep -e "$_filter" \
`# make entries unique` \
| sort -u \
`# select packages with PKG_IS_ADDON=yes (slow, but is a short list, now)` \
| xargs -n1 -I{} /bin/bash -c '. ./config/options {} &>/dev/null; [ "$PKG_IS_ADDON" = "yes" ] && echo $PKG_NAME'
)
# check if anything is found
local _count=$(wc -w <<< $_addons)
if [ $_count -eq 0 ]; then
# handle embedded addons here. Should only build when they are explictly specified in the addon list
( . ./config/options "$1" &>/dev/null
[ "$PKG_IS_ADDON" != "embedded" -a "$PKG_IS_ADDON" != "yes" ] && exit 1
echo $PKG_NAME
)
# abort when nothing found and not embedded
if [ $? -ne 0 ]; then
printf "$(print_color CLR_ERROR "ERROR: '$1' matches nothing...")\n" ' '>&$SILENT_OUT
printf "for more informations type: ./scripts/create_addon --help\n" ' '>&$SILENT_OUT
exit 1
fi
fi
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
printf "%${BUILD_INDENT}c $(print_color CLR_WARNING "*** WARNING: $PKG_ADDON_ID-$ADDONVER.zip already exists. not overwriting it ***")\n" ' '>&$SILENT_OUT
return 0
fi
fi
cd $ADDON_BUILD
printf "%${BUILD_INDENT}c $(print_color CLR_INFO "*** compressing Addon $PKG_ADDON_ID ... ***")\n" ' '>&$SILENT_OUT
$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
)
printf "%${BUILD_INDENT}c $(print_color CLR_INFO "*** creating $ADDON_JENKINS_ADDON_NAME.zip for Jenkins complete ***")\n" ' '>&$SILENT_OUT
else
printf "%${BUILD_INDENT}c $(print_color CLR_INFO "*** creating $PKG_ADDON_ID complete ***")\n" ' '>&$SILENT_OUT
fi
fi
}
not_supported_arch() {
printf "%${BUILD_INDENT}c $(print_color CLR_WARNING "*** SKIP: $PKG_ADDON_ID: '${DEVICE:-$PROJECT}' not supported ***")\n" ' '>&$SILENT_OUT
exit 0
}
not_supported_device() {
printf "%${BUILD_INDENT}c $(print_color CLR_WARNING "*** SKIP: $PKG_ADDON_ID: '$TARGET_ARCH' not supported ***")\n" ' '>&$SILENT_OUT
exit 0
}
# build addon function
build_addon() {
# addon build
. config/options $1
# check support
if [ -n "$PKG_ARCH" ]; then
listcontains "$PKG_ARCH" "!$TARGET_ARCH" && not_supported_arch
listcontains "$PKG_ARCH" "$TARGET_ARCH" || listcontains "$PKG_ARCH" "any" || not_supported_arch
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
not_supported_device
fi
if ! listcontains "$PKG_ADDON_PROJECTS" "${_DEVICE:-$PROJECT}" &&
! listcontains "$PKG_ADDON_PROJECTS" "${PROJECT}" &&
! listcontains "$PKG_ADDON_PROJECTS" "any"; then
not_supported_device
fi
fi
# build addon
$SCRIPTS/build $1
# cleanup old install path
rm -rf $ADDON_BUILD
# install addon parts
if [ "$(type -t addon)" = "function" ]; then
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
PKG_ADDON_ID=$_ADDON
pack_addon
done
else
pack_addon
fi
}
# need parameter
if [ $# -eq 0 ]; then
usage 1
fi
# collect list of addons for building
addons=""
addons_drop=""
show_only="false"
write_logs="no"
log_path="$BUILD/logs"
summary_file="/dev/null"
export BUILD_INDENT=$((${BUILD_INDENT:-1}+$BUILD_INDENT_SIZE))
# read addons from parameter list
while [ $# -gt 0 ]; do
case $1 in
--help) usage 0;;
--show-only) show_only="true";;
--write-logs=*) write_logs="${1:13}";;
--log-path=*) log_path="${1:11}";;
--*) usage 1;;
-*) addons_drop+=" $(find_addons ${1:1})";;
*) addons+=" $(find_addons $1)";;
esac
shift
done
# check log parameter
case "$write_logs" in
no) log_path=""
remove_success_logs="false";;
yes) remove_success_logs="false";;
errors) remove_success_logs="true";;
*) usage 1
esac
if [ -n "$log_path" ]; then
mkdir -p "$log_path"
summary_file="$log_path/addon-summary.log"
rm -f $summary_file
fi
# check environment and create toolchain
$SCRIPTS/checkdeps
setup_toolchain target
# build addons, by calling function build_addon with one addon, after another
# (do not abort on build failure)
addons_failed=""
set +e
_count=''
for addon in $(tr " " "\n" <<< $addons | sort -u); do
# no build, when addon is in drop list / should not build
if listcontains "$addons_drop" "$addon"; then
continue
fi
# show-only: print name and continue with next addon
if [ "$show_only" = "true" ]; then
echo $addon
continue
fi
# define log file
log_file=/dev/null
if [ -n "$log_path" ]; then
log_file="$log_path/$addon.log"
fi
# build package
printf "$(print_color CLR_BUILD "CREATE ADDON $addon") (${DEVICE:-$PROJECT}/$TARGET_ARCH)\n" ' '>&$SILENT_OUT
_count+='x'
( build_addon $addon ) \
2>&1 | tee $log_file
if [ ${PIPESTATUS[0]} != 0 ]; then
addons_failed+="$addon "
printf "$(print_color CLR_ERROR "ADDON FAILED $addon")\n" ' '>&$SILENT_OUT
echo "failed: ${addon}" >> $summary_file
else
if [ "$remove_success_logs" = "true" ]; then
rm -f $log_file
fi
echo "success: ${addon}" >> $summary_file
fi
done
# show-only has no summary, can exit here
if [ "$show_only" = "true" ]; then
exit 0
fi
# print summary
if [ "$_count" != 'x' ]; then
if [ -z "$addons_failed" ]; then
printf "$(print_color CLR_INFO "ALL ADDONS BUILDS SUCCESSFUL")\n"
exit 0
else
printf "$(print_color CLR_ERROR "FAILED ADDONS: $addons_failed")\n"
exit 1
fi
fi