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.
43 # @ECLASS-VARIABLE: CHECKREQS_MEMORY
46 # How much RAM is needed? Eg.: CHECKREQS_MEMORY=15M
48 # @ECLASS-VARIABLE: CHECKREQS_DISK_BUILD
51 # How much diskspace is needed to build the package? Eg.: CHECKREQS_DISK_BUILD=2T
53 # @ECLASS-VARIABLE: CHECKREQS_DISK_USR
56 # How much space in /usr is needed to install the package? Eg.: CHECKREQS_DISK_USR=15G
58 # @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
61 # How much space is needed in /var? Eg.: CHECKREQS_DISK_VAR=3000M
63 EXPORT_FUNCTIONS pkg_setup
66 4|5) EXPORT_FUNCTIONS pkg_pretend ;;
67 *) die "EAPI=${EAPI} is not supported" ;;
70 # @FUNCTION: check_reqs
72 # Obsolete function executing all the checks and priting out results
74 debug-print-function ${FUNCNAME} "$@"
77 ewarn "QA: Package calling old ${FUNCNAME} function."
78 ewarn "QA: Please file a bug against the package."
79 ewarn "QA: It should call check-reqs_pkg_pretend and check-reqs_pkg_setup"
80 ewarn "QA: and possibly use EAPI=4 or later."
83 check-reqs_pkg_setup "$@"
86 # @FUNCTION: check-reqs_pkg_setup
88 # Exported function running the resources checks in pkg_setup phase.
89 # It should be run in both phases to ensure condition changes between
90 # pkg_pretend and pkg_setup won't affect the build.
91 check-reqs_pkg_setup() {
92 debug-print-function ${FUNCNAME} "$@"
99 # @FUNCTION: check-reqs_pkg_pretend
101 # Exported function running the resources checks in pkg_pretend phase.
102 check-reqs_pkg_pretend() {
103 debug-print-function ${FUNCNAME} "$@"
105 check-reqs_pkg_setup "$@"
108 # @FUNCTION: check-reqs_prepare
110 # Internal function that checks the variables that should be defined.
111 check-reqs_prepare() {
112 debug-print-function ${FUNCNAME} "$@"
114 if [[ -z ${CHECKREQS_MEMORY} &&
115 -z ${CHECKREQS_DISK_BUILD} &&
116 -z ${CHECKREQS_DISK_USR} &&
117 -z ${CHECKREQS_DISK_VAR} ]]; then
118 eerror "Set some check-reqs eclass variables if you want to use it."
119 eerror "If you are user and see this message file a bug against the package."
120 die "${FUNCNAME}: check-reqs eclass called but not actualy used!"
124 # @FUNCTION: check-reqs_run
126 # Internal function that runs the check based on variable settings.
128 debug-print-function ${FUNCNAME} "$@"
130 # some people are *censored*
131 unset CHECKREQS_FAILED
133 # use != in test, because MERGE_TYPE only exists in EAPI 4 and later
134 if [[ ${MERGE_TYPE} != binary ]]; then
135 [[ -n ${CHECKREQS_MEMORY} ]] && \
139 [[ -n ${CHECKREQS_DISK_BUILD} ]] && \
142 "${CHECKREQS_DISK_BUILD}"
145 if [[ ${MERGE_TYPE} != buildonly ]]; then
146 [[ -n ${CHECKREQS_DISK_USR} ]] && \
149 "${CHECKREQS_DISK_USR}"
151 [[ -n ${CHECKREQS_DISK_VAR} ]] && \
154 "${CHECKREQS_DISK_VAR}"
158 # @FUNCTION: check-reqs_get_mebibytes
160 # Internal function that returns number in mebibytes.
161 # Returns 1024 for 1G or 1048576 for 1T.
162 check-reqs_get_mebibytes() {
163 debug-print-function ${FUNCNAME} "$@"
165 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
168 local size=${1%[GMT]}
171 G) echo $((1024 * size)) ;;
172 [M0-9]) echo ${size} ;;
173 T) echo $((1024 * 1024 * size)) ;;
175 die "${FUNCNAME}: Unknown unit: ${unit}"
180 # @FUNCTION: check-reqs_get_number
182 # Internal function that returns the numerical value without the unit.
183 # Returns "1" for "1G" or "150" for "150T".
184 check-reqs_get_number() {
185 debug-print-function ${FUNCNAME} "$@"
187 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
190 local size=${1%[GMT]}
192 # Check for unset units and warn about them.
194 if [[ ${size} == ${1} ]]; then
195 ewarn "QA: Package does not specify unit for the size check"
196 ewarn "QA: Assuming mebibytes."
197 ewarn "QA: File bug against the package. It should specify the unit."
203 # @FUNCTION: check-reqs_get_unit
205 # Internal function that return the unit without the numerical value.
206 # Returns "GiB" for "1G" or "TiB" for "150T".
207 check-reqs_get_unit() {
208 debug-print-function ${FUNCNAME} "$@"
210 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
216 [M0-9]) echo "MiB" ;;
219 die "${FUNCNAME}: Unknown unit: ${unit}"
224 # @FUNCTION: check-reqs_output
226 # Internal function that prints the warning and dies if required based on
228 check-reqs_output() {
229 debug-print-function ${FUNCNAME} "$@"
233 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
234 if [[ -n ${CHECKREQS_FAILED} ]]; then
236 ${msg} "Space constraints set in the ebuild were not met!"
237 ${msg} "The build will most probably fail, you should enhance the space"
238 ${msg} "as per failed tests."
241 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \
242 die "Build requirements not met!"
246 # @FUNCTION: check-reqs_memory
248 # Internal function that checks size of RAM.
249 check-reqs_memory() {
250 debug-print-function ${FUNCNAME} "$@"
252 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
257 check-reqs_start_phase \
261 if [[ -r /proc/meminfo ]] ; then
262 actual_memory=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
264 actual_memory=$(sysctl hw.physmem 2>/dev/null )
266 actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' )
268 if [[ -n ${actual_memory} ]] ; then
269 if [[ ${actual_memory} -lt $((1024 * $(check-reqs_get_mebibytes ${size}))) ]] ; then
271 check-reqs_unsatisfied \
279 ewarn "Couldn't determine amount of memory, skipping..."
283 # @FUNCTION: check-reqs_disk
285 # Internal function that checks space on the harddrive.
287 debug-print-function ${FUNCNAME} "$@"
289 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]"
295 check-reqs_start_phase \
297 "disk space at \"${path}\""
299 space_megs=$(df -Pm "${1}" 2>/dev/null | awk 'FNR == 2 {print $4}')
301 if [[ $? == 0 && -n ${space_megs} ]] ; then
302 if [[ ${space_megs} -lt $(check-reqs_get_mebibytes ${size}) ]] ; then
304 check-reqs_unsatisfied \
306 "disk space at \"${path}\""
312 ewarn "Couldn't determine disk space, skipping..."
316 # @FUNCTION: check-reqs_start_phase
318 # Internal function that inform about started check
319 check-reqs_start_phase() {
320 debug-print-function ${FUNCNAME} "$@"
322 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
326 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
328 ebegin "Checking for at least ${sizeunit} ${location}"
331 # @FUNCTION: check-reqs_unsatisfied
333 # Internal function that inform about check result.
334 # It has different output between pretend and setup phase,
335 # where in pretend phase it is fatal.
336 check-reqs_unsatisfied() {
337 debug-print-function ${FUNCNAME} "$@"
339 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
344 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
346 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
347 ${msg} "There is NOT at least ${sizeunit} ${location}"
349 # @ECLASS-VARIABLE: CHECKREQS_FAILED
352 # If set the checks failed and eclass should abort the build.
353 # Internal, do not set yourself.
354 CHECKREQS_FAILED="true"