test-pkg 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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
  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. if [ ${#toolchains[@]} -eq 0 ]; then
  58. printf "error: no toolchain found (networking issue?)\n" >&2; exit 1
  59. fi
  60. nb=0
  61. nb_skip=0
  62. nb_fail=0
  63. for toolchain in "${toolchains[@]}"; do
  64. build_one "${dir}" "${toolchain}" "${cfg}" "${pkg}" && ret=0 || ret=${?}
  65. case ${ret} in
  66. (0) ;;
  67. (1) : $((nb_skip++));;
  68. (2) : $((nb_fail++));;
  69. esac
  70. : $((nb++))
  71. done
  72. printf "%d builds, %d skipped, %d failed\n" ${nb} ${nb_skip} ${nb_fail}
  73. }
  74. build_one() {
  75. local dir="${1}"
  76. local url="${2}"
  77. local cfg="${3}"
  78. local pkg="${4}"
  79. local toolchain
  80. # Using basename(1) on a URL works nicely
  81. toolchain="$(basename "${url}" .config)"
  82. printf "%40s: " "${toolchain}"
  83. dir="${dir}/${toolchain}"
  84. mkdir -p "${dir}"
  85. if ! curl -s "${url}" >"${dir}/.config"; then
  86. printf "FAILED\n"
  87. return 2
  88. fi
  89. cat >>"${dir}/.config" <<-_EOF_
  90. BR2_INIT_NONE=y
  91. BR2_SYSTEM_BIN_SH_NONE=y
  92. # BR2_PACKAGE_BUSYBOX is not set
  93. # BR2_TARGET_ROOTFS_TAR is not set
  94. _EOF_
  95. cat "${cfg}" >>"${dir}/.config"
  96. if ! make O="${dir}" olddefconfig >/dev/null 2>&1; then
  97. printf "FAILED\n"
  98. return 2
  99. fi
  100. # We want all the options from the snippet to be present as-is (set
  101. # or not set) in the actual .config; if one of them is not, it means
  102. # some dependency from the toolchain or arch is not available, in
  103. # which case this config is untestable and we skip it.
  104. # We don't care about the locale to sort in, as long as both sort are
  105. # done in the same locale.
  106. comm -23 <(sort "${cfg}") <(sort "${dir}/.config") >"${dir}/missing.config"
  107. if [ -s "${dir}/missing.config" ]; then
  108. printf "SKIPPED\n"
  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. printf "FAILED\n"
  116. return 2
  117. fi
  118. fi
  119. # shellcheck disable=SC2086
  120. if ! make O="${dir}" ${pkg} >> "${dir}/logfile" 2>&1; then
  121. printf "FAILED\n"
  122. return 2
  123. fi
  124. printf "OK\n"
  125. }
  126. help() {
  127. cat <<_EOF_
  128. test-pkg: test-build a package against various toolchains and architectures
  129. The supplied config snippet is appended to each toolchain config, the
  130. resulting configuration is checked to ensure it still contains all options
  131. specified in the snippet; if any is missing, the build is skipped, on the
  132. assumption that the package under test requires a toolchain or architecture
  133. feature that is missing.
  134. In case failures are noticed, you can fix the package and just re-run the
  135. same command again; it will re-run the test where it failed. If you did
  136. specify a package (with -p), the package build dir will be removed first.
  137. The list of toolchains is retrieved from the Buildroot autobuilders, available
  138. at ${TOOLCHAINS_URL}.
  139. Options:
  140. -h, --help
  141. Print this help.
  142. -c CFG, --config-snippet CFG
  143. Use the CFG file as the source for the config snippet. This file
  144. should contain all the config options required to build a package.
  145. -d DIR, --build-dir DIR
  146. Do the builds in directory DIR, one sub-dir per toolchain.
  147. -p PKG, --package PKG
  148. Test-build the package PKG, by running 'make PKG'; if not specified,
  149. just runs 'make'.
  150. -r N, --random N
  151. Limit the tests to the N randomly selected toolchains, instead of
  152. building with all toolchains.
  153. Example:
  154. Testing libcec would require a config snippet that contains:
  155. BR2_PACKAGE_LIBCEC=y
  156. Testing libcurl with openSSL support would require a snippet such as:
  157. BR2_PACKAGE_OPENSSL=y
  158. BR2_PACKAGE_LIBCURL=y
  159. _EOF_
  160. }
  161. my_name="${0##*/}"
  162. main "${@}"