1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: check-reqs.eclass
6 # QA Team <qa@gentoo.org>
8 # Bo Ørsted Andresen <zlin@gentoo.org>
9 # Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
10 # @BLURB: Provides a uniform way of handling ebuild which have very high build requirements
12 # This eclass provides a uniform way of handling ebuilds which have very high
13 # build requirements in terms of memory or disk space. It provides a function
14 # which should usually be called during pkg_setup().
16 # The chosen action only happens when the system's resources are detected
17 # correctly and only if they are below the threshold specified by the package.
20 # # need this much memory (does *not* check swap)
21 # CHECKREQS_MEMORY="256M"
23 # # need this much temporary build space
24 # CHECKREQS_DISK_BUILD="2G"
26 # # install will need this much space in /usr
27 # CHECKREQS_DISK_USR="1G"
29 # # install will need this much space in /var
30 # CHECKREQS_DISK_VAR="1024M"
34 # If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not
37 # These checks should probably mostly work on non-Linux, and they should
38 # probably degrade gracefully if they don't. Probably.
40 if [[ ! ${_CHECK_REQS_ECLASS_} ]]; then
44 # @ECLASS-VARIABLE: CHECKREQS_MEMORY
47 # How much RAM is needed? Eg.: CHECKREQS_MEMORY=15M
49 # @ECLASS-VARIABLE: CHECKREQS_DISK_BUILD
52 # How much diskspace is needed to build the package? Eg.: CHECKREQS_DISK_BUILD=2T
54 # @ECLASS-VARIABLE: CHECKREQS_DISK_USR
57 # How much space in /usr is needed to install the package? Eg.: CHECKREQS_DISK_USR=15G
59 # @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
62 # How much space is needed in /var? Eg.: CHECKREQS_DISK_VAR=3000M
64 EXPORT_FUNCTIONS pkg_setup
67 4|5|6) EXPORT_FUNCTIONS pkg_pretend ;;
68 *) die "EAPI=${EAPI} is not supported" ;;
71 # @FUNCTION: check_reqs
73 # Obsolete function executing all the checks and printing out results
75 debug-print-function ${FUNCNAME} "$@"
77 [[ ${EAPI:-0} == [012345] ]] || die "${FUNCNAME} is banned in EAPI > 5"
80 eqawarn "Package calling old ${FUNCNAME} function."
81 eqawarn "Please file a bug against the package."
82 eqawarn "It should call check-reqs_pkg_pretend and check-reqs_pkg_setup"
83 eqawarn "and possibly use EAPI=4 or later."
86 check-reqs_pkg_setup "$@"
89 # @FUNCTION: check-reqs_pkg_setup
91 # Exported function running the resources checks in pkg_setup phase.
92 # It should be run in both phases to ensure condition changes between
93 # pkg_pretend and pkg_setup won't affect the build.
94 check-reqs_pkg_setup() {
95 debug-print-function ${FUNCNAME} "$@"
102 # @FUNCTION: check-reqs_pkg_pretend
104 # Exported function running the resources checks in pkg_pretend phase.
105 check-reqs_pkg_pretend() {
106 debug-print-function ${FUNCNAME} "$@"
108 check-reqs_pkg_setup "$@"
111 # @FUNCTION: check-reqs_prepare
114 # Internal function that checks the variables that should be defined.
115 check-reqs_prepare() {
116 debug-print-function ${FUNCNAME} "$@"
118 if [[ -z ${CHECKREQS_MEMORY} &&
119 -z ${CHECKREQS_DISK_BUILD} &&
120 -z ${CHECKREQS_DISK_USR} &&
121 -z ${CHECKREQS_DISK_VAR} ]]; then
122 eerror "Set some check-reqs eclass variables if you want to use it."
123 eerror "If you are user and see this message file a bug against the package."
124 die "${FUNCNAME}: check-reqs eclass called but not actualy used!"
128 # @FUNCTION: check-reqs_run
131 # Internal function that runs the check based on variable settings.
133 debug-print-function ${FUNCNAME} "$@"
135 # some people are *censored*
136 unset CHECKREQS_FAILED
138 [[ ${EAPI:-0} == [0123] ]] && local MERGE_TYPE=""
140 # use != in test, because MERGE_TYPE only exists in EAPI 4 and later
141 if [[ ${MERGE_TYPE} != binary ]]; then
142 [[ -n ${CHECKREQS_MEMORY} ]] && \
146 [[ -n ${CHECKREQS_DISK_BUILD} ]] && \
149 "${CHECKREQS_DISK_BUILD}"
152 if [[ ${MERGE_TYPE} != buildonly ]]; then
153 [[ -n ${CHECKREQS_DISK_USR} ]] && \
156 "${CHECKREQS_DISK_USR}"
158 [[ -n ${CHECKREQS_DISK_VAR} ]] && \
161 "${CHECKREQS_DISK_VAR}"
165 # @FUNCTION: check-reqs_get_kibibytes
168 # Internal function that returns number in KiB.
169 # Returns 1024**2 for 1G or 1024**3 for 1T.
170 check-reqs_get_kibibytes() {
171 debug-print-function ${FUNCNAME} "$@"
173 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
176 local size=${1%[GMT]}
179 G) echo $((1024 * 1024 * size)) ;;
180 M) echo $((1024 * size)) ;;
181 T) echo $((1024 * 1024 * 1024 * size)) ;;
182 [0-9]) echo $((1024 * size)) ;;
184 die "${FUNCNAME}: Unknown unit: ${unit}"
189 # @FUNCTION: check-reqs_get_number
192 # Internal function that returns the numerical value without the unit.
193 # Returns "1" for "1G" or "150" for "150T".
194 check-reqs_get_number() {
195 debug-print-function ${FUNCNAME} "$@"
197 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
200 local size=${1%[GMT]}
202 [[ ${EAPI:-0} == [012345] ]] && msg=eqawarn
204 # Check for unset units and warn about them.
206 if [[ ${size} == ${1} ]]; then
207 ${msg} "Package does not specify unit for the size check"
208 ${msg} "File bug against the package. It should specify the unit."
214 # @FUNCTION: check-reqs_get_unit
217 # Internal function that returns the unit without the numerical value.
218 # Returns "GiB" for "1G" or "TiB" for "150T".
219 check-reqs_get_unit() {
220 debug-print-function ${FUNCNAME} "$@"
222 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
228 [M0-9]) echo "MiB" ;;
231 die "${FUNCNAME}: Unknown unit: ${unit}"
236 # @FUNCTION: check-reqs_output
239 # Internal function that prints the warning and dies if required based on
241 check-reqs_output() {
242 debug-print-function ${FUNCNAME} "$@"
246 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
247 if [[ -n ${CHECKREQS_FAILED} ]]; then
249 ${msg} "Space constraints set in the ebuild were not met!"
250 ${msg} "The build will most probably fail, you should enhance the space"
251 ${msg} "as per failed tests."
254 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \
255 die "Build requirements not met!"
259 # @FUNCTION: check-reqs_memory
262 # Internal function that checks size of RAM.
263 check-reqs_memory() {
264 debug-print-function ${FUNCNAME} "$@"
266 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
271 check-reqs_start_phase \
275 if [[ -r /proc/meminfo ]] ; then
276 actual_memory=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
278 actual_memory=$(sysctl hw.physmem 2>/dev/null )
280 actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' )
282 if [[ -n ${actual_memory} ]] ; then
283 if [[ ${actual_memory} -lt $(check-reqs_get_kibibytes ${size}) ]] ; then
285 check-reqs_unsatisfied \
293 ewarn "Couldn't determine amount of memory, skipping..."
297 # @FUNCTION: check-reqs_disk
300 # Internal function that checks space on the harddrive.
302 debug-print-function ${FUNCNAME} "$@"
304 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]"
310 check-reqs_start_phase \
312 "disk space at \"${path}\""
314 space_kbi=$(df -Pk "${1}" 2>/dev/null | awk 'FNR == 2 {print $4}')
316 if [[ $? == 0 && -n ${space_kbi} ]] ; then
317 if [[ ${space_kbi} -lt $(check-reqs_get_kibibytes ${size}) ]] ; then
319 check-reqs_unsatisfied \
321 "disk space at \"${path}\""
327 ewarn "Couldn't determine disk space, skipping..."
331 # @FUNCTION: check-reqs_start_phase
334 # Internal function that inform about started check
335 check-reqs_start_phase() {
336 debug-print-function ${FUNCNAME} "$@"
338 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
342 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
344 ebegin "Checking for at least ${sizeunit} ${location}"
347 # @FUNCTION: check-reqs_unsatisfied
350 # Internal function that inform about check result.
351 # It has different output between pretend and setup phase,
352 # where in pretend phase it is fatal.
353 check-reqs_unsatisfied() {
354 debug-print-function ${FUNCNAME} "$@"
356 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
361 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
363 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
364 ${msg} "There is NOT at least ${sizeunit} ${location}"
366 # @ECLASS-VARIABLE: CHECKREQS_FAILED
369 # If set the checks failed and eclass should abort the build.
370 # Internal, do not set yourself.
371 CHECKREQS_FAILED="true"
374 _CHECK_REQS_ECLASS_=1