Last active
May 29, 2018 22:37
-
-
Save MilhouseVH/ac7e46e3c4174b35a1f6a8029775d06e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setup_toolchain() { | |
if [ "$LTO_SUPPORT" = "yes" ]; then | |
if flag_enabled "lto-fat" "no"; then | |
TARGET_CFLAGS+=" $CFLAGS_OPTIM_LTO" | |
TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_LTO" | |
if flag_enabled "lto-parallel" "no"; then | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO_PARALLEL" | |
else | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO" | |
fi | |
elif flag_enabled "lto-thin" "no"; then | |
TARGET_CFLAGS+=" $CFLAGS_OPTIM_LTO_NO_FAT" | |
TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_LTO_NO_FAT" | |
if flag_enabled "lto-parallel" "no"; then | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO_PARALLEL" | |
else | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO" | |
fi | |
fi | |
fi | |
# gold flag | |
if flag_enabled "gold" "$GOLD_SUPPORT" "only-disable"; then | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_GOLD" | |
fi | |
# position-independent code | |
if flag_enabled "pic" "no"; then | |
TARGET_CFLAGS+=" $CFLAGS_OPTIM_PIC" | |
TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_PIC" | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_PIC" | |
fi | |
if flag_enabled "pic:host" "no"; then | |
HOST_CFLAGS+=" $CFLAGS_OPTIM_PIC" | |
HOST_CXXFLAGS+=" $CXXFLAGS_OPTIM_PIC" | |
HOST_LDFLAGS+=" $LDFLAGS_OPTIM_PIC" | |
fi | |
# hardening support | |
if flag_enabled "hardening" "$HARDENING_SUPPORT"; then | |
TARGET_CFLAGS+=" $CFLAGS_OPTIM_HARDENING" | |
TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_HARDENING" | |
TARGET_CFLAGS+=" $CPPFLAGS_OPTIM_HARDENING" | |
TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_HARDENING" | |
fi | |
# parallel | |
if ! flag_enabled "parallel" "yes"; then | |
NINJA_OPTS="$NINJA_OPTS -j1" | |
export MAKEFLAGS="-j1" | |
else | |
export MAKEFLAGS="-j$CONCURRENCY_MAKE_LEVEL" | |
fi | |
case "$1" in | |
target|init) | |
export DESTIMAGE="target" | |
export CC="${TARGET_PREFIX}gcc" | |
export CXX="${TARGET_PREFIX}g++" | |
export CPP="${TARGET_PREFIX}cpp" | |
export LD="${TARGET_PREFIX}ld" | |
export AS="${TARGET_PREFIX}as" | |
export AR="${TARGET_PREFIX}ar" | |
export NM="${TARGET_PREFIX}nm" | |
export RANLIB="${TARGET_PREFIX}ranlib" | |
export OBJCOPY="${TARGET_PREFIX}objcopy" | |
export OBJDUMP="${TARGET_PREFIX}objdump" | |
export STRIP="${TARGET_PREFIX}strip" | |
export CPPFLAGS="$TARGET_CPPFLAGS" | |
export CFLAGS="$TARGET_CFLAGS" | |
export CXXFLAGS="$TARGET_CXXFLAGS" | |
export LDFLAGS="$TARGET_LDFLAGS" | |
export PKG_CONFIG="$TOOLCHAIN/bin/pkg-config" | |
export PKG_CONFIG_PATH="" | |
export PKG_CONFIG_LIBDIR="$SYSROOT_PREFIX/usr/lib/pkgconfig:$SYSROOT_PREFIX/usr/share/pkgconfig" | |
export PKG_CONFIG_SYSROOT_DIR="$SYSROOT_PREFIX" | |
export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 | |
export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 | |
export CMAKE_CONF=$TOOLCHAIN/etc/cmake-$TARGET_NAME.conf | |
export CMAKE="cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_CONF -DCMAKE_INSTALL_PREFIX=/usr" | |
if [ ! -f $CMAKE_CONF ] ; then | |
mkdir -p $TOOLCHAIN/etc | |
echo "SET(CMAKE_SYSTEM_NAME Linux)" >> $CMAKE_CONF | |
echo "SET(CMAKE_SYSTEM_VERSION 1)" >> $CMAKE_CONF | |
echo "SET(CMAKE_SYSTEM_PROCESSOR $TARGET_ARCH)" >> $CMAKE_CONF | |
echo "SET(CMAKE_C_COMPILER $CC)" >> $CMAKE_CONF | |
echo "SET(CMAKE_CXX_COMPILER $CXX)" >> $CMAKE_CONF | |
echo "SET(CMAKE_CPP_COMPILER $CPP)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH $SYSROOT_PREFIX)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)" >> $CMAKE_CONF | |
fi | |
export HOST_CC="$TOOLCHAIN/bin/host-gcc" | |
export HOST_CXX="$TOOLCHAIN/bin/host-g++" | |
export HOSTCC="$HOST_CC" | |
export HOSTCXX="$HOST_CXX" | |
export CC_FOR_BUILD="$HOST_CC" | |
export CXX_FOR_BUILD="$HOST_CXX" | |
export BUILD_CC="$HOST_CC" | |
export BUILD_CXX="$HOST_CXX" | |
export _python_sysroot="$SYSROOT_PREFIX" | |
export _python_prefix=/usr | |
export _python_exec_prefix=/usr | |
;; | |
host|bootstrap) | |
export DESTIMAGE="host" | |
export AWK="gawk" | |
export CC="$TOOLCHAIN/bin/host-gcc" | |
export CXX="$TOOLCHAIN/bin/host-g++" | |
export CPP="cpp" | |
export LD="ld" | |
export AS="as" | |
export AR="ar" | |
export NM="nm" | |
export RANLIB="ranlib" | |
export OBJCOPY="objcopy" | |
export OBJDUMP="objdump" | |
export STRIP="strip" | |
export CPPFLAGS="$HOST_CPPFLAGS" | |
export CFLAGS="$HOST_CFLAGS" | |
export CXXFLAGS="$HOST_CXXFLAGS" | |
export LDFLAGS="$HOST_LDFLAGS" | |
export PKG_CONFIG="$TOOLCHAIN/bin/pkg-config" | |
export PKG_CONFIG_PATH="" | |
export PKG_CONFIG_LIBDIR="$TOOLCHAIN/lib/pkgconfig:$TOOLCHAIN/share/pkgconfig" | |
export PKG_CONFIG_SYSROOT_DIR="" | |
unset PKG_CONFIG_ALLOW_SYSTEM_CFLAGS | |
unset PKG_CONFIG_ALLOW_SYSTEM_LIBS | |
export CMAKE_CONF=$TOOLCHAIN/etc/cmake-$HOST_NAME.conf | |
export CMAKE="cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_CONF -DCMAKE_INSTALL_PREFIX=$TOOLCHAIN" | |
if [ ! -f $CMAKE_CONF ] ; then | |
mkdir -p $TOOLCHAIN/etc | |
echo "SET(CMAKE_SYSTEM_NAME Linux)" >> $CMAKE_CONF | |
echo "SET(CMAKE_SYSTEM_VERSION 1)" >> $CMAKE_CONF | |
echo "SET(CMAKE_C_COMPILER $CC)" >> $CMAKE_CONF | |
echo "SET(CMAKE_CXX_COMPILER $CXX)" >> $CMAKE_CONF | |
echo "SET(CMAKE_CPP_COMPILER $CXX)" >> $CMAKE_CONF | |
echo "SET(CMAKE_AR $AR CACHE FILEPATH "Archiver")" >> $CMAKE_CONF # hum? | |
echo "SET(CMAKE_FIND_ROOT_PATH $TOOLCHAIN)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)" >> $CMAKE_CONF | |
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)" >> $CMAKE_CONF | |
fi | |
export HOST_CC="$CC" | |
export HOST_CXX="$CXX" | |
export HOSTCC="$CC" | |
export HOSTCXX="$CXX" | |
export CC_FOR_BUILD="$CC" | |
export CXX_FOR_BUILD="$CXX" | |
export BUILD_CC="$CC" | |
export BUILD_CXX="$CXX" | |
export _python_sysroot="$TOOLCHAIN" | |
export _python_prefix=/ | |
export _python_exec_prefix=/ | |
;; | |
esac | |
} | |
create_meson_conf() { | |
local endian root | |
case "$1" in | |
target|init) endian="little" | |
root="$SYSROOT_PREFIX/usr" | |
;; | |
host|bootstrap) endian="big" | |
root="$TOOLCHAIN" | |
;; | |
esac | |
cat > $2 <<EOF | |
[binaries] | |
c = '$CC' | |
cpp = '$CXX' | |
ar = '$AR' | |
strip = '$STRIP' | |
pkgconfig = '$PKG_CONFIG' | |
[host_machine] | |
system = 'linux' | |
cpu_family = '$TARGET_ARCH' | |
cpu = '$TARGET_SUBARCH' | |
endian = '$endian' | |
[properties] | |
root = '$root' | |
$(python -c "import os; print('c_args = {}'.format([x for x in os.getenv('CFLAGS').split()]))") | |
$(python -c "import os; print('c_link_args = {}'.format([x for x in os.getenv('LDFLAGS').split()]))") | |
EOF | |
} | |
# unset all PKG_* vars apart from those exported by setup_toolchain, then set default values | |
reset_pkg_vars() { | |
local vars var | |
for var in ${!PKG_*}; do | |
if [ "${var}" = "PKG_CONFIG" ] || \ | |
[ "${var}" = "PKG_CONFIG_PATH" ] || \ | |
[ "${var}" = "PKG_CONFIG_LIBDIR" ] || \ | |
[ "${var}" = "PKG_CONFIG_SYSROOT_DIR" ] || \ | |
[ "${var}" = "PKG_CONFIG_ALLOW_SYSTEM_CFLAGS" ] || \ | |
[ "${var}" = "PKG_CONFIG_ALLOW_SYSTEM_LIBS" ]; then | |
continue | |
fi | |
vars+="${var} " | |
done | |
[ -n "${vars}" ] && unset -v ${vars} | |
PKG_VERSION="0.0invalid" | |
PKG_REV="0" | |
PKG_ARCH="any" | |
PKG_LICENSE="unknown" | |
PKG_TOOLCHAIN="auto" | |
PKG_IS_ADDON="no" | |
PKG_PYTHON_VERSION="python2.7" | |
} | |
kernel_path() { | |
get_build_dir linux | |
} | |
kernel_version() { | |
get_pkg_version linux | |
} | |
kernel_config_path() { | |
local cfg pkg_linux_dir pkg_linux_version config_name | |
# avoid infinite recursion if this is called by linux | |
if [ "$PKG_NAME" = "linux" ]; then | |
pkg_linux_version="$PKG_VERSION" | |
pkg_linux_dir="$PKG_DIR" | |
else | |
pkg_linux_version="$(get_pkg_version linux)" | |
pkg_linux_dir="$(get_pkg_directory linux)" | |
fi | |
config_name="linux.${TARGET_PATCH_ARCH:-$TARGET_ARCH}.conf" | |
for cfg in $PROJECT_DIR/$PROJECT/devices/$DEVICE/linux/$pkg_linux_version/$config_name \ | |
$PROJECT_DIR/$PROJECT/devices/$DEVICE/linux/$LINUX/$config_name \ | |
$PROJECT_DIR/$PROJECT/devices/$DEVICE/linux/$config_name \ | |
$PROJECT_DIR/$PROJECT/linux/$pkg_linux_version/$config_name \ | |
$PROJECT_DIR/$PROJECT/linux/$LINUX/$config_name \ | |
$PROJECT_DIR/$PROJECT/linux/$config_name \ | |
$pkg_linux_dir/config/$pkg_linux_version/$config_name \ | |
$pkg_linux_dir/config/$LINUX/$config_name \ | |
$pkg_linux_dir/config/$config_name \ | |
; do | |
[[ $cfg =~ /devices//linux/ ]] && continue | |
[ -f "$cfg" ] && echo "$cfg" && break | |
done | |
} | |
# get kernel module dir | |
get_module_dir() { | |
if [ -n "${_CACHED_KERNEL_MODULE_DIR}" ]; then | |
echo "${_CACHED_KERNEL_MODULE_DIR}" | |
else | |
basename $(ls -d $(get_build_dir linux)/.install_pkg/usr/lib/kernel-overlays/base/lib/modules/*) | |
fi | |
} | |
# get base path to kernel modules and firmware | |
get_kernel_overlay_dir() { | |
echo "usr/lib/kernel-overlays/${1:-base}" | |
} | |
# get full path to kernel module dir | |
# optional parameter specifies overlay level (default is base) | |
get_full_module_dir() { | |
echo "$(get_kernel_overlay_dir $1)/lib/modules/$(get_module_dir)" | |
} | |
# get full path to firmware dir | |
# optional parameter specifies overlay level (default is base) | |
get_full_firmware_dir() { | |
echo "$(get_kernel_overlay_dir $1)/lib/firmware" | |
} | |
# get package's build dir | |
get_build_dir() { | |
local _PKG_NAME="$(get_pkg_variable "$1" PKG_NAME)" _PKG_VERSION="$(get_pkg_version "$1")" | |
if [ -n "$_PKG_NAME" -a -n "$_PKG_VERSION" ]; then | |
echo $BUILD/${_PKG_NAME}-${_PKG_VERSION} | |
fi | |
} | |
get_pkg_version() { | |
get_pkg_variable "$1" PKG_VERSION | |
} | |
get_pkg_directory() { | |
local _PKG_ROOT_NAME=${1%:*} _ALL_DIRS _FOUND=0 _ANCHOR="@?+?@" _PKG_DIR _DIR | |
# Check for any available local package in preference to a global package | |
for _DIR in $(echo -e "${_CACHE_PACKAGE_LOCAL}" | grep -F "/${_PKG_ROOT_NAME}${_ANCHOR}"); do | |
_DIR="${_DIR%${_ANCHOR}}" | |
# found first, set $_PKG_DIR | |
_PKG_DIR="$_DIR" | |
# keep track of dirs with package.mk for detecting multiple folders | |
_ALL_DIRS+="${_DIR}\n" | |
_FOUND=$((_FOUND+1)) | |
done | |
# If there's no local package available, use the global package | |
if [ $_FOUND -eq 0 ]; then | |
for _DIR in $(echo -e "${_CACHE_PACKAGE_GLOBAL}" | grep -F "/${_PKG_ROOT_NAME}${_ANCHOR}"); do | |
_DIR="${_DIR%${_ANCHOR}}" | |
# found first, set $_PKG_DIR | |
_PKG_DIR="$_DIR" | |
# keep track of dirs with package.mk for detecting multiple folders | |
_ALL_DIRS+="${_DIR}\n" | |
_FOUND=$((_FOUND+1)) | |
done | |
fi | |
# _FOUND multiple packages? fail | |
if [ $_FOUND -gt 1 ]; then | |
echo "Error - multiple package folders for package ${_PKG_ROOT_NAME}:" >&2 | |
echo -e "$_ALL_DIRS" >&2 | |
exit 1 | |
fi | |
echo "$_PKG_DIR" | |
} | |
# get variable ($2) for package ($1) | |
get_pkg_variable() { | |
if [ -n "$1" -a -n "$2" ] ; then | |
cd $ROOT | |
. config/options $1 &>/dev/null | |
echo "${!2}" | |
fi | |
} | |
calculate_stamp() { | |
local stamp | |
stamp="$PKG_DIR $PROJECT_DIR/$PROJECT/patches/$PKG_NAME" | |
[ -n "$DEVICE" ] && stamp+=" $PROJECT_DIR/$PROJECT/devices/$DEVICE/patches/$PKG_NAME" | |
[ -n "$PKG_NEED_UNPACK" ] && stamp+=" $PKG_NEED_UNPACK" | |
find ${stamp} -exec sha256sum {} \; 2>/dev/null | sed "s/ ${ROOT//\//\\/}\// /" | sort | sha256sum | cut -d" " -f1 | |
} | |
# return 0 if $2 in space-separated list $1, otherwise return 1 | |
listcontains() { | |
if [ -n "$1" -a -n "$2" ]; then | |
[[ ${1} =~ (^|[[:space:]])${2}($|[[:space:]]) ]] && return 0 || return 1 | |
else | |
return 1 | |
fi | |
} | |
# remove item(s) from list. | |
# looping makes it greedy (eg. removefromlist "abc def ghi" "(abc|def)" will work). | |
listremoveitem() { | |
local data="${1}" odata tmp_array | |
if [ -n "$1" -a -n "$2" ]; then | |
while [ : ]; do | |
odata="${data}" | |
data="$(echo "${data}" | sed -E "s (^|[[:space:]])${2}($|[[:space:]]) \ g")" | |
[ "${odata}" = "${data}" ] && break | |
done | |
fi | |
# Use array word splitting to squash spaces | |
tmp_array=(${data}) | |
echo "${tmp_array[@]}" | |
} | |
# check if a flag is enabled | |
# $1: flag-name, $2: default (yes/no), $3: ingenious check (none,only-disable,only-enable) | |
# set variable PKG_[FLAG]_[HOST/TARGET]_ENABLED=(yes/no) | |
# return 0 if flag is enabled, otherwise 1 | |
flag_enabled() { | |
# make flag name upper case and replace hyphen with underscore, to use as variable name | |
local flag_name=${1^^} | |
[[ $flag_name =~ : ]] || flag_name+="_TARGET" | |
flag_name="PKG_${flag_name//[:-]/_}_ENABLED" | |
# check flag | |
if [ -n "${PKG_BUILD_FLAGS}" ] && listcontains "${PKG_BUILD_FLAGS}" "[+]?$1"; then | |
if [ "${3:none}" = "only-disable" ]; then | |
echo "ERROR: $1 can not enable via PKG_BUILD_FLAGS (found in $PKG_NAME)" | |
exit 1 | |
fi | |
declare ${flag_name}="yes" | |
return 0 | |
elif [ "$2" = "yes" ] && ! listcontains "${PKG_BUILD_FLAGS}" "-$1"; then | |
declare ${flag_name}="yes" | |
return 0 | |
else | |
if [ "${3:none}" = "only-enable" ]; then | |
echo "ERROR: $1 can not disable via PKG_BUILD_FLAGS (found in $PKG_NAME)" | |
exit 1 | |
fi | |
declare ${flag_name}="no" | |
return 1 | |
fi | |
} | |
target_has_feature() { | |
listcontains "$TARGET_FEATURES" "$1" | |
} | |
# find path for matching file or directory, searching standard directory hierarchy, using optional default | |
# if a path is located it will be set in FOUND_PATH and exit code will be 0. | |
find_path() { | |
local test_func="$1" search="$2" default="$3" | |
local dir match wildcard=0 ftype | |
# support wildcard matches | |
[[ $search =~ \* || $search =~ \? ]] && wildcard=1 | |
[ "$test_func" = "-f" ] && ftype="file" || ftype="dir" | |
for dir in $PROJECT_DIR/$PROJECT/devices/$DEVICE/packages/$PKG_NAME \ | |
$PROJECT_DIR/$PROJECT/devices/$DEVICE \ | |
$PROJECT_DIR/$PROJECT/packages/$PKG_NAME \ | |
$PROJECT_DIR/$PROJECT \ | |
$DISTRO_DIR/$DISTRO/packages/$PKG_NAME \ | |
$DISTRO_DIR/$DISTRO \ | |
$PKG_DIR \ | |
; do | |
# ignore directories with missing DEVICE or PKG_NAME components | |
[[ $dir =~ /packages/$ ]] && continue | |
[[ $dir =~ /devices/$ ]] && continue | |
[[ $dir =~ /devices//packages/$PKG_NAME$ ]] && continue | |
if [ $wildcard -eq 1 ]; then | |
ls $dir/$search 1>/dev/null 2>&1 && match="$dir/$search" && break | |
else | |
[ $test_func "$dir/$search" ] && match="$dir/$search" && break | |
fi | |
done | |
if [ -z "$match" -a -n "$default" ]; then | |
if [[ $default =~ \* || $default =~ \? ]]; then | |
ls $default 1>/dev/null 2>&1 && match="$default" | |
else | |
[ $test_func "$default" ] && match="$default" | |
fi | |
fi | |
if [ -n "$match" ]; then | |
FOUND_PATH="$match" | |
[ "${VERBOSE_FIND_PATH,,}" = "yes" ] && echo "find_path: Searching for $ftype: \"$search\", found: \"$FOUND_PATH\"" >&2 | |
return 0 | |
else | |
unset FOUND_PATH | |
[ "${VERBOSE_FIND_PATH,,}" = "yes" ] && echo "find_path: Searching for $ftype: \"$search\" - not found" >&2 | |
return 1 | |
fi | |
} | |
find_file_path() { | |
find_path -f "$1" "$2" | |
} | |
find_dir_path() { | |
find_path -d "$1" "$2" | |
} | |
set_debug_depends() { | |
local pkg dep_pkg map tmp_array mpkg bpkg kvpair | |
_DEBUG_DEPENDS_LIST="" | |
_DEBUG_PACKAGE_LIST="" | |
if [ "${DEBUG:-no}" != "no" ]; then | |
# Convert DEBUG_GROUPS into array of groups, adding "all" if required | |
declare -A debug_group_map | |
for kvpair in ${DEBUG_GROUPS}; do | |
debug_group_map+=(["${kvpair%=*}"]="${kvpair#*=}") | |
done | |
[ -z "${debug_group_map["all"]}" ] && debug_group_map+=(["all"]="all") | |
# Expand $DEBUG into $_DEBUG_PACKAGE_LIST | |
for pkg in ${DEBUG//,/ }; do | |
[ "${pkg}" = "yes" ] && pkg="${DEBUG_GROUP_YES:-all}" | |
map="${debug_group_map["${pkg}"]}" | |
[ -z "${map}" ] && map="${pkg}" | |
for mpkg in ${map//,/ }; do | |
[[ ${mpkg} =~ ^[!-] ]] && bpkg="${mpkg:1}" || bpkg="${mpkg}" | |
# Remove existing instances of this package | |
listcontains "${_DEBUG_PACKAGE_LIST}" "[!-]?${bpkg}" && _DEBUG_PACKAGE_LIST="$(listremoveitem "${_DEBUG_PACKAGE_LIST}" "[!-]?${bpkg}")" | |
# Add package | |
_DEBUG_PACKAGE_LIST+=" ${mpkg}" | |
done | |
done | |
# Use array word splitting to squash spaces | |
tmp_array=(${_DEBUG_PACKAGE_LIST}) | |
_DEBUG_PACKAGE_LIST="${tmp_array[@]}" | |
# Determine dependencies for each package | |
for pkg in ${_DEBUG_PACKAGE_LIST}; do | |
if [ "${pkg}" != "all" ] && [[ ! ${pkg} =~ ^[!-] ]]; then | |
! listcontains "${_DEBUG_DEPENDS_LIST}" "${pkg}" && _DEBUG_DEPENDS_LIST+=" ${pkg}" | |
for dep_pkg in $(get_pkg_variable ${pkg} PKG_DEPENDS_TARGET); do | |
[ "${dep_pkg}" = "toolchain" ] && continue | |
[[ ${dep_pkg} =~ ^.*:host$ ]] && continue | |
! listcontains "${_DEBUG_DEPENDS_LIST}" "${dep_pkg}" && _DEBUG_DEPENDS_LIST+=" ${dep_pkg}" | |
done | |
fi | |
done | |
tmp_array=(${_DEBUG_DEPENDS_LIST}) | |
_DEBUG_DEPENDS_LIST="${tmp_array[@]}" | |
fi | |
export _DEBUG_DEPENDS_LIST _DEBUG_PACKAGE_LIST | |
} | |
# Return 0 if building with debug is enabled for the current package (or all packages). | |
# Examples: DEBUG=yes DEBUG=all DEBUG='all,!linux' DEBUG=kodi DEBUG=kodi,samba | |
build_with_debug() { | |
if [ "${DEBUG:-no}" != "no" -a -n "${PKG_NAME}" -a -n "${_DEBUG_DEPENDS_LIST+x}" ]; then | |
# Return 1 if this package is not to be built with debug | |
listcontains "${_DEBUG_PACKAGE_LIST}" "[!-]${PKG_NAME}" && return 1 | |
# Build all packages with debug | |
listcontains "${_DEBUG_PACKAGE_LIST}" "all" && return 0 | |
# Debugging is enabled for at least one package, so enable debug in the "debug" virtual package | |
[ "${PKG_NAME}" = "debug" ] && return 0 | |
# Build addons with debug if we're building the mediacenter with debug | |
[ "${PKG_IS_ADDON}" = "yes" ] && listcontains "${_DEBUG_DEPENDS_LIST}" "${MEDIACENTER}" && return 0 | |
# Build kernel packages with debug if we're building the kernel with debug | |
[ "${PKG_IS_KERNEL_PKG}" = "yes" ] && listcontains "${_DEBUG_DEPENDS_LIST}" "linux" && return 0 | |
# Build this package with debug if it's a resolved dependency | |
listcontains "${_DEBUG_DEPENDS_LIST}" "${PKG_NAME}" && return 0 | |
fi | |
return 1 | |
} | |
install_binary_addon() { | |
local addon_id="$1" addon_so | |
mkdir -p $ADDON_BUILD/$addon_id/ | |
cp -R $PKG_BUILD/.install_pkg/usr/share/$MEDIACENTER/addons/$addon_id/* $ADDON_BUILD/$addon_id/ | |
addon_so=$(xmlstarlet sel -t -v "/addon/extension/@library_linux" $ADDON_BUILD/$addon_id/addon.xml || :) | |
if [ -n "$addon_so" ]; then | |
cp -L $PKG_BUILD/.install_pkg/usr/lib/$MEDIACENTER/addons/$addon_id/$addon_so $ADDON_BUILD/$addon_id/ | |
chmod +x $ADDON_BUILD/$addon_id/$addon_so | |
fi | |
if [ -d $PKG_BUILD/.install_pkg/usr/lib/kernel-overlays/$addon_id ] ; then | |
mkdir -p $ADDON_BUILD/$addon_id/kernel-overlay | |
cp -PR $PKG_BUILD/.install_pkg/usr/lib/kernel-overlays/$addon_id/* $ADDON_BUILD/$addon_id/kernel-overlay | |
fi | |
} | |
install_addon_source() { | |
if [ -d $PKG_DIR/source ]; then | |
cp -R $PKG_DIR/source/* "$1" | |
fi | |
} | |
install_addon_images() { | |
local dest_dir="$1" | |
if [ -f "$PKG_DIR/icon/icon.png" ]; then | |
mkdir -p "$dest_dir/resources" | |
cp "$PKG_DIR/icon/icon.png" "$dest_dir/resources" | |
fi | |
if [ -f "$DISTRO_DIR/$DISTRO/addons/fanart.png" ]; then | |
mkdir -p "$dest_dir/resources" | |
cp "$DISTRO_DIR/$DISTRO/addons/fanart.png" "$dest_dir/resources" | |
fi | |
} | |
create_addon_xml() { | |
local addon_xml addon_version addon_name provider_name requires requires_addonname requires_addonversion screenshots | |
addon_xml="$1/addon.xml" | |
IFS=" " | |
for i in $PKG_ADDON_REQUIRES; do | |
requires_addonname=`echo $i | cut -f1 -d ":"` | |
requires_addonversion=`echo $i | cut -f2 -d ":"` | |
requires="$requires\n <import addon=\"$requires_addonname\" version=\"$requires_addonversion\" />" | |
done | |
unset IFS | |
if [ ! -f "$addon_xml" ] ; then | |
cp $ROOT/config/addon/${PKG_ADDON_TYPE}.xml "$addon_xml" | |
addon_version=${PKG_ADDON_VERSION:-${ADDON_VERSION}.${PKG_REV}} | |
else | |
if [ ! $(which xmlstarlet) ]; then | |
echo "*** ERROR: $ADDON has addon.xml shipped, you need 'xmlstarlet' ***" | |
exit 255 | |
fi | |
addon_version="${PKG_ADDON_VERSION:-$(xmlstarlet sel -t -v "/addon/@version" "$addon_xml").$PKG_REV}" | |
xmlstarlet ed --inplace -u "/addon[@version]/@version" -v "$addon_version" "$addon_xml" | |
fi | |
if [ -f $PKG_DIR/changelog.txt ]; then | |
sed -e "/@PKG_ADDON_NEWS@/ \ | |
{ | |
r $PKG_DIR/changelog.txt | |
d | |
}" -i "$addon_xml" | |
else | |
sed -e "s|@PKG_ADDON_NEWS@||g" -i "$addon_xml" | |
fi | |
provider_name=${PKG_MAINTAINER:-"Team LibreELEC"} | |
addon_name=${PKG_ADDON_NAME:-"$PKG_NAME"} | |
for f in $PKG_DIR/source/resources/screenshot-*.{jpg,png}; do | |
if [ -f "$f" ]; then | |
screenshots+="<screenshot>resources/$(basename $f)</screenshot>\n" | |
fi | |
done | |
$SED -e "s|@PKG_ADDON_ID@|$PKG_ADDON_ID|g" \ | |
-e "s|@ADDON_NAME@|$addon_name|g" \ | |
-e "s|@ADDON_VERSION@|$addon_version|g" \ | |
-e "s|@REQUIRES@|$requires|g" \ | |
-e "s|@PKG_SHORTDESC@|$PKG_SHORTDESC|g" \ | |
-e "s|@OS_VERSION@|$OS_VERSION|g" \ | |
-e "s|@PKG_LONGDESC@|$PKG_LONGDESC|g" \ | |
-e "s|@PKG_DISCLAIMER@|$PKG_DISCLAIMER|g" \ | |
-e "s|@PROVIDER_NAME@|$provider_name|g" \ | |
-e "s|@PKG_ADDON_PROVIDES@|$PKG_ADDON_PROVIDES|g" \ | |
-e "s|@PKG_ADDON_SCREENSHOT@|$screenshots|g" \ | |
-e "s|@PKG_ADDON_BROKEN@|$PKG_ADDON_BROKEN|g" \ | |
-i "$addon_xml" | |
} | |
install_driver_addon_files() { | |
if [ "$#" -eq 0 ] ; then | |
printf "$(print_color CLR_ERROR "no module search path defined")\n" | |
exit 1 | |
fi | |
PKG_MODULE_DIR="$INSTALL/$(get_full_module_dir $PKG_ADDON_ID)/updates/$PKG_ADDON_ID" | |
PKG_ADDON_DIR="$INSTALL/usr/share/$MEDIACENTER/addons/$PKG_ADDON_ID" | |
mkdir -p $PKG_MODULE_DIR | |
find $@ -name \*.ko -exec cp {} $PKG_MODULE_DIR \; | |
find $PKG_MODULE_DIR -name \*.ko -exec ${TARGET_KERNEL_PREFIX}strip --strip-debug {} \; | |
mkdir -p $PKG_ADDON_DIR | |
cp $PKG_DIR/changelog.txt $PKG_ADDON_DIR | |
install_addon_files "$PKG_ADDON_DIR" | |
} | |
install_addon_files() { | |
install_addon_source "$1" | |
install_addon_images "$1" | |
create_addon_xml "$1" | |
} | |
tolower() { | |
echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | |
} | |
require_eglibc() { | |
if [ "$TARGET_LIBC" != eglibc ]; then | |
echo "$1 requires eglibc, aborting." | |
exit 1 | |
fi | |
} | |
add_user() { | |
# Usage: add_user "username" "password" "userid" "groupid" "description" "home" "shell" | |
mkdir -p ${INSTALL}/etc | |
touch ${INSTALL}/etc/passwd | |
if ! grep -q "^$1:" ${INSTALL}/etc/passwd; then | |
echo "$1:x:$3:$4:$5:$6:$7" >> ${INSTALL}/etc/passwd | |
fi | |
mkdir -p ${INSTALL}/usr/cache | |
touch ${INSTALL}/usr/cache/shadow | |
ln -sf /storage/.cache/shadow ${INSTALL}/etc/shadow | |
PASSWORD="$2" | |
if [ "$PASSWORD" = "x" ]; then | |
PASSWORD="*" | |
fi | |
if ! grep -q "^$1:" ${INSTALL}/usr/cache/shadow; then | |
echo "$1:$PASSWORD:::::::" >> ${INSTALL}/usr/cache/shadow | |
fi | |
} | |
add_group() { | |
# Usage: add_group "groupname" "groupid" ("members") | |
mkdir -p ${INSTALL}/etc | |
touch ${INSTALL}/etc/group | |
if [ -z "`grep "$1:" ${INSTALL}/etc/group`" ]; then | |
echo "$1:x:$2:$3" >> ${INSTALL}/etc/group | |
fi | |
} | |
do_autoreconf() { | |
export ACLOCAL_DIR=$SYSROOT_PREFIX/usr/share/aclocal | |
if [ -e "$TOOLCHAIN/bin/autoconf" ]; then | |
export AUTOCONF=$TOOLCHAIN/bin/autoconf | |
fi | |
if [ -e "$TOOLCHAIN/bin/automake" ]; then | |
export AUTOMAKE=$TOOLCHAIN/bin/automake | |
fi | |
if [ -e "$TOOLCHAIN/bin/autopoint" ]; then | |
export AUTOPOINT=$TOOLCHAIN/bin/autopoint | |
fi | |
if [ -e "$TOOLCHAIN/bin/libtoolize" ]; then | |
export LIBTOOLIZE=$TOOLCHAIN/bin/libtoolize | |
fi | |
if [ -e "$TOOLCHAIN/bin/intltoolize" ]; then | |
export INTLTOOLIZE=$TOOLCHAIN/bin/intltoolize | |
fi | |
if [ -e "$TOOLCHAIN/bin/aclocal" ]; then | |
export ACLOCAL="$TOOLCHAIN/bin/aclocal -I $ACLOCAL_DIR" | |
fi | |
if [ -e "$TOOLCHAIN/bin/autoheader" ]; then | |
export AUTOHEADER=$TOOLCHAIN/bin/autoheader | |
fi | |
if [ -e "$TOOLCHAIN/bin/libtool" ]; then | |
export LIBTOOL=$TOOLCHAIN/bin/libtool | |
fi | |
if [ -e "$TOOLCHAIN/bin/autoreconf" -a -e "$INTLTOOLIZE" ]; then | |
mkdir -p $ACLOCAL_DIR | |
if [ -e "$LIBTOOLIZE" ]; then | |
export AUTORECONF="$TOOLCHAIN/bin/autoreconf --verbose --force --install -I $ACLOCAL_DIR" | |
else | |
export AUTORECONF="$TOOLCHAIN/bin/autoreconf --verbose --force -I $ACLOCAL_DIR" | |
fi | |
$AUTORECONF $@ | |
fi | |
} | |
fix_module_depends() { | |
# modify .modinfo section in kernel module to depends on other required modules | |
local MODULE="$1" | |
local DEPENDS="$2" | |
local OLD_DEPENDS="" | |
cp ${MODULE} ${MODULE}_orig | |
$OBJDUMP -s -j .modinfo ${MODULE}_orig | awk 'BEGIN{v=0;} /Contents/ {v=1; next;} {if (v==1) print $0;}' >new.modinfo1 | |
cat new.modinfo1 | cut -c7-41 | awk '{printf($0);}' | sed 's/ //g;s/../\\\x&/g;' >new.modinfo2 | |
/bin/echo -ne `cat new.modinfo2` | tr '\000' '\n' >new.modinfo3 | |
cat new.modinfo3 | awk '/^depends=/ {next;} {print $0;}' | tr '\n' '\000' >new.modinfo | |
OLD_DEPENDS=$(awk '{FS="="} /depends=/ {print $2}' new.modinfo3) | |
[ -n "$OLD_DEPENDS" ] && DEPENDS="$OLD_DEPENDS,$DEPENDS" | |
/bin/echo -ne "depends=$DEPENDS\0" >>new.modinfo | |
$OBJCOPY --remove-section=.modinfo --add-section=.modinfo=new.modinfo --set-section-flags .modinfo=contents,alloc,load,readonly,data ${MODULE}_orig ${MODULE} | |
rm new.modinfo* | |
} | |
# Usage: enable_service <unit> [target] | |
enable_service () { | |
local unit="$1" | |
local unit_dir="/usr/lib/systemd/system" | |
local target="$2" | |
local target_dir=$INSTALL | |
[ -f "$target_dir/$unit_dir/$unit" ] || exit 1 | |
if [ -z "$target" ] ; then | |
for target in `grep '^WantedBy' $target_dir/$unit_dir/$unit | cut -f2 -d=` ; do | |
if [ -n "$target" ]; then | |
mkdir -p ${target_dir}/$unit_dir/${target}.wants | |
ln -sf ../${unit} ${target_dir}/$unit_dir/${target}.wants/ | |
fi | |
done | |
fi | |
for target in `grep '^Alias' $target_dir/$unit_dir/$unit | cut -f2 -d=` ; do | |
if [ -n "$target" ]; then | |
ln -sf ${unit} ${target_dir}/$unit_dir/${target} | |
fi | |
done | |
} | |
init_package_cache() { | |
local _ANCHOR="@?+?@" DIR | |
# If the package caches are unset, then populate them | |
if [ -z "${_CACHE_PACKAGE_LOCAL+x}" -o -z "${_CACHE_PACKAGE_GLOBAL+x}" ]; then | |
_CACHE_PACKAGE_LOCAL="" | |
_CACHE_PACKAGE_GLOBAL="" | |
# cache project/device folder for a package | |
if [ -n $DEVICE ]; then | |
for DIR in $(find $ROOT/projects/$PROJECT/devices/$DEVICE/packages -type d 2>/dev/null); do | |
[ -r "$DIR/package.mk" ] && _CACHE_PACKAGE_LOCAL+="${DIR}${_ANCHOR}\n" | |
done | |
fi | |
# cache project folder for a package | |
for DIR in $(find $ROOT/projects/$PROJECT/packages -type d 2>/dev/null); do | |
[ -r "$DIR/package.mk" ] && _CACHE_PACKAGE_LOCAL+="${DIR}${_ANCHOR}\n" | |
done | |
# cache packages folder | |
for DIR in $(find $ROOT/$PACKAGES -type d 2>/dev/null); do | |
[ -r "$DIR/package.mk" ] && _CACHE_PACKAGE_GLOBAL+="${DIR}${_ANCHOR}\n" | |
done | |
export _CACHE_PACKAGE_LOCAL _CACHE_PACKAGE_GLOBAL | |
fi | |
} | |
check_path() { | |
dashes="===========================" | |
if [ "${PWD##/usr}" != "${PWD}" ]; then | |
check_pathmessage="$check_pathmessage\n $dashes$dashes$dashes" | |
check_pathmessage="$check_pathmessage\n ERROR: You try to build inside /usr" | |
check_pathmessage="$check_pathmessage\n $dashes$dashes$dashes" | |
check_pathmessage="$check_pathmessage\n This is not supported with our buildsystem." | |
check_pathmessage="$check_pathmessage\n Please use another dir (for example your \$HOME) to build $DISTRONAME" | |
echo -e $check_pathmessage | |
exit 1 | |
fi | |
} | |
load_build_config() { | |
if [ -d "${1}" -a -f ${1}/.build.conf ]; then | |
source ${1}/.build.conf | |
return 0 | |
fi | |
return 1 | |
} | |
save_build_config() { | |
local var | |
mkdir -p ${BUILD} | |
rm -f ${BUILD}/.build.conf | |
for var in PROJECT DEVICE ARCH DEBUG BUILD_SUFFIX; do | |
echo "export ${var}=\"${!var}\"" >> ${BUILD}/.build.conf | |
done | |
} | |
check_config() { | |
dashes="===========================" | |
if [ ! -d $PROJECT_DIR/$PROJECT ]; then | |
check_project="$check_project\n $dashes$dashes$dashes" | |
check_project="$check_project\n ERROR: Project not found, use a valid project or create a new config" | |
check_project="$check_project\n $dashes$dashes$dashes" | |
check_project="$check_project\n\n Valid projects:" | |
for projects in $PROJECT_DIR/*; do | |
check_project="$check_project\n - $(basename $projects)" | |
done | |
echo -e $check_project | |
exit 1 | |
fi | |
if [ \( -z "$DEVICE" -a -d "$PROJECT_DIR/$PROJECT/devices" \) -o \( -n "$DEVICE" -a ! -d "$PROJECT_DIR/$PROJECT/devices/$DEVICE" \) ]; then | |
check_device="$check_device\n $dashes$dashes$dashes" | |
check_device="$check_device\n ERROR: You need to specify a valid device for the $PROJECT project" | |
check_device="$check_device\n $dashes$dashes$dashes" | |
check_device="$check_device\n\n Valid devices for project: $PROJECT" | |
for device in $PROJECT_DIR/$PROJECT/devices/*; do | |
check_device="$check_device\n - $(basename $device)" | |
done | |
echo -e $check_device | |
exit 1 | |
fi | |
if [ -d $PROJECT_DIR/$PROJECT/devices/$DEVICE/linux ]; then | |
linux_config_dir="$PROJECT_DIR/$PROJECT/devices/$DEVICE/linux" | |
else | |
linux_config_dir="$PROJECT_DIR/$PROJECT/linux" | |
fi | |
if [ ! -e $linux_config_dir/linux.${TARGET_PATCH_ARCH:-$TARGET_ARCH}.conf ] && | |
! ls $linux_config_dir/*/linux.${TARGET_PATCH_ARCH:-$TARGET_ARCH}.conf &>/dev/null; then | |
check_arch="$check_arch\n $dashes$dashes$dashes" | |
check_arch="$check_arch\n ERROR: Architecture not found, use a valid Architecture" | |
check_arch="$check_arch\n for your project or create a new config" | |
check_arch="$check_arch\n $dashes$dashes$dashes" | |
check_arch="$check_arch\n\n Valid Architectures for your project: $PROJECT" | |
for arch in $linux_config_dir/*.conf $linux_config_dir/*/linux.$TARGET_ARCH.conf; do | |
[[ ${arch} =~ .*\*.* ]] && continue #ignore unexpanded wildcard | |
check_arch="$check_arch\n - $(basename $arch | cut -f2 -d".")" | |
done | |
echo -e $check_arch | |
exit 1 | |
fi | |
} | |
# strip | |
debug_strip() { | |
if [ -z "${BUILD_WITH_DEBUG}" ]; then | |
echo "ERROR: debug_strip() must not be called without configuring BUILD_WITH_DEBUG" >&2 | |
exit 1 | |
fi | |
if [ "${BUILD_WITH_DEBUG}" != "yes" ]; then | |
find $* -type f -executable | xargs $STRIP 2>/dev/null || : | |
fi | |
} | |
print_color() { | |
local clr_name="$1" clr_text="$2" clr_actual | |
if [ "$DISABLE_COLORS" = "yes" ]; then | |
[ $# -eq 2 ] && echo -en "${clr_text}" | |
return 0 | |
fi | |
clr_actual="${!clr_name}" | |
# If $clr_name isn't another colour variable (boldgreen etc.), then | |
# assume it's an actual colour escape sequence. | |
# | |
# Otherwise if $clr_name isn't defined, or doesn't exist, then use | |
# standard colours. | |
# | |
if [[ -n "${clr_actual}" ]] && [[ -z "${!clr_actual}" ]]; then | |
clr_actual="${clr_name}" | |
elif [[ -z "${clr_actual}" ]] || [[ -z "${!clr_actual}" ]]; then | |
case "${clr_name}" in | |
CLR_ERROR) clr_actual="boldred";; | |
CLR_WARNING) clr_actual="boldred";; | |
CLR_WARNING_DIM) clr_actual="red";; | |
CLR_APPLY_PATCH) clr_actual="boldgreen";; | |
CLR_AUTORECONF) clr_actual="boldmagenta";; | |
CLR_BUILD) clr_actual="boldyellow";; | |
CLR_TOOLCHAIN) clr_actual="boldmagenta";; | |
CLR_CLEAN) clr_actual="boldred";; | |
CLR_FIXCONFIG) clr_actual="boldyellow";; | |
CLR_GET) clr_actual="boldcyan";; | |
CLR_INFO) clr_actual="boldgreen";; | |
CLR_INSTALL) clr_actual="boldgreen";; | |
CLR_PATCH_DESC) clr_actual="boldwhite";; | |
CLR_TARGET) clr_actual="boldwhite";; | |
CLR_UNPACK) clr_actual="boldcyan";; | |
CLR_ENDCOLOR) clr_actual="endcolor";; | |
*) clr_actual="endcolor";; | |
esac | |
fi | |
if [ $# -eq 2 ]; then | |
echo -en "${!clr_actual}${clr_text}${endcolor}" | |
else | |
echo -en "${!clr_actual}" | |
fi | |
} | |
# Use distribution functions if any | |
if [ -f "distributions/$DISTRO/config/functions" ]; then | |
. distributions/$DISTRO/config/functions | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment