test-pkg 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #!/bin/bash
  2. set -e
  3. TOOLCHAINS_URL='http://autobuild.buildroot.org/toolchains/configs/toolchain-configs.csv'
  4. main() {
  5. local o O opts
  6. local cfg dir pkg random toolchain
  7. local ret nb nb_skip nb_fail nb_legal nb_tc build_dir
  8. local -a toolchains
  9. o='hc:d:p:r:'
  10. O='help,config-snippet:build-dir:package:,random:'
  11. opts="$(getopt -n "${my_name}" -o "${o}" -l "${O}" -- "${@}")"
  12. eval set -- "${opts}"
  13. random=0
  14. while [ ${#} -gt 0 ]; do
  15. case "${1}" in
  16. (-h|--help)
  17. help; exit 0
  18. ;;
  19. (-c|--config-snippet)
  20. cfg="${2}"; shift 2
  21. ;;
  22. (-d|--build-dir)
  23. dir="${2}"; shift 2
  24. ;;
  25. (-p|--package)
  26. pkg="${2}"; shift 2
  27. ;;
  28. (-r|--random)
  29. random="${2}"; shift 2
  30. ;;
  31. (--)
  32. shift; break
  33. ;;
  34. esac
  35. done
  36. if [ -z "${cfg}" ]; then
  37. printf "error: no config snippet specified\n" >&2; exit 1
  38. fi
  39. if [ ! -e "${cfg}" ]; then
  40. printf "error: %s: no such file\n" "${cfg}" >&2; exit 1
  41. fi
  42. if [ -z "${dir}" ]; then
  43. dir="${HOME}/br-test-pkg"
  44. fi
  45. # Extract the URLs of the toolchains; drop internal toolchains
  46. # E.g.: http://server/path/to/name.config,arch,libc
  47. # --> http://server/path/to/name.config
  48. toolchains=($(curl -s "${TOOLCHAINS_URL}" \
  49. |sed -r -e 's/,.*//; /internal/d;' \
  50. |if [ ${random} -gt 0 ]; then \
  51. sort -R |head -n ${random}
  52. else
  53. cat
  54. fi |sort
  55. )
  56. )
  57. nb_tc="${#toolchains[@]}"
  58. if [ ${nb_tc} -eq 0 ]; then
  59. printf "error: no toolchain found (networking issue?)\n" >&2; exit 1
  60. fi
  61. nb=0
  62. nb_skip=0
  63. nb_fail=0
  64. nb_legal=0
  65. for toolchainconfig in "${toolchains[@]}"; do
  66. : $((nb++))
  67. # Using basename(1) on a URL works nicely
  68. toolchain="$(basename "${toolchainconfig}" .config)"
  69. build_dir="${dir}/${toolchain}"
  70. printf "%40s [%*d/%d]: " "${toolchain}" ${#nb_tc} ${nb} ${nb_tc}
  71. build_one "${build_dir}" "${toolchainconfig}" "${cfg}" "${pkg}" && ret=0 || ret=${?}
  72. case ${ret} in
  73. (0) printf "OK\n";;
  74. (1) : $((nb_skip++)); printf "SKIPPED\n";;
  75. (2) : $((nb_fail++)); printf "FAILED\n";;
  76. (3) : $((nb_legal++)); printf "FAILED\n";;
  77. esac
  78. done
  79. printf "%d builds, %d skipped, %d build failed, %d legal-info failed\n" \
  80. ${nb} ${nb_skip} ${nb_fail} ${nb_legal}
  81. }
  82. build_one() {
  83. local dir="${1}"
  84. local url="${2}"
  85. local cfg="${3}"
  86. local pkg="${4}"
  87. mkdir -p "${dir}"
  88. if ! curl -s "${url}" >"${dir}/.config"; then
  89. return 2
  90. fi
  91. cat >>"${dir}/.config" <<-_EOF_
  92. BR2_INIT_NONE=y
  93. BR2_SYSTEM_BIN_SH_NONE=y
  94. # BR2_PACKAGE_BUSYBOX is not set
  95. # BR2_TARGET_ROOTFS_TAR is not set
  96. _EOF_
  97. cat "${cfg}" >>"${dir}/.config"
  98. if ! make O="${dir}" olddefconfig > "${dir}/logfile" 2>&1; then
  99. return 2
  100. fi
  101. # We want all the options from the snippet to be present as-is (set
  102. # or not set) in the actual .config; if one of them is not, it means
  103. # some dependency from the toolchain or arch is not available, in
  104. # which case this config is untestable and we skip it.
  105. # We don't care about the locale to sort in, as long as both sort are
  106. # done in the same locale.
  107. comm -23 <(sort "${cfg}") <(sort "${dir}/.config") >"${dir}/missing.config"
  108. if [ -s "${dir}/missing.config" ]; then
  109. return 1
  110. fi
  111. # Remove file, it's empty anyway.
  112. rm -f "${dir}/missing.config"
  113. if [ -n "${pkg}" ]; then
  114. if ! make O="${dir}" "${pkg}-dirclean" >> "${dir}/logfile" 2>&1; then
  115. return 2
  116. fi
  117. fi
  118. # shellcheck disable=SC2086
  119. if ! make O="${dir}" ${pkg} >> "${dir}/logfile" 2>&1; then
  120. return 2
  121. fi
  122. # legal-info done systematically, because some packages have different
  123. # sources depending on the configuration (e.g. lua-5.2 vs. lua-5.3)
  124. if [ -n "${pkg}" ]; then
  125. if ! make O="${dir}" "${pkg}-legal-info" >> "${dir}/logfile" 2>&1; then
  126. return 3
  127. fi
  128. fi
  129. }
  130. help() {
  131. cat <<_EOF_
  132. test-pkg: test-build a package against various toolchains and architectures
  133. The supplied config snippet is appended to each toolchain config, the
  134. resulting configuration is checked to ensure it still contains all options
  135. specified in the snippet; if any is missing, the build is skipped, on the
  136. assumption that the package under test requires a toolchain or architecture
  137. feature that is missing.
  138. In case failures are noticed, you can fix the package and just re-run the
  139. same command again; it will re-run the test where it failed. If you did
  140. specify a package (with -p), the package build dir will be removed first.
  141. The list of toolchains is retrieved from the Buildroot autobuilders, available
  142. at ${TOOLCHAINS_URL}.
  143. Options:
  144. -h, --help
  145. Print this help.
  146. -c CFG, --config-snippet CFG
  147. Use the CFG file as the source for the config snippet. This file
  148. should contain all the config options required to build a package.
  149. -d DIR, --build-dir DIR
  150. Do the builds in directory DIR, one sub-dir per toolchain.
  151. -p PKG, --package PKG
  152. Test-build the package PKG, by running 'make PKG'; if not specified,
  153. just runs 'make'.
  154. -r N, --random N
  155. Limit the tests to the N randomly selected toolchains, instead of
  156. building with all toolchains.
  157. Example:
  158. Testing libcec would require a config snippet that contains:
  159. BR2_PACKAGE_LIBCEC=y
  160. Testing libcurl with openSSL support would require a snippet such as:
  161. BR2_PACKAGE_OPENSSL=y
  162. BR2_PACKAGE_LIBCURL=y
  163. _EOF_
  164. }
  165. my_name="${0##*/}"
  166. main "${@}"