test-pkg 5.4 KB

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