1 # Copyright 1999-2014 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 # @ECLASS: check-reqs.eclass
7 # QA Team <qa@gentoo.org>
9 # Bo Ørsted Andresen <zlin@gentoo.org>
10 # Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
11 # @BLURB: Provides a uniform way of handling ebuild which have very high build requirements
13 # This eclass provides a uniform way of handling ebuilds which have very high
14 # build requirements in terms of memory or disk space. It provides a function
15 # which should usually be called during pkg_setup().
17 # The chosen action only happens when the system's resources are detected
18 # correctly and only if they are below the threshold specified by the package.
21 # # need this much memory (does *not* check swap)
22 # CHECKREQS_MEMORY="256M"
24 # # need this much temporary build space
25 # CHECKREQS_DISK_BUILD="2G"
27 # # install will need this much space in /usr
28 # CHECKREQS_DISK_USR="1G"
30 # # install will need this much space in /var
31 # CHECKREQS_DISK_VAR="1024M"
35 # If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not
38 # These checks should probably mostly work on non-Linux, and they should
39 # probably degrade gracefully if they don't. Probably.
41 if [[ ! ${_CHECK_REQS_ECLASS_} ]]; then
45 # @ECLASS-VARIABLE: CHECKREQS_MEMORY
48 # How much RAM is needed? Eg.: CHECKREQS_MEMORY=15M
50 # @ECLASS-VARIABLE: CHECKREQS_DISK_BUILD
53 # How much diskspace is needed to build the package? Eg.: CHECKREQS_DISK_BUILD=2T
55 # @ECLASS-VARIABLE: CHECKREQS_DISK_USR
58 # How much space in /usr is needed to install the package? Eg.: CHECKREQS_DISK_USR=15G
60 # @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
63 # How much space is needed in /var? Eg.: CHECKREQS_DISK_VAR=3000M
65 EXPORT_FUNCTIONS pkg_setup
68 4|5|6) EXPORT_FUNCTIONS pkg_pretend ;;
69 *) die "EAPI=${EAPI} is not supported" ;;
72 # @FUNCTION: check_reqs
74 # Obsolete function executing all the checks and printing out results
76 debug-print-function ${FUNCNAME} "$@"
78 [[ ${EAPI:-0} == [012345] ]] || die "${FUNCNAME} is banned in EAPI > 5"
81 eqawarn "Package calling old ${FUNCNAME} function."
82 eqawarn "Please file a bug against the package."
83 eqawarn "It should call check-reqs_pkg_pretend and check-reqs_pkg_setup"
84 eqawarn "and possibly use EAPI=4 or later."
87 check-reqs_pkg_setup "$@"
90 # @FUNCTION: check-reqs_pkg_setup
92 # Exported function running the resources checks in pkg_setup phase.
93 # It should be run in both phases to ensure condition changes between
94 # pkg_pretend and pkg_setup won't affect the build.
95 check-reqs_pkg_setup() {
96 debug-print-function ${FUNCNAME} "$@"
103 # @FUNCTION: check-reqs_pkg_pretend
105 # Exported function running the resources checks in pkg_pretend phase.
106 check-reqs_pkg_pretend() {
107 debug-print-function ${FUNCNAME} "$@"
109 check-reqs_pkg_setup "$@"
112 # @FUNCTION: check-reqs_prepare
115 # Internal function that checks the variables that should be defined.
116 check-reqs_prepare() {
117 debug-print-function ${FUNCNAME} "$@"
119 if [[ -z ${CHECKREQS_MEMORY} &&
120 -z ${CHECKREQS_DISK_BUILD} &&
121 -z ${CHECKREQS_DISK_USR} &&
122 -z ${CHECKREQS_DISK_VAR} ]]; then
123 eerror "Set some check-reqs eclass variables if you want to use it."
124 eerror "If you are user and see this message file a bug against the package."
125 die "${FUNCNAME}: check-reqs eclass called but not actualy used!"
129 # @FUNCTION: check-reqs_run
132 # Internal function that runs the check based on variable settings.
134 debug-print-function ${FUNCNAME} "$@"
136 # some people are *censored*
137 unset CHECKREQS_FAILED
139 [[ ${EAPI:-0} == [0123] ]] && local MERGE_TYPE=""
141 # use != in test, because MERGE_TYPE only exists in EAPI 4 and later
142 if [[ ${MERGE_TYPE} != binary ]]; then
143 [[ -n ${CHECKREQS_MEMORY} ]] && \
147 [[ -n ${CHECKREQS_DISK_BUILD} ]] && \
150 "${CHECKREQS_DISK_BUILD}"
153 if [[ ${MERGE_TYPE} != buildonly ]]; then
154 [[ -n ${CHECKREQS_DISK_USR} ]] && \
157 "${CHECKREQS_DISK_USR}"
159 [[ -n ${CHECKREQS_DISK_VAR} ]] && \
162 "${CHECKREQS_DISK_VAR}"
166 # @FUNCTION: check-reqs_get_kibibytes
169 # Internal function that returns number in KiB.
170 # Returns 1024**2 for 1G or 1024**3 for 1T.
171 check-reqs_get_kibibytes() {
172 debug-print-function ${FUNCNAME} "$@"
174 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
177 local size=${1%[GMT]}
180 G) echo $((1024 * 1024 * size)) ;;
181 M) echo $((1024 * size)) ;;
182 T) echo $((1024 * 1024 * 1024 * size)) ;;
183 [0-9]) echo $((1024 * size)) ;;
185 die "${FUNCNAME}: Unknown unit: ${unit}"
190 # @FUNCTION: check-reqs_get_number
193 # Internal function that returns the numerical value without the unit.
194 # Returns "1" for "1G" or "150" for "150T".
195 check-reqs_get_number() {
196 debug-print-function ${FUNCNAME} "$@"
198 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
201 local size=${1%[GMT]}
203 [[ ${EAPI:-0} == [012345] ]] && msg=eqawarn
205 # Check for unset units and warn about them.
207 if [[ ${size} == ${1} ]]; then
208 ${msg} "Package does not specify unit for the size check"
209 ${msg} "File bug against the package. It should specify the unit."
215 # @FUNCTION: check-reqs_get_unit
218 # Internal function that return the unit without the numerical value.
219 # Returns "GiB" for "1G" or "TiB" for "150T".
220 check-reqs_get_unit() {
221 debug-print-function ${FUNCNAME} "$@"
223 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
229 [M0-9]) echo "MiB" ;;
232 die "${FUNCNAME}: Unknown unit: ${unit}"
237 # @FUNCTION: check-reqs_output
240 # Internal function that prints the warning and dies if required based on
242 check-reqs_output() {
243 debug-print-function ${FUNCNAME} "$@"
247 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
248 if [[ -n ${CHECKREQS_FAILED} ]]; then
250 ${msg} "Space constraints set in the ebuild were not met!"
251 ${msg} "The build will most probably fail, you should enhance the space"
252 ${msg} "as per failed tests."
255 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \
256 die "Build requirements not met!"
260 # @FUNCTION: check-reqs_memory
263 # Internal function that checks size of RAM.
264 check-reqs_memory() {
265 debug-print-function ${FUNCNAME} "$@"
267 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
272 check-reqs_start_phase \
276 if [[ -r /proc/meminfo ]] ; then
277 actual_memory=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
279 actual_memory=$(sysctl hw.physmem 2>/dev/null )
281 actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' )
283 if [[ -n ${actual_memory} ]] ; then
284 if [[ ${actual_memory} -lt $(check-reqs_get_kibibytes ${size}) ]] ; then
286 check-reqs_unsatisfied \
294 ewarn "Couldn't determine amount of memory, skipping..."
298 # @FUNCTION: check-reqs_disk
301 # Internal function that checks space on the harddrive.
303 debug-print-function ${FUNCNAME} "$@"
305 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]"
311 check-reqs_start_phase \
313 "disk space at \"${path}\""
315 space_kbi=$(df -Pk "${1}" 2>/dev/null | awk 'FNR == 2 {print $4}')
317 if [[ $? == 0 && -n ${space_kbi} ]] ; then
318 if [[ ${space_kbi} -lt $(check-reqs_get_kibibytes ${size}) ]] ; then
320 check-reqs_unsatisfied \
322 "disk space at \"${path}\""
328 ewarn "Couldn't determine disk space, skipping..."
332 # @FUNCTION: check-reqs_start_phase
335 # Internal function that inform about started check
336 check-reqs_start_phase() {
337 debug-print-function ${FUNCNAME} "$@"
339 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
343 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
345 ebegin "Checking for at least ${sizeunit} ${location}"
348 # @FUNCTION: check-reqs_unsatisfied
351 # Internal function that inform about check result.
352 # It has different output between pretend and setup phase,
353 # where in pretend phase it is fatal.
354 check-reqs_unsatisfied() {
355 debug-print-function ${FUNCNAME} "$@"
357 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
362 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
364 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
365 ${msg} "There is NOT at least ${sizeunit} ${location}"
367 # @ECLASS-VARIABLE: CHECKREQS_FAILED
370 # If set the checks failed and eclass should abort the build.
371 # Internal, do not set yourself.
372 CHECKREQS_FAILED="true"
375 _CHECK_REQS_ECLASS_=1