test-pkg 5.2 KB

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