br2-external 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 outputdir
  14. while getopts :d: OPT; do
  15. case "${OPT}" in
  16. d) outputdir="${OPTARG}";;
  17. :) error "option '%s' expects a mandatory argument\n" "${OPTARG}";;
  18. \?) error "unknown option '%s'\n" "${OPTARG}";;
  19. esac
  20. done
  21. # Forget options; keep only positional args
  22. shift $((OPTIND-1))
  23. if [ -z "${outputdir}" ]; then
  24. error "no output directory specified (-d)\n"
  25. fi
  26. # Trap any unexpected error to generate a meaningful error message
  27. trap "error 'unexpected error while generating ${ofile}\n'" ERR
  28. mkdir -p "${outputdir}"
  29. do_validate "${outputdir}" ${@//:/ }
  30. do_mk "${outputdir}"
  31. do_kconfig "${outputdir}"
  32. }
  33. # Validates the br2-external trees passed as arguments. Makes each of
  34. # them canonical and store them in the global arrays BR2_EXT_NAMES
  35. # and BR2_EXT_PATHS.
  36. #
  37. # Note: since this script is always first called from Makefile context
  38. # to generate the Makefile fragment before it is called to generate the
  39. # Kconfig snippet, we're sure that any error in do_validate will be
  40. # interpreted in Makefile context. Going up to generating the Kconfig
  41. # snippet means that there were no error.
  42. #
  43. do_validate() {
  44. local outputdir="${1}"
  45. local br2_ext
  46. shift
  47. if [ ${#} -eq 0 ]; then
  48. # No br2-external tree is valid
  49. return
  50. fi
  51. for br2_ext in "${@}"; do
  52. do_validate_one "${br2_ext}"
  53. done >"${outputdir}/.br2-external.mk"
  54. }
  55. do_validate_one() {
  56. local br2_ext="${1}"
  57. local br2_name br2_desc br2_ver n d
  58. if [ ! -d "${br2_ext}" ]; then
  59. error "'%s': no such file or directory\n" "${br2_ext}"
  60. fi
  61. if [ ! -r "${br2_ext}" -o ! -x "${br2_ext}" ]; then
  62. error "'%s': permission denied\n" "${br2_ext}"
  63. fi
  64. if [ ! -f "${br2_ext}/external.desc" ]; then
  65. error "'%s': does not have an 'external.desc'. See %s\n" \
  66. "${br2_ext}" "${MANUAL_URL}"
  67. fi
  68. br2_name="$(sed -r -e '/^name: +(.*)$/!d; s//\1/' "${br2_ext}/external.desc")"
  69. if [ -z "${br2_name}" ]; then
  70. error "'%s/external.desc': does not define the name\n" "${br2_ext}"
  71. fi
  72. # Only ASCII chars in [A-Za-z0-9_] are permitted
  73. n="$(sed -r -e 's/[A-Za-z0-9_]//g' <<<"${br2_name}" )"
  74. if [ -n "${n}" ]; then
  75. # Escape '$' so that it gets printed
  76. error "'%s': name '%s' contains invalid chars: '%s'\n" \
  77. "${br2_ext}" "${br2_name//\$/\$\$}" "${n//\$/\$\$}"
  78. fi
  79. eval d="\"\${BR2_EXT_PATHS_${br2_name}}\""
  80. if [ -n "${d}" ]; then
  81. error "'%s': name '%s' is already used in '%s'\n" \
  82. "${br2_ext}" "${br2_name}" "${d}"
  83. fi
  84. br2_desc="$(sed -r -e '/^desc: +(.*)$/!d; s//\1/' "${br2_ext}/external.desc")"
  85. if [ ! -f "${br2_ext}/external.mk" ]; then
  86. error "'%s/external.mk': no such file or directory\n" "${br2_ext}"
  87. fi
  88. if [ ! -f "${br2_ext}/Config.in" ]; then
  89. error "'%s/Config.in': no such file or directory\n" "${br2_ext}"
  90. fi
  91. # Register this br2-external tree, use an absolute canonical path
  92. br2_ext="$( cd "${br2_ext}"; pwd )"
  93. br2_ver="$( support/scripts/setlocalversion "${br2_ext}" )"
  94. BR2_EXT_NAMES+=( "${br2_name}" )
  95. eval BR2_EXT_PATHS_${br2_name}="\"\${br2_ext}\""
  96. eval BR2_EXT_VERS_${br2_name}="\"\${br2_ver}\""
  97. eval BR2_EXT_DESCS_${br2_name}="\"\${br2_desc:-\${br2_name}}\""
  98. }
  99. # Generate the .mk snippet that defines makefile variables
  100. # for the br2-external tree
  101. do_mk() {
  102. local outputdir="${1}"
  103. local br2_name br2_desc br2_ext br2_ver
  104. {
  105. printf '#\n# Automatically generated file; DO NOT EDIT.\n#\n'
  106. printf '\n'
  107. printf 'BR2_EXTERNAL ?='
  108. for br2_name in "${BR2_EXT_NAMES[@]}"; do
  109. eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
  110. printf ' %s' "${br2_ext}"
  111. done
  112. printf '\n'
  113. printf 'export BR2_EXTERNAL_NAMES = \n'
  114. printf 'BR2_EXTERNAL_DIRS = \n'
  115. printf 'BR2_EXTERNAL_MKS = \n'
  116. if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
  117. printf '\n'
  118. printf '# No br2-external tree defined.\n'
  119. return
  120. fi
  121. for br2_name in "${BR2_EXT_NAMES[@]}"; do
  122. eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
  123. eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
  124. eval br2_ver="\"\${BR2_EXT_VERS_${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. printf 'export BR2_EXTERNAL_%s_VERSION = %s\n' "${br2_name}" "${br2_ver}"
  132. done
  133. } >"${outputdir}/.br2-external.mk"
  134. }
  135. # Generate the kconfig snippets for the br2-external tree.
  136. do_kconfig() {
  137. local outputdir="${1}"
  138. local br2_name br2_desc br2_ext br2_ver br2
  139. local -a items
  140. items=(
  141. paths
  142. menus
  143. toolchains
  144. jpeg
  145. openssl
  146. skeleton
  147. init
  148. linux
  149. )
  150. for br2 in "${items[@]}"; do
  151. {
  152. printf '#\n# Automatically generated file; DO NOT EDIT.\n#\n'
  153. printf '\n'
  154. if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
  155. printf '# No br2-external tree defined.\n'
  156. fi
  157. } >"${outputdir}/.br2-external.in.${br2}"
  158. done
  159. if [ ${#BR2_EXT_NAMES[@]} -eq 0 ]; then
  160. return
  161. fi
  162. printf 'menu "External options"\n\n' >>"${outputdir}/.br2-external.in.menus"
  163. {
  164. printf 'config BR2_EXTERNAL_NAMES\n'
  165. printf '\tstring\n'
  166. # Use star-expansion: we really one a single arg.
  167. printf '\tdefault "%s"\n' "${BR2_EXT_NAMES[*]}"
  168. printf '\n'
  169. } >>"${outputdir}/.br2-external.in.paths"
  170. for br2_name in "${BR2_EXT_NAMES[@]}"; do
  171. eval br2_desc="\"\${BR2_EXT_DESCS_${br2_name}}\""
  172. eval br2_ext="\"\${BR2_EXT_PATHS_${br2_name}}\""
  173. eval br2_ver="\"\${BR2_EXT_VERS_${br2_name}}\""
  174. {
  175. printf 'config BR2_EXTERNAL_%s_PATH\n' "${br2_name}"
  176. printf '\tstring\n'
  177. printf '\tdefault "%s"\n' "${br2_ext}"
  178. printf 'config BR2_EXTERNAL_%s_VERSION\n' "${br2_name}"
  179. printf '\tstring\n'
  180. printf '\tdefault "%s"\n' "${br2_ver}"
  181. printf '\n'
  182. } >>"${outputdir}/.br2-external.in.paths"
  183. {
  184. if [ ${#BR2_EXT_NAMES[@]} -gt 1 ]; then
  185. printf 'menu "%s"\n' "${br2_desc}"
  186. fi
  187. printf 'comment "%s (in %s)"\n' "${br2_desc}" "${br2_ext}"
  188. printf 'source "%s/Config.in"\n' "${br2_ext}"
  189. if [ ${#BR2_EXT_NAMES[@]} -gt 1 ]; then
  190. printf 'endmenu # %s\n' "${br2_name}"
  191. fi
  192. printf '\n'
  193. } >>"${outputdir}/.br2-external.in.menus"
  194. if [ -f "${br2_ext}/provides/toolchains.in" ]; then
  195. printf 'comment "Toolchains from: %s"\n' "${br2_desc}"
  196. printf 'source "%s/provides/toolchains.in"\n' "${br2_ext}"
  197. printf '\n'
  198. else
  199. printf '# No toolchain from: %s\n\n' "${br2_desc}"
  200. fi >>"${outputdir}/.br2-external.in.toolchains"
  201. if [ -f "${br2_ext}/provides/jpeg.in" ]; then
  202. printf 'comment "jpeg from: %s"\n' "${br2_desc}"
  203. printf 'source "%s/provides/jpeg.in"\n' "${br2_ext}"
  204. printf '\n'
  205. else
  206. printf '# No jpeg from: %s\n\n' "${br2_desc}"
  207. fi >>"${outputdir}/.br2-external.in.jpeg"
  208. if [ -f "${br2_ext}/provides/openssl.in" ]; then
  209. printf 'comment "openssl from: %s"\n' "${br2_desc}"
  210. printf 'source "%s/provides/openssl.in"\n' "${br2_ext}"
  211. printf '\n'
  212. else
  213. printf '# No openssl from: %s\n\n' "${br2_desc}"
  214. fi >>"${outputdir}/.br2-external.in.openssl"
  215. if [ -f "${br2_ext}/provides/skeleton.in" ]; then
  216. printf 'comment "skeleton from: %s"\n' "${br2_desc}"
  217. printf 'source "%s/provides/skeleton.in"\n' "${br2_ext}"
  218. printf '\n'
  219. else
  220. printf '# No skeleton from: %s\n\n' "${br2_desc}"
  221. fi >>"${outputdir}/.br2-external.in.skeleton"
  222. if [ -f "${br2_ext}/provides/init.in" ]; then
  223. printf 'comment "init from: %s"\n' "${br2_desc}"
  224. printf 'source "%s/provides/init.in"\n' "${br2_ext}"
  225. printf '\n'
  226. else
  227. printf '# No init from: %s\n\n' "${br2_desc}"
  228. fi >>"${outputdir}/.br2-external.in.init"
  229. if [ -f "${br2_ext}/linux/Config.ext.in" ]; then
  230. printf 'comment "linux extension from: %s"\n' "${br2_desc}"
  231. printf 'source "%s/linux/Config.ext.in"\n' "${br2_ext}"
  232. printf '\n'
  233. else
  234. printf '# No linux extension from: %s\n\n' "${br2_desc}"
  235. fi >>"${outputdir}/.br2-external.in.linux"
  236. done
  237. printf 'endmenu\n' >>"${outputdir}/.br2-external.in.menus"
  238. }
  239. error() { local fmt="${1}"; shift; printf "BR2_EXTERNAL_ERROR = ${fmt}" "${@}"; exit 1; }
  240. my_name="${0##*/}"
  241. main "${@}"