diff --git a/config/functions b/config/functions
index 9eb4f232e0..c0a3b8227c 100644
--- a/config/functions
+++ b/config/functions
@@ -547,7 +547,7 @@ build_with_debug() {
[ "${PKG_NAME}" = "debug" ] && return 0
# Build addons with debug if we're building the mediacenter with debug and with dependencies
- [ "${PKG_IS_ADDON}" = "yes" ] && listcontains "${_DEBUG_DEPENDS_LIST}" "${MEDIACENTER}\+" && return 0
+ [ "${PKG_IS_ADDON}" = "yes" -o "${PKG_IS_ADDON}" = "embedded" ] && listcontains "${_DEBUG_DEPENDS_LIST}" "${MEDIACENTER}\+" && return 0
# Build kernel packages with debug if we're building the kernel with debug and with dependencies
[ "${PKG_IS_KERNEL_PKG}" = "yes" ] && listcontains "${_DEBUG_DEPENDS_LIST}" "linux\+" && return 0
diff --git a/config/path b/config/path
index dc2f3e6e8b..da0b1182b5 100644
--- a/config/path
+++ b/config/path
@@ -84,7 +84,7 @@ if [ -n "$PKG_DIR" -a -r $PKG_DIR/package.mk ]; then
[ -z "$PKG_LONGDESC" ] && PKG_LONGDESC="$PKG_NAME (autogenerated)"
fi
-if [ "$PKG_IS_ADDON" = "yes" ] ; then
+if [ "$PKG_IS_ADDON" = "yes" -o "$PKG_IS_ADDON" = "embedded" ] ; then
[ -z $PKG_SECTION ] && PKG_ADDON_ID="$PKG_NAME" || PKG_ADDON_ID="${PKG_SECTION//\//.}.$PKG_NAME"
[ "$PKG_ADDON_IS_STANDALONE" != "yes" ] && PKG_NEED_UNPACK="${PKG_NEED_UNPACK} $(get_pkg_directory $MEDIACENTER)"
fi
diff --git a/packages/addons/script/driverselect/package.mk b/packages/addons/script/driverselect/package.mk
index 5547689d31..43b7ebce8d 100644
--- a/packages/addons/script/driverselect/package.mk
+++ b/packages/addons/script/driverselect/package.mk
@@ -16,7 +16,7 @@ PKG_SHORTDESC="script.program.driverselect"
PKG_LONGDESC="script.program.driverselect"
PKG_TOOLCHAIN="manual"
-PKG_IS_ADDON="yes"
+PKG_IS_ADDON="embedded"
PKG_ADDON_NAME="Driver Select"
PKG_ADDON_TYPE="xbmc.python.script"
diff --git a/packages/addons/service/slice/package.mk b/packages/addons/service/slice/package.mk
index 5c646f4557..f70f73173b 100644
--- a/packages/addons/service/slice/package.mk
+++ b/packages/addons/service/slice/package.mk
@@ -14,7 +14,7 @@ PKG_SHORTDESC="Provides the ability to change the led lights on the Slice box vi
PKG_LONGDESC="Provides the ability to change the led lights on the Slice box via Kodi actions"
PKG_TOOLCHAIN="manual"
-PKG_IS_ADDON="yes"
+PKG_IS_ADDON="embedded"
PKG_ADDON_NAME="Slice"
PKG_ADDON_PROJECTS="Slice Slice3"
PKG_ADDON_TYPE="xbmc.service"
diff --git a/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk b/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk
index 790dffdf0d..f5ec450c16 100644
--- a/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk
+++ b/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk
@@ -16,5 +16,5 @@ PKG_SHORTDESC="peripheral.joystick: Joystick support in Kodi"
PKG_LONGDESC="peripheral.joystick provides joystick support and button mapping"
PKG_BUILD_FLAGS="+lto"
-PKG_IS_ADDON="yes"
+PKG_IS_ADDON="embedded"
PKG_ADDON_TYPE="kodi.peripheral"
diff --git a/packages/readme.md b/packages/readme.md
index 0d08c63772..cd2df2efdb 100644
--- a/packages/readme.md
+++ b/packages/readme.md
@@ -66,7 +66,7 @@ Additional options used when the package builds an addon.
| Variable | Default | Required |Description |
|-------------|---------|----------|------------|
| PKG_REV | - | yes | The revision number of the addon (starts at 100). Must be placed after `PKG_VERSION`. Must be incremented for each new version else Kodi clients will not detect version change and download the updated addon. |
-| PKG_IS_ADDON | no | yes | Must be set to `yes` |
+| PKG_IS_ADDON | no | yes | Must be set to `yes`
or to `embedded` when this addon is part of the image |
| PKG_ADDON_NAME | - | yes | Proper name of the addon that is shown at the repo |
| PKG_ADDON_TYPE | - | yes | See LE/config/addon/ for other possibilities |
| PKG_ADDON_VERSION | - | no | The version of the addon, used in addon.xml |
diff --git a/scripts/create_addon b/scripts/create_addon
index 0506663da0..3479a812ce 100755
--- a/scripts/create_addon
+++ b/scripts/create_addon
@@ -2,40 +2,105 @@
# 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 $1
+. config/options ""
-if [ -z "$1" ]; then
- echo "usage: $0 package_name"
- exit 1
-fi
+# usage
+usage() {
+ cat - >&2 < ./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}
}
-if [ -n "$PKG_ADDON_PROJECTS" ]; then
- [ "${DEVICE}" = "RPi" ] && _DEVICE="RPi1" || _DEVICE="${DEVICE}"
+# 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
- if listcontains "$PKG_ADDON_PROJECTS" "!${_DEVICE:-$PROJECT}" ||
- listcontains "$PKG_ADDON_PROJECTS" "!${PROJECT}"; then
- not_supported
+ 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{} $SHELL -c '. ./config/options {} &>/dev/null; [ "$PKG_IS_ADDON" == "yes" ] && echo $PKG_NAME'
+ )
+
+ # check if anything is found
+ local _count=$(wc -w <<< $_addons)
+ if [ "$_count" == 0 ]; then
+ # handle embedded addons here. Should only build, when they explicte in the addon list
+ ( . ./config/options "$1" &>/dev/null
+ [ "$PKG_IS_ADDON" != "embedded" ] && exit 1
+ echo $PKG_NAME
+ )
+
+ # abort when nothing found and not embedded
+ if [ $? != 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
- if ! listcontains "$PKG_ADDON_PROJECTS" "${_DEVICE:-$PROJECT}" &&
- ! listcontains "$PKG_ADDON_PROJECTS" "${PROJECT}" &&
- ! listcontains "$PKG_ADDON_PROJECTS" "any"; then
- not_supported
- fi
-fi
-
-$SCRIPTS/checkdeps
+ echo $_addons
+}
pack_addon() {
scripts/install_addon $PKG_NAME $PKG_ADDON_ID || exit
@@ -48,12 +113,12 @@ pack_addon() {
if [ "$ADDON_OVERWRITE" = "yes" ]; then
rm $ADDON_INSTALL_DIR/$PKG_ADDON_ID-$ADDONVER.zip
else
- echo "*** WARNING: $PKG_ADDON_ID-$ADDONVER.zip already exists. not overwriting it ***"
+ 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
- echo "*** compressing Addon $PKG_ADDON_ID ... ***"
+ 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
@@ -93,21 +158,54 @@ pack_addon() {
( cd $ADDON_JENKINS_DIR
sha256sum $ADDON_JENKINS_ADDON_NAME.zip > $ADDON_JENKINS_ADDON_NAME.zip.sha256
)
- echo "*** creating $ADDON_JENKINS_ADDON_NAME.zip for Jenkins complete ***"
+ printf "%${BUILD_INDENT}c $(print_color CLR_INFO "*** creating $ADDON_JENKINS_ADDON_NAME.zip for Jenkins complete ***")\n" ' '>&$SILENT_OUT
fi
fi
}
-if [ "$PKG_IS_ADDON" = "yes" ] ; then
- setup_toolchain target
+not_supported_arch() {
+ printf "%${BUILD_INDENT}c $(print_color CLR_WARNING "*** ERROR: $PKG_ADDON_ID: '${DEVICE:-$PROJECT}' not supported ***")\n" ' '>&$SILENT_OUT
+ exit 0
+}
- $SCRIPTS/build $@
+not_supported_device() {
+ printf "%${BUILD_INDENT}c $(print_color CLR_WARNING "*** ERROR: $PKG_ADDON_ID: '$TARGET_ARCH' not supported ***")\n" ' '>&$SILENT_OUT
+ exit 0
+}
- printf "%${BUILD_INDENT}c CREATE ADDON (${DEVICE:-$PROJECT}/$TARGET_ARCH) $1\n" ' '>&$SILENT_OUT
- export BUILD_INDENT=$((${BUILD_INDENT:-1}+$BUILD_INDENT_SIZE))
+# 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
@@ -125,4 +223,102 @@ if [ "$PKG_IS_ADDON" = "yes" ] ; then
else
pack_addon
fi
+}
+
+# need parameter
+if [ $# == 0 ]; then
+ usage 1
+fi
+
+# collect list of addons for building
+addons=""
+addons_drop=""
+show_only="false"
+write_logs="no"
+log_path="$BUILD/logs"
+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"
+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
+ else
+ printf "$(print_color CLR_INFO "ADDON SUCCESS $addon")\n" ' '>&$SILENT_OUT
+ if [ $remove_success_logs == "true" ]; then
+ rm -f $log_file
+ fi
+ 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