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