| #!/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 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_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 outputdir="${1}" |
| local br2_name br2_desc 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 |
| } >"${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 |
| local -a items |
| |
| items=( |
| paths |
| menus |
| toolchains |
| jpeg |
| openssl |
| ) |
| |
| 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" |
| |
| 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 'config BR2_EXTERNAL_%s_PATH\n' "${br2_name}" |
| printf '\tstring\n' |
| printf '\tdefault "%s"\n' "${br2_ext}" |
| 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" |
| 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 "${@}" |