123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- #!/usr/bin/env bash
- set -e
- TOOLCHAINS_CSV='support/config-fragments/autobuild/toolchain-configs.csv'
- TEMP_CONF=""
- do_clean() {
- if [ ! -z "${TEMP_CONF}" ]; then
- rm -f "${TEMP_CONF}"
- fi
- }
- main() {
- local o O opts
- local cfg dir pkg random toolchains_dir toolchain all number mode
- local ret nb nb_skip nb_fail nb_legal nb_tc build_dir
- local -a toolchains
- local pkg_br_name
- o='hac:d:n:p:r:t:'
- O='help,config-snippet:build-dir:package:,random:,toolchains-dir:'
- opts="$(getopt -n "${my_name}" -o "${o}" -l "${O}" -- "${@}")"
- eval set -- "${opts}"
- random=0
- all=0
- number=0
- mode=0
- toolchains_csv="${TOOLCHAINS_CSV}"
- while [ ${#} -gt 0 ]; do
- case "${1}" in
- (-h|--help)
- help; exit 0
- ;;
- (-a|--all)
- all=1; shift 1
- ;;
- (-c|--config-snippet)
- cfg="${2}"; shift 2
- ;;
- (-d|--build-dir)
- dir="${2}"; shift 2
- ;;
- (-n|--number)
- number="${2}"; shift 2
- ;;
- (-p|--package)
- pkg="${2}"; shift 2
- ;;
- (-r|--random)
- random="${2}"; shift 2
- ;;
- (-t|--toolchains-csv)
- toolchains_csv="${2}"; shift 2
- ;;
- (--)
- shift; break
- ;;
- esac
- done
- trap do_clean INT TERM HUP EXIT
- if [ -z "${cfg}" ]; then
- pkg_br_name="${pkg//-/_}"
- pkg_br_name="BR2_PACKAGE_${pkg_br_name^^}"
- TEMP_CONF=$(mktemp /tmp/test-${pkg}-config.XXXXXX)
- echo "${pkg_br_name}=y" > ${TEMP_CONF}
- cfg="${TEMP_CONF}"
- fi
- if [ ! -e "${cfg}" ]; then
- printf "error: %s: no such file\n" "${cfg}" >&2; exit 1
- fi
- if [ -z "${dir}" ]; then
- dir="${HOME}/br-test-pkg"
- fi
- if [ ${random} -gt 0 ]; then
- mode=$((mode+1))
- fi
- if [ ${number} -gt 0 ]; then
- mode=$((mode+1))
- fi
- if [ ${all} -eq 1 ]; then
- mode=$((mode+1))
- fi
- # Default mode is to test the N first toolchains, which have been
- # chosen to be a good selection of toolchains.
- if [ ${mode} -eq 0 ] ; then
- number=6
- elif [ ${mode} -gt 1 ] ; then
- printf "error: --all, --number and --random are mutually exclusive\n" >&2; exit 1
- fi
- # Extract the URLs of the toolchains; drop internal toolchains
- # E.g.: http://server/path/to/name.config,arch,libc
- # --> http://server/path/to/name.config
- toolchains=($(sed -r -e 's/,.*//; /internal/d; /^#/d; /^$/d;' "${toolchains_csv}" \
- |if [ ${random} -gt 0 ]; then \
- sort -R |head -n ${random}
- elif [ ${number} -gt 0 ]; then \
- head -n ${number}
- else
- sort
- fi
- )
- )
- nb_tc="${#toolchains[@]}"
- if [ ${nb_tc} -eq 0 ]; then
- printf "error: no toolchain found (networking issue?)\n" >&2; exit 1
- fi
- nb=0
- nb_skip=0
- nb_fail=0
- nb_legal=0
- for toolchainconfig in "${toolchains[@]}"; do
- : $((nb++))
- toolchain="$(basename "${toolchainconfig}" .config)"
- build_dir="${dir}/${toolchain}"
- printf "%40s [%*d/%d]: " "${toolchain}" ${#nb_tc} ${nb} ${nb_tc}
- build_one "${build_dir}" "${toolchainconfig}" "${cfg}" "${pkg}" && ret=0 || ret=${?}
- case ${ret} in
- (0) printf "OK\n";;
- (1) : $((nb_skip++)); printf "SKIPPED\n";;
- (2) : $((nb_fail++)); printf "FAILED\n";;
- (3) : $((nb_legal++)); printf "FAILED\n";;
- esac
- done
- printf "%d builds, %d skipped, %d build failed, %d legal-info failed\n" \
- ${nb} ${nb_skip} ${nb_fail} ${nb_legal}
- }
- build_one() {
- local dir="${1}"
- local toolchainconfig="${2}"
- local cfg="${3}"
- local pkg="${4}"
- mkdir -p "${dir}"
- CONFIG_= support/kconfig/merge_config.sh -O "${dir}" \
- "${toolchainconfig}" "support/config-fragments/minimal.config" "${cfg}" \
- >> "${dir}/logfile" 2>&1
- # We want all the options from the snippet to be present as-is (set
- # or not set) in the actual .config; if one of them is not, it means
- # some dependency from the toolchain or arch is not available, in
- # which case this config is untestable and we skip it.
- # We don't care about the locale to sort in, as long as both sort are
- # done in the same locale.
- comm -23 <(sort "${cfg}") <(sort "${dir}/.config") >"${dir}/missing.config"
- if [ -s "${dir}/missing.config" ]; then
- return 1
- fi
- # Remove file, it's empty anyway.
- rm -f "${dir}/missing.config"
- if [ -n "${pkg}" ]; then
- if ! make O="${dir}" "${pkg}-dirclean" >> "${dir}/logfile" 2>&1; then
- return 2
- fi
- fi
- # shellcheck disable=SC2086
- if ! BR_FORCE_CHECK_DEPENDENCIES=YES make O="${dir}" ${pkg} >> "${dir}/logfile" 2>&1; then
- return 2
- fi
- # legal-info done systematically, because some packages have different
- # sources depending on the configuration (e.g. lua-5.2 vs. lua-5.3)
- if ! make O="${dir}" legal-info >> "${dir}/logfile" 2>&1; then
- return 3
- fi
- }
- help() {
- cat <<_EOF_
- test-pkg: test-build a package against various toolchains and architectures
- The supplied config snippet is appended to each toolchain config, the
- resulting configuration is checked to ensure it still contains all options
- specified in the snippet; if any is missing, the build is skipped, on the
- assumption that the package under test requires a toolchain or architecture
- feature that is missing.
- In case failures are noticed, you can fix the package and just re-run the
- same command again; it will re-run the test where it failed. If you did
- specify a package (with -p), the package build dir will be removed first.
- The list of toolchains is retrieved from ${TOOLCHAINS_CSV}.
- Only the external toolchains are tried, because building a Buildroot toolchain
- would take too long. An alternative toolchains CSV file can be specified with
- the -t option. This file should have lines consisting of the path to the
- toolchain config fragment and the required host architecture, separated by a
- comma. The config fragments should contain only the toolchain and architecture
- settings.
- By default, a useful subset of toolchains is tested. If needed, all
- toolchains can be tested (-a), an arbitrary number of toolchains (-n
- in order, -r for random).
- Options:
- -h, --help
- Print this help.
- -c CFG, --config-snippet CFG
- Use the CFG file as the source for the config snippet. This file
- should contain all the config options required to build a package.
- -d DIR, --build-dir DIR
- Do the builds in directory DIR, one sub-dir per toolchain.
- -p PKG, --package PKG
- Test-build the package PKG, by running 'make PKG'; if not specified,
- just runs 'make'.
- -a, --all
- Test all toolchains, instead of the default subset defined by
- Buildroot developers.
- -n N, --number N
- Test N toolchains, in the order defined in the toolchain CSV
- file.
- -r N, --random N
- Limit the tests to the N randomly selected toolchains.
- -t CSVFILE, --toolchains-csv CSVFILE
- CSV file containing the paths to config fragments of toolchains to
- try. If not specified, the toolchains in ${TOOLCHAINS_CSV} will be
- used.
- Example:
- Testing libcec would require a config snippet that contains:
- BR2_PACKAGE_LIBCEC=y
- Testing libcurl with openSSL support would require a snippet such as:
- BR2_PACKAGE_OPENSSL=y
- BR2_PACKAGE_LIBCURL=y
- _EOF_
- }
- my_name="${0##*/}"
- main "${@}"
|