br2-external 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #!/usr/bin/env bash
  2. set -e
  3. # This script must be able to run with bash-3.1, so it can't use
  4. # associative arrays. Instead, it emulates them using 'eval'. It
  5. # can however use indexed arrays, supported since at least bash-3.0.
  6. # The names of the br2-external trees, once validated.
  7. declare -a BR2_EXT_NAMES
  8. # URL to manual for help in converting old br2-external trees.
  9. # Escape '#' so that make does not consider it a comment.
  10. MANUAL_URL='https://buildroot.org/manual.html\#br2-external-converting'
  11. main() {
  12. local OPT OPTARG
  13. local br2_ext ofile ofmt
  14. while getopts :hkmo: OPT; do
  15. case "${OPT}" in
  16. h) help; exit 0;;
  17. o) ofile="${OPTARG}";;
  18. k) ofmt="kconfig";;
  19. m) ofmt="mk";;
  20. :) error "option '%s' expects a mandatory argument\n" "${OPTARG}";;
  21. \?) error "unknown option '%s'\n" "${OPTARG}";;
  22. esac
  23. done
  24. # Forget options; keep only positional args
  25. shift $((OPTIND-1))
  26. case "${ofmt}" in
  27. mk|kconfig)
  28. ;;
  29. *) error "no output format specified (-m/-k)\n";;
  30. esac
  31. if [ -z "${ofile}" ]; then
  32. error "no output file specified (-o)\n"
  33. fi
  34. exec >"${ofile}"
  35. # Trap any unexpected error to generate a meaningful error message
  36. trap "error 'unexpected error while generating ${ofile}\n'" ERR
  37. do_validate ${@//:/ }
  38. do_${ofmt}
  39. }
  40. # Validates the br2-external trees passed as arguments. Makes each of
  41. # them canonical and store them in the global arrays BR2_EXT_NAMES
  42. # and BR2_EXT_PATHS.
  43. #
  44. # Note: since this script is always first called from Makefile context
  45. # to generate the Makefile fragment before it is called to generate the
  46. # Kconfig snippet, we're sure that any error in do_validate will be
  47. # interpreted in Makefile context. Going up to generating the Kconfig
  48. # snippet means that there were no error.
  49. #
  50. do_validate() {
  51. local br2_ext
  52. if [ ${#} -eq 0 ]; then
  53. # No br2-external tree is valid
  54. return
  55. fi
  56. for br2_ext in "${@}"; do
  57. do_validate_one "${br2_ext}"
  58. done
  59. }
  60. do_validate_one() {
  61. local br2_ext="${1}"
  62. local br2_name br2_desc n d
  63. if [ ! -d "${br2_ext}" ]; then
  64. error "'%s': no such file or directory\n" "${br2_ext}"
  65. fi
  66. if [ ! -r "${br2_ext}" -o ! -x "${br2_ext}" ]; then
  67. error "'%s': permission denied\n" "${br2_ext}"
  68. fi
  69. if [ ! -f "${br2_ext}/external.desc" ]; then
  70. error "'%s': does not have a name (in 'external.desc'). See %s\n" \
  71. "${br2_ext}" "${MANUAL_URL}"
  72. fi
  73. br2_name="$(sed -r -e '/^name: +(.*)$/!d; s//\1/' "${br2_ext}/external.desc")"
  74. if [ -z "${br2_name}" ]; then
  75. error "'%s/external.desc': does not define the name\n" "${br2_ext}"
  76. fi
  77. # Only ASCII chars in [A-Za-z0-9_] are permitted
  78. n="$(sed -r -e 's/[A-Za-z0-9_]//g' <<<"${br2_name}" )"
  79. if [ -n "${n}" ]; then
  80. # Escape '$' so that it gets printed
  81. error "'%s': name '%s' contains invalid chars: '%s'\n" \
  82. "${br2_ext}" "${br2_name//\$/\$\$}" "${n//\$/\$\$}"
  83. fi
  84. eval d="\"\${BR2_EXT_PATHS_${br2_name}}\""
  85. if [ -n "${d}" ]; then
  86. error "'%s': name '%s' is already used in '%s'\n" \
  87. "${br2_ext}" "${br2_name}" "${d}"
  88. fi
  89. br2_desc="$(sed -r -e '/^desc: +(.*)$/!d; s//\1/' "${br2_ext}/external.desc")"
  90. if [ ! -f "${br2_ext}/external.mk" ]; then
  91. error "'%s/external.mk': no such file or directory\n" "${br2_ext}"
  92. fi
  93. if [ ! -f "${br2_ext}/Config.in" ]; then
  94. error "'%s/Config.in': no such file or directory\n" "${br2_ext}"
  95. fi
  96. # Register this br2-external tree, use an absolute canonical path
  97. br2_ext="$( cd "${br2_ext}"; pwd )"
  98. BR2_EXT_NAMES+=( "${br2_name}" )
  99. eval BR2_EXT_PATHS_${br2_name}="\"\${br2_ext}\""
  100. eval BR2_EXT_DESCS_${br2_name}="\"\${br2_desc:-\${br2_name}}\""
  101. }
  102. # Generate the .mk snippet that defines makefile variables
  103. # for the br2-external tree
  104. do_mk() {
  105. local br2_name br2_ext
  106. printf '#\n# Automatically generated file; DO NOT EDIT.\n#\n'
  107. printf '\n'
  108. printf 'BR2_EXTERNAL ?='
  109. for br2_name in "${BR2_EXT_NAMES[@]}"; do
  110. eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
  111. printf ' %s' "${br2_ext}"
  112. done
  113. printf '\n'
  114. printf 'BR2_EXTERNAL_NAMES = \n'
  115. printf 'BR2_EXTERNAL_DIRS = \n'
  116. printf 'BR2_EXTERNAL_MKS = \n'
  117. if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
  118. printf '\n'
  119. printf '# No br2-external tree defined.\n'
  120. return
  121. fi
  122. for br2_name in "${BR2_EXT_NAMES[@]}"; do
  123. eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
  124. eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
  125. printf '\n'
  126. printf 'BR2_EXTERNAL_NAMES += %s\n' "${br2_name}"
  127. printf 'BR2_EXTERNAL_DIRS += %s\n' "${br2_ext}"
  128. printf 'BR2_EXTERNAL_MKS += %s/external.mk\n' "${br2_ext}"
  129. printf 'export BR2_EXTERNAL_%s_PATH = %s\n' "${br2_name}" "${br2_ext}"
  130. printf 'export BR2_EXTERNAL_%s_DESC = %s\n' "${br2_name}" "${br2_desc}"
  131. done
  132. }
  133. # Generate the kconfig snippet for the br2-external tree.
  134. do_kconfig() {
  135. local br2_name br2_ext
  136. printf '#\n# Automatically generated file; DO NOT EDIT.\n#\n'
  137. printf '\n'
  138. if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
  139. printf '# No br2-external tree defined.\n'
  140. return
  141. fi
  142. printf 'menu "External options"\n'
  143. printf '\n'
  144. for br2_name in "${BR2_EXT_NAMES[@]}"; do
  145. eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
  146. eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
  147. if [ ${#BR2_EXT_NAMES[@]} -gt 1 ]; then
  148. printf 'menu "%s"\n' "${br2_desc}"
  149. fi
  150. printf 'comment "%s (in %s)"\n' "${br2_desc}" "${br2_ext}"
  151. printf 'config BR2_EXTERNAL_%s_PATH\n' "${br2_name}"
  152. printf '\tstring\n'
  153. printf '\tdefault "%s"\n' "${br2_ext}"
  154. printf 'source "%s/Config.in"\n' "${br2_ext}"
  155. if [ ${#BR2_EXT_NAMES[@]} -gt 1 ]; then
  156. printf 'endmenu # %s\n' "${br2_name}"
  157. fi
  158. printf '\n'
  159. done
  160. printf "endmenu # User-provided options\n"
  161. }
  162. help() {
  163. cat <<-_EOF_
  164. Usage:
  165. ${my_name} <-m|-k> -o FILE PATH
  166. With -m, ${my_name} generates the makefile fragment that defines
  167. variables related to the br2-external trees passed as positional
  168. arguments.
  169. With -k, ${my_name} generates the kconfig snippet to include the
  170. configuration options specified in the br2-external trees passed
  171. as positional arguments.
  172. Using -k and -m together is not possible. The last one wins.
  173. Options:
  174. -m Generate the makefile fragment.
  175. -k Generate the kconfig snippet.
  176. -o FILE
  177. FILE in which to generate the kconfig snippet or makefile
  178. fragment.
  179. Returns:
  180. 0 If no error
  181. !0 If any error
  182. _EOF_
  183. }
  184. error() { local fmt="${1}"; shift; printf "BR2_EXTERNAL_ERROR = ${fmt}" "${@}"; exit 1; }
  185. my_name="${0##*/}"
  186. main "${@}"