#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) TXRED="$(tput setaf 1 bold)" TXGREEN="$(tput setaf 2 bold)" TXYELLOW="$(tput setaf 3 bold)" TXBLUE="$(tput setaf 4 bold)" TXMAGENTA="$(tput setaf 5 bold)" TXCYAN="$(tput setaf 6 bold)" TXRESET="$(tput sgr0)" TXCLR="$(tput el)" log() { local filename="$1" lc=$2 level="$3" msg="$4" data="$5" local txcolour flc colw [ "${level}" = "FAIL" ] && txcolour="${TXRED}" || txcolour="${TXYELLOW}" [[ ${filename} =~ ^\./ ]] && filename="${filename:2}" [ ${lc} -eq 0 ] && flc="---" || flc="$(printf "%03d" ${lc})" [[ ${filename} =~ packages/addons/addon-depends ]] && colw=80 || colw=50 printf "[%s] %3s: %-*s: %-25s: %s\n" "${txcolour}${level}${TXRESET}" "${flc}" ${colw} "${filename}" "${msg}" "${data}" } process_line() { local filename="$1" lc="$2" line="$3" inassign="$4" funcname="$5" local var matches assignallowed=Y if [ -n "${funcname}" -a "${funcname}" != "configure_package" -a "${inassign}" = "Y" ]; then if [[ ${line} =~ PKG_DEPENDS_.*= ]]; then log "${filename}" ${lc} "WARN" "ignored depends assign" "${funcname}() => ${line//[[:space:]]*PKG_DEPENDS_/PKG_DEPENDS_}" fi fi [ -n "${funcname}" ] && return 0 rightside="${line#*=}" for var in PKG_SHORTDESC PKG_LONGDESC PKG_IS_ADDON PKG_NEED_UNPACK PKG_SOURCE_NAME PKG_ADDON_IS_STANDALONE \ PKG_CONFIGURE_SCRIPT PKG_CMAKE_SCRIPT PKG_MESON_SCRIPT \ PKG_DIR PKG_ADDON_ID PKG_BUILD \ DESTIMAGE CC CXX CPP LD AS AR NM \ RANLIB OBJCOPY OBJDUMP STRIP \ CPPFLAGS CFLAGS CXXFLAGS LDFLAGS \ PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR PKG_CONFIG_SYSROOT_DIR PKG_CONFIG_ALLOW_SYSTEM_CFLAGS PKG_CONFIG_ALLOW_SYSTEM_LIBS \ CMAKE_CONF CMAKE \ HOST_CC HOST_CXX HOSTCC HOSTCXX \ CC_FOR_BUILD CXX_FOR_BUILD BUILD_CC BUILD_CXX \ _python_sysroot _python_prefix _python_exec_prefix \ TARGET_CONFIGURE_OPTS CMAKE_GENERATOR_NINJA TARGET_CMAKE_OPTS TARGET_MESON_OPTS \ HOST_CONFIGURE_OPTS HOST_CMAKE_OPTS HOST_MESON_OPTS \ INIT_CONFIGURE_OPTS INIT_CMAKE_OPTS INIT_MESON_OPTS \ BOOTSTRAP_CONFIGURE_OPTS BOOTSTRAP_CMAKE_OPTS BOOTSTRAP_MESON_OPTS \ ; do # After PKG_DIR, treat assigns to var as invalid [ "${var}" = "PKG_DIR" ] && assignallowed=N if [ "${assignallowed}" = "N" ]; then if [[ ${line} =~ (^|[[:space:]])${var}= ]]; then [ "${inassign}" = "N" ] && matches+=", assign to ${var}" fi fi if [[ ${line} =~ \$\{${var}} ]] || [[ ${line} =~ \$${var}[^A-Za-z0-9_] ]]; then matches+=", ref ${var}" fi if [[ ${line} =~ (^|[[:space:]])unset\ ${var}($|[[:space:]]) ]]; then matches+=", unset ${var}" fi done [ -n "${matches}" ] && log "${filename}" ${lc} "FAIL" "late binding violation" "${matches:2}" } init_target_funcs() { local f t funcs for t in target host init bootstrap; do for f in pre_build \ pre_configure configure post_configure \ pre_make make post_make \ pre_makeinstall makeinstall post_makeinstall \ ; do funcs+=" ${f}_${t}" done done echo "${funcs:1}" } check_func_name() { local filename="$1" lc="$2" line="$3" local f for f in configure_package \ pre_unpack unpack post_unpack \ pre_patch post_patch \ pre_configure \ ${TARGET_FUNCS} \ pre_install post_install \ addon \ ; do [[ ${line} =~ ^${f} ]] && return 0 done log "${filename}" ${lc} "WARN" "unknown function" "${line// *{*/}" } process_pkg() { local filename="$1" local lc=0 isassign=N funcname= fc=0 intertwined=N while IFS= read -r line; do lc=$((lc + 1)) [[ ${line} =~ ^[[:space:]]*$ ]] && continue [[ ${line} =~ ^(|[[:space:]]*)# ]] && continue if [[ "${line}" =~ ^[^#]*\(\)[[:space:]]*$ ]]; then log "${filename}" ${lc} "FAIL" "bad func - missing brace" "${line}" fi if [[ "${line}" =~ \(\)[[:space:]]*\{ ]]; then funcname="${line//(*/}" fc=$((fc+1)) check_func_name "${filename}" "${lc}" "${line}" fi if [ "${intertwined}" = "N" -a -z "${funcname}" -a ${fc} -ge 1 ]; then log "${filename}" ${lc} "WARN" "intertwined vars & funcs" "${line}" intertwined=Y fi [[ "${line}" =~ ^[[:space:]]*PKG_.*=\" ]] && isassign=Y process_line "$1" "${lc}" "${line}" "${isassign}" "${funcname}" [[ "${line}" =~ (\"$|\"[[:space:]]*$|\"[[:space:]]*#.*$) ]] && isassign=N [[ "${line}" =~ (^}|^[[:space:]]*}) ]] && funcname= done < "${filename}" # Duplicate function check while read -r count line; do [ -n "${line}" ] && log "${filename}" 0 "FAIL" "duplicate function def" "${line}" done <<< "$(grep -E ".*() {" "${filename}" | sed 's/[[:space:]]*{.*//' | sort | uniq -c | grep -v ^[[:space:]]*1[[:space:]])" } TARGET_FUNCS="$(init_target_funcs)" if [ $# -ne 0 ]; then for arg in ${@}; do for p in $(find packages projects -type f -path */${arg}/package.mk | sort); do echo -en "${TXCLR}${p}...\r" >&2 process_pkg "${p}" done done else for p in $(find packages projects -type f -name package.mk | sort); do echo -en "${TXCLR}${p}...\r" >&2 process_pkg "${p}" done fi echo -en "${TXCLR}" >&2