mirror of
https://gitlab.com/buildroot.org/buildroot.git
synced 2026-08-01 21:23:51 -09:00
Specifying a list of br2-external trees is poorly documented, and the
only example uses a colon to separate the br2-external paths.
Adding the support for colon-separated list is the biggest mistake that
was made when introducing support for multiple br2-external [0]. Indeed,
both space and colon can be used to separate entries in the list, and it
is also possible to mix the two. However, internally, the list is stored
as a space-separated list, and all the code will split on spaces.
Besides, all other lists in Buildroot are a space-separated:
BR2_ROOTFS_DEVICE_TABLE
BR2_ROOTFS_STATIC_DEVICE_TABLE
BR2_TARGET_TZ_ZONELIST
BR2_ROOTFS_USERS_TABLES
BR2_ROOTFS_OVERLAY
BR2_ROOTFS_PRE_BUILD_SCRIPT
BR2_ROOTFS_POST_BUILD_SCRIPT
BR2_ROOTFS_POST_FAKEROOT_SCRIPT
BR2_ROOTFS_POST_IMAGE_SCRIPT
...
So, using colons is odd.
The fact that BR2_EXTERNAL is passed on the command line rather than
being a Kconfig item is not a reason enough to justify that it be
colon-separated.
Change the documentation to only mention using a space-separated list.
Of course, for backward compatibility, we keep the code as-is to accept
a colon-separated list, but we just do not advertise it.
Note that keeping the split on colons means that colons are not accepted
in pathnames of br2-external trees; in practice, this is not a new
restriction, or one that could lift as usign colons in Makefiles are
problematic anyway.
[0] in 20cd497387 core: add support for multiple br2-external trees
Reported-by: Fiona Klute (WIWA) <fiona.klute@gmx.de>
Reported-by: Brandon Maier <Brandon.Maier@collins.com>
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
Cc: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
Signed-off-by: Romain Naour <romain.naour@smile.fr>
283 lines
9.7 KiB
Bash
Executable File
283 lines
9.7 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
|
|
|
|
if ! mkdir -p "${outputdir}"; then
|
|
error "Cannot create output directory '%s'\n" "${outputdir}"
|
|
fi
|
|
|
|
# Historically, BR2_EXTERNAL could also be colon-separated, so for
|
|
# backward compatibility, keep splitting on colons (in addition to
|
|
# spaces).
|
|
# shellcheck disable=SC2068 # We do want to split on spaces
|
|
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}" ] || [ ! -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"
|
|
}
|
|
|
|
# shellcheck disable=SC2059 # fmt *is* a format
|
|
error() { local fmt="${1}"; shift; printf "BR2_EXTERNAL_ERROR = ${fmt}" "${@}"; exit 1; }
|
|
|
|
main "${@}"
|