xref: /OK3568_Linux_fs/buildroot/support/scripts/br2-external (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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