]> rtime.felk.cvut.cz Git - coffee/buildroot.git/blob - utils/test-pkg
lrzsz: install symlinks for XMODEM and YMODEM
[coffee/buildroot.git] / utils / test-pkg
1 #!/usr/bin/env bash
2 set -e
3
4 TOOLCHAINS_CSV='support/config-fragments/autobuild/toolchain-configs.csv'
5
6 main() {
7     local o O opts
8     local cfg dir pkg random toolchains_dir toolchain all number mode
9     local ret nb nb_skip nb_fail nb_legal nb_tc build_dir
10     local -a toolchains
11
12     o='hac:d:n:p:r:t:'
13     O='help,config-snippet:build-dir:package:,random:,toolchains-dir:'
14     opts="$(getopt -n "${my_name}" -o "${o}" -l "${O}" -- "${@}")"
15     eval set -- "${opts}"
16
17     random=0
18     all=0
19     number=0
20     mode=0
21     toolchains_csv="${TOOLCHAINS_CSV}"
22     while [ ${#} -gt 0 ]; do
23         case "${1}" in
24         (-h|--help)
25             help; exit 0
26             ;;
27         (-a|--all)
28             all=1; shift 1
29             ;;
30         (-c|--config-snippet)
31             cfg="${2}"; shift 2
32             ;;
33         (-d|--build-dir)
34             dir="${2}"; shift 2
35             ;;
36         (-n|--number)
37             number="${2}"; shift 2
38             ;;
39         (-p|--package)
40             pkg="${2}"; shift 2
41             ;;
42         (-r|--random)
43             random="${2}"; shift 2
44             ;;
45         (-t|--toolchains-csv)
46             toolchains_csv="${2}"; shift 2
47             ;;
48         (--)
49             shift; break
50             ;;
51         esac
52     done
53     if [ -z "${cfg}" ]; then
54         printf "error: no config snippet specified\n" >&2; exit 1
55     fi
56     if [ ! -e "${cfg}" ]; then
57         printf "error: %s: no such file\n" "${cfg}" >&2; exit 1
58     fi
59     if [ -z "${dir}" ]; then
60         dir="${HOME}/br-test-pkg"
61     fi
62
63     if [ ${random} -gt 0 ]; then
64         mode=$((mode+1))
65     fi
66
67     if [ ${number} -gt 0 ]; then
68         mode=$((mode+1))
69     fi
70
71     if [ ${all} -eq 1 ]; then
72         mode=$((mode+1))
73     fi
74
75     # Default mode is to test the N first toolchains, which have been
76     # chosen to be a good selection of toolchains.
77     if [ ${mode} -eq 0 ] ; then
78         number=6
79     elif [ ${mode} -gt 1 ] ; then
80         printf "error: --all, --number and --random are mutually exclusive\n" >&2; exit 1
81     fi
82
83     # Extract the URLs of the toolchains; drop internal toolchains
84     # E.g.: http://server/path/to/name.config,arch,libc
85     #  -->  http://server/path/to/name.config
86     toolchains=($(sed -r -e 's/,.*//; /internal/d; /^#/d; /^$/d;' "${toolchains_csv}" \
87                   |if [ ${random} -gt 0 ]; then \
88                       sort -R |head -n ${random}
89                   elif [ ${number} -gt 0 ]; then \
90                       head -n ${number}
91                   else
92                       sort
93                   fi
94                  )
95                )
96
97     nb_tc="${#toolchains[@]}"
98     if [ ${nb_tc} -eq 0 ]; then
99         printf "error: no toolchain found (networking issue?)\n" >&2; exit 1
100     fi
101
102     nb=0
103     nb_skip=0
104     nb_fail=0
105     nb_legal=0
106     for toolchainconfig in "${toolchains[@]}"; do
107         : $((nb++))
108         toolchain="$(basename "${toolchainconfig}" .config)"
109         build_dir="${dir}/${toolchain}"
110         printf "%40s [%*d/%d]: " "${toolchain}" ${#nb_tc} ${nb} ${nb_tc}
111         build_one "${build_dir}" "${toolchainconfig}" "${cfg}" "${pkg}" && ret=0 || ret=${?}
112         case ${ret} in
113         (0) printf "OK\n";;
114         (1) : $((nb_skip++)); printf "SKIPPED\n";;
115         (2) : $((nb_fail++)); printf "FAILED\n";;
116         (3) : $((nb_legal++)); printf "FAILED\n";;
117         esac
118     done
119
120     printf "%d builds, %d skipped, %d build failed, %d legal-info failed\n" \
121         ${nb} ${nb_skip} ${nb_fail} ${nb_legal}
122 }
123
124 build_one() {
125     local dir="${1}"
126     local toolchainconfig="${2}"
127     local cfg="${3}"
128     local pkg="${4}"
129
130     mkdir -p "${dir}"
131
132     support/kconfig/merge_config.sh -O "${dir}" \
133         "${toolchainconfig}" "support/config-fragments/minimal.config" "${cfg}" \
134         > /dev/null
135     # We want all the options from the snippet to be present as-is (set
136     # or not set) in the actual .config; if one of them is not, it means
137     # some dependency from the toolchain or arch is not available, in
138     # which case this config is untestable and we skip it.
139     # We don't care about the locale to sort in, as long as both sort are
140     # done in the same locale.
141     comm -23 <(sort "${cfg}") <(sort "${dir}/.config") >"${dir}/missing.config"
142     if [ -s "${dir}/missing.config" ]; then
143         return 1
144     fi
145     # Remove file, it's empty anyway.
146     rm -f "${dir}/missing.config"
147
148     if [ -n "${pkg}" ]; then
149         if ! make O="${dir}" "${pkg}-dirclean" >> "${dir}/logfile" 2>&1; then
150             return 2
151         fi
152     fi
153
154     # shellcheck disable=SC2086
155     if ! make O="${dir}" ${pkg} >> "${dir}/logfile" 2>&1; then
156         return 2
157     fi
158
159     # legal-info done systematically, because some packages have different
160     # sources depending on the configuration (e.g. lua-5.2 vs. lua-5.3)
161     if ! make O="${dir}" legal-info >> "${dir}/logfile" 2>&1; then
162         return 3
163     fi
164 }
165
166 help() {
167     cat <<_EOF_
168 test-pkg: test-build a package against various toolchains and architectures
169
170 The supplied config snippet is appended to each toolchain config, the
171 resulting configuration is checked to ensure it still contains all options
172 specified in the snippet; if any is missing, the build is skipped, on the
173 assumption that the package under test requires a toolchain or architecture
174 feature that is missing.
175
176 In case failures are noticed, you can fix the package and just re-run the
177 same command again; it will re-run the test where it failed. If you did
178 specify a package (with -p), the package build dir will be removed first.
179
180 The list of toolchains is retrieved from ${TOOLCHAINS_CSV}.
181 Only the external toolchains are tried, because building a Buildroot toolchain
182 would take too long. An alternative toolchains CSV file can be specified with
183 the -t option. This file should have lines consisting of the path to the
184 toolchain config fragment and the required host architecture, separated by a
185 comma. The config fragments should contain only the toolchain and architecture
186 settings.
187
188 By default, a useful subset of toolchains is tested. If needed, all
189 toolchains can be tested (-a), an arbitrary number of toolchains (-n
190 in order, -r for random).
191
192 Options:
193
194     -h, --help
195         Print this help.
196
197     -c CFG, --config-snippet CFG
198         Use the CFG file as the source for the config snippet. This file
199         should contain all the config options required to build a package.
200
201     -d DIR, --build-dir DIR
202         Do the builds in directory DIR, one sub-dir per toolchain.
203
204     -p PKG, --package PKG
205         Test-build the package PKG, by running 'make PKG'; if not specified,
206         just runs 'make'.
207
208     -a, --all
209         Test all toolchains, instead of the default subset defined by
210         Buildroot developers.
211
212     -n N, --number N
213         Test N toolchains, in the order defined in the toolchain CSV
214         file.
215
216     -r N, --random N
217         Limit the tests to the N randomly selected toolchains.
218
219     -t CSVFILE, --toolchains-csv CSVFILE
220         CSV file containing the paths to config fragments of toolchains to
221         try. If not specified, the toolchains in ${TOOLCHAINS_CSV} will be
222         used.
223
224 Example:
225
226     Testing libcec would require a config snippet that contains:
227         BR2_PACKAGE_LIBCEC=y
228
229     Testing libcurl with openSSL support would require a snippet such as:
230         BR2_PACKAGE_OPENSSL=y
231         BR2_PACKAGE_LIBCURL=y
232
233 _EOF_
234 }
235
236 my_name="${0##*/}"
237 main "${@}"