123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- #!/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 ofile ofmt
- while getopts :hkmo: OPT; do
- case "${OPT}" in
- h) help; exit 0;;
- o) ofile="${OPTARG}";;
- k) ofmt="kconfig";;
- m) ofmt="mk";;
- :) 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))
- case "${ofmt}" in
- mk|kconfig)
- ;;
- *) error "no output format specified (-m/-k)\n";;
- esac
- if [ -z "${ofile}" ]; then
- error "no output file specified (-o)\n"
- fi
- exec >"${ofile}"
- # Trap any unexpected error to generate a meaningful error message
- trap "error 'unexpected error while generating ${ofile}\n'" ERR
- do_validate ${@//:/ }
- do_${ofmt}
- }
- # 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 br2_ext
- if [ ${#} -eq 0 ]; then
- # No br2-external tree is valid
- return
- fi
- for br2_ext in "${@}"; do
- do_validate_one "${br2_ext}"
- done
- }
- do_validate_one() {
- local br2_ext="${1}"
- local br2_name br2_desc 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 a name (in '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_EXT_NAMES+=( "${br2_name}" )
- eval BR2_EXT_PATHS_${br2_name}="\"\${br2_ext}\""
- 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 br2_name br2_ext
- 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 '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}}\""
- 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}"
- done
- }
- # Generate the kconfig snippet for the br2-external tree.
- do_kconfig() {
- local br2_name br2_ext
- 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'
- return
- fi
- printf 'menu "External options"\n'
- printf '\n'
- for br2_name in "${BR2_EXT_NAMES[@]}"; do
- eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
- eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
- 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 'config BR2_EXTERNAL_%s_PATH\n' "${br2_name}"
- printf '\tstring\n'
- printf '\tdefault "%s"\n' "${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'
- done
- printf "endmenu # User-provided options\n"
- }
- help() {
- cat <<-_EOF_
- Usage:
- ${my_name} <-m|-k> -o FILE PATH
- With -m, ${my_name} generates the makefile fragment that defines
- variables related to the br2-external trees passed as positional
- arguments.
- With -k, ${my_name} generates the kconfig snippet to include the
- configuration options specified in the br2-external trees passed
- as positional arguments.
- Using -k and -m together is not possible. The last one wins.
- Options:
- -m Generate the makefile fragment.
- -k Generate the kconfig snippet.
- -o FILE
- FILE in which to generate the kconfig snippet or makefile
- fragment.
- Returns:
- 0 If no error
- !0 If any error
- _EOF_
- }
- error() { local fmt="${1}"; shift; printf "BR2_EXTERNAL_ERROR = ${fmt}" "${@}"; exit 1; }
- my_name="${0##*/}"
- main "${@}"
|