kumquat-buildroot/support/scripts/br2-external
Yann E. MORIN 9ae089e2e9 br2-external: make version of external trees available
For various reasons, like debugging or compliance, it is important to
identify what br2-external trees versions were used for a specific
build.

Add a Kconfig option that contains the version as computed by
support/scripts/setlocalversion; this will appear in the .config file
(but not in defconfig files, which is what we want).

Also generate that variable on the .mk side, so that it gets properly
exported in the environment, for post-build of post-iamge scripts to use
as they see fit (like, ensuring there is no dirtyness when in a CI for
example).

Reported-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
2023-05-13 12:06:08 +02:00

279 lines
9.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -e
# This script must be able to run with bash-3.1, so it can't use
# associative arrays. Instead, it emulates them using 'eval'. It
# can however use indexed arrays, supported since at least bash-3.0.
# The names of the br2-external trees, once validated.
declare -a BR2_EXT_NAMES
# URL to manual for help in converting old br2-external trees.
# Escape '#' so that make does not consider it a comment.
MANUAL_URL='https://buildroot.org/manual.html\#br2-external-converting'
main() {
local OPT OPTARG
local br2_ext outputdir
while getopts :d: OPT; do
case "${OPT}" in
d) outputdir="${OPTARG}";;
:) error "option '%s' expects a mandatory argument\n" "${OPTARG}";;
\?) error "unknown option '%s'\n" "${OPTARG}";;
esac
done
# Forget options; keep only positional args
shift $((OPTIND-1))
if [ -z "${outputdir}" ]; then
error "no output directory specified (-d)\n"
fi
# Trap any unexpected error to generate a meaningful error message
trap "error 'unexpected error while generating ${ofile}\n'" ERR
mkdir -p "${outputdir}"
do_validate "${outputdir}" ${@//:/ }
do_mk "${outputdir}"
do_kconfig "${outputdir}"
}
# Validates the br2-external trees passed as arguments. Makes each of
# them canonical and store them in the global arrays BR2_EXT_NAMES
# and BR2_EXT_PATHS.
#
# Note: since this script is always first called from Makefile context
# to generate the Makefile fragment before it is called to generate the
# Kconfig snippet, we're sure that any error in do_validate will be
# interpreted in Makefile context. Going up to generating the Kconfig
# snippet means that there were no error.
#
do_validate() {
local outputdir="${1}"
local br2_ext
shift
if [ ${#} -eq 0 ]; then
# No br2-external tree is valid
return
fi
for br2_ext in "${@}"; do
do_validate_one "${br2_ext}"
done >"${outputdir}/.br2-external.mk"
}
do_validate_one() {
local br2_ext="${1}"
local br2_name br2_desc br2_ver n d
if [ ! -d "${br2_ext}" ]; then
error "'%s': no such file or directory\n" "${br2_ext}"
fi
if [ ! -r "${br2_ext}" -o ! -x "${br2_ext}" ]; then
error "'%s': permission denied\n" "${br2_ext}"
fi
if [ ! -f "${br2_ext}/external.desc" ]; then
error "'%s': does not have an 'external.desc'. See %s\n" \
"${br2_ext}" "${MANUAL_URL}"
fi
br2_name="$(sed -r -e '/^name: +(.*)$/!d; s//\1/' "${br2_ext}/external.desc")"
if [ -z "${br2_name}" ]; then
error "'%s/external.desc': does not define the name\n" "${br2_ext}"
fi
# Only ASCII chars in [A-Za-z0-9_] are permitted
n="$(sed -r -e 's/[A-Za-z0-9_]//g' <<<"${br2_name}" )"
if [ -n "${n}" ]; then
# Escape '$' so that it gets printed
error "'%s': name '%s' contains invalid chars: '%s'\n" \
"${br2_ext}" "${br2_name//\$/\$\$}" "${n//\$/\$\$}"
fi
eval d="\"\${BR2_EXT_PATHS_${br2_name}}\""
if [ -n "${d}" ]; then
error "'%s': name '%s' is already used in '%s'\n" \
"${br2_ext}" "${br2_name}" "${d}"
fi
br2_desc="$(sed -r -e '/^desc: +(.*)$/!d; s//\1/' "${br2_ext}/external.desc")"
if [ ! -f "${br2_ext}/external.mk" ]; then
error "'%s/external.mk': no such file or directory\n" "${br2_ext}"
fi
if [ ! -f "${br2_ext}/Config.in" ]; then
error "'%s/Config.in': no such file or directory\n" "${br2_ext}"
fi
# Register this br2-external tree, use an absolute canonical path
br2_ext="$( cd "${br2_ext}"; pwd )"
br2_ver="$( support/scripts/setlocalversion "${br2_ext}" )"
BR2_EXT_NAMES+=( "${br2_name}" )
eval BR2_EXT_PATHS_${br2_name}="\"\${br2_ext}\""
eval BR2_EXT_VERS_${br2_name}="\"\${br2_ver}\""
eval BR2_EXT_DESCS_${br2_name}="\"\${br2_desc:-\${br2_name}}\""
}
# Generate the .mk snippet that defines makefile variables
# for the br2-external tree
do_mk() {
local outputdir="${1}"
local br2_name br2_desc br2_ext br2_ver
{
printf '#\n# Automatically generated file; DO NOT EDIT.\n#\n'
printf '\n'
printf 'BR2_EXTERNAL ?='
for br2_name in "${BR2_EXT_NAMES[@]}"; do
eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
printf ' %s' "${br2_ext}"
done
printf '\n'
printf 'export BR2_EXTERNAL_NAMES = \n'
printf 'BR2_EXTERNAL_DIRS = \n'
printf 'BR2_EXTERNAL_MKS = \n'
if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
printf '\n'
printf '# No br2-external tree defined.\n'
return
fi
for br2_name in "${BR2_EXT_NAMES[@]}"; do
eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
eval br2_ver="\"\${BR2_EXT_VERS_${br2_name}}\""
printf '\n'
printf 'BR2_EXTERNAL_NAMES += %s\n' "${br2_name}"
printf 'BR2_EXTERNAL_DIRS += %s\n' "${br2_ext}"
printf 'BR2_EXTERNAL_MKS += %s/external.mk\n' "${br2_ext}"
printf 'export BR2_EXTERNAL_%s_PATH = %s\n' "${br2_name}" "${br2_ext}"
printf 'export BR2_EXTERNAL_%s_DESC = %s\n' "${br2_name}" "${br2_desc}"
printf 'export BR2_EXTERNAL_%s_VERSION = %s\n' "${br2_name}" "${br2_ver}"
done
} >"${outputdir}/.br2-external.mk"
}
# Generate the kconfig snippets for the br2-external tree.
do_kconfig() {
local outputdir="${1}"
local br2_name br2_desc br2_ext br2_ver br2
local -a items
items=(
paths
menus
toolchains
jpeg
openssl
skeleton
init
linux
)
for br2 in "${items[@]}"; do
{
printf '#\n# Automatically generated file; DO NOT EDIT.\n#\n'
printf '\n'
if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
printf '# No br2-external tree defined.\n'
fi
} >"${outputdir}/.br2-external.in.${br2}"
done
if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
return
fi
printf 'menu "External options"\n\n' >>"${outputdir}/.br2-external.in.menus"
{
printf 'config BR2_EXTERNAL_NAMES\n'
printf '\tstring\n'
# Use star-expansion: we really one a single arg.
printf '\tdefault "%s"\n' "${BR2_EXT_NAMES[*]}"
printf '\n'
} >>"${outputdir}/.br2-external.in.paths"
for br2_name in "${BR2_EXT_NAMES[@]}"; do
eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
eval br2_ver="\"\${BR2_EXT_VERS_${br2_name}}\""
{
printf 'config BR2_EXTERNAL_%s_PATH\n' "${br2_name}"
printf '\tstring\n'
printf '\tdefault "%s"\n' "${br2_ext}"
printf 'config BR2_EXTERNAL_%s_VERSION\n' "${br2_name}"
printf '\tstring\n'
printf '\tdefault "%s"\n' "${br2_ver}"
printf '\n'
} >>"${outputdir}/.br2-external.in.paths"
{
if [ ${#BR2_EXT_NAMES[@]} -gt 1 ]; then
printf 'menu "%s"\n' "${br2_desc}"
fi
printf 'comment "%s (in %s)"\n' "${br2_desc}" "${br2_ext}"
printf 'source "%s/Config.in"\n' "${br2_ext}"
if [ ${#BR2_EXT_NAMES[@]} -gt 1 ]; then
printf 'endmenu # %s\n' "${br2_name}"
fi
printf '\n'
} >>"${outputdir}/.br2-external.in.menus"
if [ -f "${br2_ext}/provides/toolchains.in" ]; then
printf 'comment "Toolchains from: %s"\n' "${br2_desc}"
printf 'source "%s/provides/toolchains.in"\n' "${br2_ext}"
printf '\n'
else
printf '# No toolchain from: %s\n\n' "${br2_desc}"
fi >>"${outputdir}/.br2-external.in.toolchains"
if [ -f "${br2_ext}/provides/jpeg.in" ]; then
printf 'comment "jpeg from: %s"\n' "${br2_desc}"
printf 'source "%s/provides/jpeg.in"\n' "${br2_ext}"
printf '\n'
else
printf '# No jpeg from: %s\n\n' "${br2_desc}"
fi >>"${outputdir}/.br2-external.in.jpeg"
if [ -f "${br2_ext}/provides/openssl.in" ]; then
printf 'comment "openssl from: %s"\n' "${br2_desc}"
printf 'source "%s/provides/openssl.in"\n' "${br2_ext}"
printf '\n'
else
printf '# No openssl from: %s\n\n' "${br2_desc}"
fi >>"${outputdir}/.br2-external.in.openssl"
if [ -f "${br2_ext}/provides/skeleton.in" ]; then
printf 'comment "skeleton from: %s"\n' "${br2_desc}"
printf 'source "%s/provides/skeleton.in"\n' "${br2_ext}"
printf '\n'
else
printf '# No skeleton from: %s\n\n' "${br2_desc}"
fi >>"${outputdir}/.br2-external.in.skeleton"
if [ -f "${br2_ext}/provides/init.in" ]; then
printf 'comment "init from: %s"\n' "${br2_desc}"
printf 'source "%s/provides/init.in"\n' "${br2_ext}"
printf '\n'
else
printf '# No init from: %s\n\n' "${br2_desc}"
fi >>"${outputdir}/.br2-external.in.init"
if [ -f "${br2_ext}/linux/Config.ext.in" ]; then
printf 'comment "linux extension from: %s"\n' "${br2_desc}"
printf 'source "%s/linux/Config.ext.in"\n' "${br2_ext}"
printf '\n'
else
printf '# No linux extension from: %s\n\n' "${br2_desc}"
fi >>"${outputdir}/.br2-external.in.linux"
done
printf 'endmenu\n' >>"${outputdir}/.br2-external.in.menus"
}
error() { local fmt="${1}"; shift; printf "BR2_EXTERNAL_ERROR = ${fmt}" "${@}"; exit 1; }
my_name="${0##*/}"
main "${@}"