/[gentoo-x86]/eclass/check-reqs.eclass
Gentoo

Diff of /eclass/check-reqs.eclass

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.7 Revision 1.11
1# Copyright 1999-2008 Gentoo Foundation 1# Copyright 1999-2012 Gentoo Foundation
2# Distributed under the terms of the GNU General Public License v2 2# Distributed under the terms of the GNU General Public License v2
3# $Header: /var/cvsroot/gentoo-x86/eclass/check-reqs.eclass,v 1.7 2010/08/22 21:18:03 halcy0n Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/check-reqs.eclass,v 1.11 2012/09/27 16:35:41 axs Exp $
4 4
5# @ECLASS: check-reqs.eclass 5# @ECLASS: check-reqs.eclass
6# @MAINTAINER: 6# @MAINTAINER:
7# QA Team <qa@gentoo.org>
8# @AUTHOR:
7# Bo ├śrsted Andresen <zlin@gentoo.org> 9# Bo ├śrsted Andresen <zlin@gentoo.org>
8#
9# Original Author: Ciaran McCreesh <ciaranm@gentoo.org> 10# Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
10# @BLURB: Provides a uniform way of handling ebuild which have very high build requirements 11# @BLURB: Provides a uniform way of handling ebuild which have very high build requirements
11# @DESCRIPTION: 12# @DESCRIPTION:
12# This eclass provides a uniform way of handling ebuilds which have very high 13# 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# build requirements in terms of memory or disk space. It provides a function
14# which should usually be called during pkg_setup(). 15# which should usually be called during pkg_setup().
15# 16#
16# From a user perspective, the variable CHECKREQS_ACTION can be set to:
17# * "warn" (default), which will display a warning and wait for 15s
18# * "error", which will make the ebuild error out
19# * "ignore", which will not take any action
20#
21# The chosen action only happens when the system's resources are detected 17# The chosen action only happens when the system's resources are detected
22# correctly and only if they are below the threshold specified by the package. 18# correctly and only if they are below the threshold specified by the package.
23# 19#
24# For ebuild authors: only use this eclass if you reaaalllllly have stupidly
25# high build requirements. At an absolute minimum, you shouldn't be using this
26# unless the ebuild needs >256MBytes RAM or >1GByte temporary or install space.
27# The code should look something like:
28#
29# @CODE 20# @CODE
30# pkg_setup() {
31# # values in MBytes
32#
33# # need this much memory (does *not* check swap) 21# # need this much memory (does *not* check swap)
34# CHECKREQS_MEMORY="256" 22# CHECKREQS_MEMORY="256M"
35# 23#
36# # need this much temporary build space 24# # need this much temporary build space
37# CHECKREQS_DISK_BUILD="2048" 25# CHECKREQS_DISK_BUILD="2G"
38# 26#
39# # install will need this much space in /usr 27# # install will need this much space in /usr
40# CHECKREQS_DISK_USR="1024" 28# CHECKREQS_DISK_USR="1G"
41# 29#
42# # install will need this much space in /var 30# # install will need this much space in /var
43# CHECKREQS_DISK_VAR="1024" 31# CHECKREQS_DISK_VAR="1024M"
44# 32#
45# # go!
46# check_reqs
47# }
48# @CODE 33# @CODE
49# 34#
50# Alternatively, the check_reqs_conditional function can be used to carry out
51# alternate actions (e.g. using a much slower but far less memory intensive
52# build option that gives the same end result).
53#
54# You should *not* override the user's CHECKREQS_ACTION setting, nor should you
55# attempt to provide a value if it is unset. Note that the environment variables
56# are used rather than parameters for a few reasons:
57# * easier to do if use blah ; then things
58# * we might add in additional requirements things later
59# If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not 35# If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not
60# carried out. 36# carried out.
61# 37#
62# These checks should probably mostly work on non-Linux, and they should 38# These checks should probably mostly work on non-Linux, and they should
63# probably degrade gracefully if they don't. Probably. 39# probably degrade gracefully if they don't. Probably.
64 40
65inherit eutils 41inherit eutils
66 42
67# @ECLASS-VARIABLE: CHECKREQS_MEMORY 43# @ECLASS-VARIABLE: CHECKREQS_MEMORY
44# @DEFAULT_UNSET
68# @DESCRIPTION: 45# @DESCRIPTION:
69# How much RAM is needed in MB? 46# How much RAM is needed? Eg.: CHECKREQS_MEMORY=15M
70 47
71# @ECLASS-VARIABLE: CHECKREQS_DISK_BUILD 48# @ECLASS-VARIABLE: CHECKREQS_DISK_BUILD
49# @DEFAULT_UNSET
72# @DESCRIPTION: 50# @DESCRIPTION:
73# How much diskspace is needed to build the package? In MB 51# How much diskspace is needed to build the package? Eg.: CHECKREQS_DISK_BUILD=2T
74 52
75# @ECLASS-VARIABLE: CHECKREQS_DISK_USR 53# @ECLASS-VARIABLE: CHECKREQS_DISK_USR
54# @DEFAULT_UNSET
76# @DESCRIPTION: 55# @DESCRIPTION:
77# How much space in /usr is needed to install the package? In MB 56# How much space in /usr is needed to install the package? Eg.: CHECKREQS_DISK_USR=15G
78 57
79# @ECLASS-VARIABLE: CHECKREQS_DISK_VAR 58# @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
59# @DEFAULT_UNSET
80# @DESCRIPTION: 60# @DESCRIPTION:
81# How much space is needed in /var? In MB 61# How much space is needed in /var? Eg.: CHECKREQS_DISK_VAR=3000M
62
63EXPORT_FUNCTIONS pkg_setup
64case "${EAPI:-0}" in
65 0|1|2|3) ;;
66 4|5) EXPORT_FUNCTIONS pkg_pretend ;;
67 *) die "EAPI=${EAPI} is not supported" ;;
68esac
82 69
83# @FUNCTION: check_reqs 70# @FUNCTION: check_reqs
84# @DESCRIPTION: 71# @DESCRIPTION:
85# Checks the requirements given in the specific variables. If not reached, 72# Obsolete function executing all the checks and priting out results
86# either prints a warning or dies.
87check_reqs() { 73check_reqs() {
88 [[ -n "${1}" ]] && die "Usage: check_reqs" 74 debug-print-function ${FUNCNAME} "$@"
89 75
90 export CHECKREQS_NEED_SLEEP="" CHECKREQS_NEED_DIE=""
91 if [[ "$CHECKREQS_ACTION" != "ignore" ]] ; then
92 [[ -n "$CHECKREQS_MEMORY" ]] && check_build_memory
93 [[ -n "$CHECKREQS_DISK_BUILD" ]] && check_build_disk \
94 "${T}" "${CHECKREQS_DISK_BUILD}"
95 [[ -n "$CHECKREQS_DISK_USR" ]] && check_build_disk \
96 "${ROOT}/usr" "${CHECKREQS_DISK_USR}"
97 [[ -n "$CHECKREQS_DISK_VAR" ]] && check_build_disk \
98 "${ROOT}/var" "${CHECKREQS_DISK_VAR}"
99 fi
100
101 if [[ -n "${CHECKREQS_NEED_SLEEP}" ]] ; then
102 echo 76 echo
103 ewarn "Bad things may happen! You may abort the build by pressing ctrl+c in" 77 ewarn "QA: Package calling old ${FUNCNAME} function."
104 ewarn "the next 15 seconds." 78 ewarn "QA: Please file a bug against the package."
105 ewarn " " 79 ewarn "QA: It should call check-reqs_pkg_pretend and check-reqs_pkg_setup"
106 einfo "To make this kind of warning a fatal error, add a line to /etc/make.conf" 80 ewarn "QA: and possibly use EAPI=4 or later."
107 einfo "setting CHECKREQS_ACTION=\"error\". To skip build requirements checking," 81 echo
108 einfo "set CHECKREQS_ACTION=\"ignore\"."
109 epause 15
110 fi
111 82
83 check-reqs_pkg_setup "$@"
84}
85
86# @FUNCTION: check-reqs_pkg_setup
87# @DESCRIPTION:
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.
91check-reqs_pkg_setup() {
92 debug-print-function ${FUNCNAME} "$@"
93
94 check-reqs_prepare
95 check-reqs_run
96 check-reqs_output
97}
98
99# @FUNCTION: check-reqs_pkg_pretend
100# @DESCRIPTION:
101# Exported function running the resources checks in pkg_pretend phase.
102check-reqs_pkg_pretend() {
103 debug-print-function ${FUNCNAME} "$@"
104
105 check-reqs_pkg_setup "$@"
106}
107
108# @FUNCTION: check-reqs_prepare
109# @DESCRIPTION:
110# Internal function that checks the variables that should be defined.
111check-reqs_prepare() {
112 debug-print-function ${FUNCNAME} "$@"
113
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!"
121 fi
122}
123
124# @FUNCTION: check-reqs_run
125# @DESCRIPTION:
126# Internal function that runs the check based on variable settings.
127check-reqs_run() {
128 debug-print-function ${FUNCNAME} "$@"
129
130 # some people are *censored*
131 unset CHECKREQS_FAILED
132
133 [[ -n ${CHECKREQS_MEMORY} ]] && \
134 check-reqs_memory \
135 ${CHECKREQS_MEMORY}
136
137 [[ -n ${CHECKREQS_DISK_BUILD} ]] && \
138 check-reqs_disk \
139 "${T}" \
140 "${CHECKREQS_DISK_BUILD}"
141
142 [[ -n ${CHECKREQS_DISK_USR} ]] && \
143 check-reqs_disk \
144 "${EROOT}/usr" \
145 "${CHECKREQS_DISK_USR}"
146
147 [[ -n ${CHECKREQS_DISK_VAR} ]] && \
148 check-reqs_disk \
149 "${EROOT}/var" \
150 "${CHECKREQS_DISK_VAR}"
151}
152
153# @FUNCTION: check-reqs_get_mebibytes
154# @DESCRIPTION:
155# Internal function that returns number in mebibytes.
156# Converts from 1G=1024 or 1T=1048576
157check-reqs_get_mebibytes() {
158 debug-print-function ${FUNCNAME} "$@"
159
160 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
161
162 local unit=${1:(-1)}
163 local size=${1%[GMT]}
164
165 case ${unit} in
166 G) echo $((1024 * size)) ;;
167 [M0-9]) echo ${size} ;;
168 T) echo $((1024 * 1024 * size)) ;;
169 *)
170 die "${FUNCNAME}: Unknown unit: ${unit}"
171 ;;
172 esac
173}
174
175# @FUNCTION: check-reqs_get_number
176# @DESCRIPTION:
177# Internal function that returns number without the unit.
178# Converts from 1G=1 or 150T=150.
179check-reqs_get_number() {
180 debug-print-function ${FUNCNAME} "$@"
181
182 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
183
184 local unit=${1:(-1)}
185 local size=${1%[GMT]}
186
187 # Check for unset units and warn about them.
188 # Backcompat.
189 if [[ ${size} == ${1} ]]; then
190 ewarn "QA: Package does not specify unit for the size check"
191 ewarn "QA: Assuming mebibytes."
192 ewarn "QA: File bug against the package. It should specify the unit."
193 fi
194
195 echo ${size}
196}
197
198# @FUNCTION: check-reqs_get_unit
199# @DESCRIPTION:
200# Internal function that returns number without the unit.
201# Converts from 1G=1 or 150T=150.
202check-reqs_get_unit() {
203 debug-print-function ${FUNCNAME} "$@"
204
205 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
206
207 local unit=${1:(-1)}
208
209 case ${unit} in
210 G) echo "gibibytes" ;;
211 [M0-9]) echo "mebibytes" ;;
212 T) echo "tebibytes" ;;
213 *)
214 die "${FUNCNAME}: Unknown unit: ${unit}"
215 ;;
216 esac
217}
218
219# @FUNCTION: check-reqs_output
220# @DESCRIPTION:
221# Internal function that prints the warning and dies if required based on
222# the test results.
223check-reqs_output() {
224 debug-print-function ${FUNCNAME} "$@"
225
226 local msg="ewarn"
227
228 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
112 if [[ -n "${CHECKREQS_NEED_DIE}" ]] ; then 229 if [[ -n ${CHECKREQS_FAILED} ]]; then
113 eerror "Bailing out as specified by CHECKREQS_ACTION" 230 ${msg}
231 ${msg} "Space constrains set in the ebuild were not met!"
232 ${msg} "The build will most probably fail, you should enhance the space"
233 ${msg} "as per failed tests."
234 ${msg}
235
236 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \
114 die "Build requirements not met" 237 die "Build requirements not met!"
115 fi 238 fi
116} 239}
117 240
118# @FUNCTION: check_reqs_conditional 241# @FUNCTION: check-reqs_memory
119# @RETURN: True if requirements check passed, else False
120# @DESCRIPTION: 242# @DESCRIPTION:
121# Checks the requirements given in the specific variables 243# Internal function that checks size of RAM.
122check_reqs_conditional() { 244check-reqs_memory() {
123 [[ -n "${1}" ]] && die "Usage: check_reqs" 245 debug-print-function ${FUNCNAME} "$@"
124 246
125 export CHECKREQS_NEED_SLEEP="" CHECKREQS_NEED_DIE="" 247 [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
126 if [[ "$CHECKREQS_ACTION" != "ignore" ]] ; then
127 [[ -n "$CHECKREQS_MEMORY" ]] && check_build_memory
128 [[ -n "$CHECKREQS_DISK_BUILD" ]] && check_build_disk \
129 "${T}" "${CHECKREQS_DISK_BUILD}"
130 [[ -n "$CHECKREQS_DISK_USR" ]] && check_build_disk \
131 "${ROOT}/usr" "${CHECKREQS_DISK_USR}"
132 [[ -n "$CHECKREQS_DISK_VAR" ]] && check_build_disk \
133 "${ROOT}/var" "${CHECKREQS_DISK_VAR}"
134 fi
135 248
136 [[ -z "${CHECKREQS_NEED_SLEEP}" && -z "${CHECKREQS_NEED_DIE}" ]] 249 local size=${1}
137} 250 local actual_memory
138 251
139# internal use only! 252 check-reqs_start_phase \
140check_build_memory() { 253 ${size} \
141 [[ -n "${1}" ]] && die "Usage: check_build_memory" 254 "RAM"
142 check_build_msg_begin "${CHECKREQS_MEMORY}" "MBytes" "RAM" 255
143 if [[ -r /proc/meminfo ]] ; then 256 if [[ -r /proc/meminfo ]] ; then
144 actual_memory=$(sed -n -e '/MemTotal:/s/^[^:]*: *\([0-9]\+\) kB/\1/p' \ 257 actual_memory=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
145 /proc/meminfo)
146 else 258 else
147 actual_memory=$(sysctl hw.physmem 2>/dev/null ) 259 actual_memory=$(sysctl hw.physmem 2>/dev/null )
148 [[ "$?" == "0" ]] && 260 [[ "$?" == "0" ]] &&
149 actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' ) 261 actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' )
150 fi 262 fi
151 if [[ -n "${actual_memory}" ]] ; then 263 if [[ -n ${actual_memory} ]] ; then
152 if [[ ${actual_memory} -lt $((1024 * ${CHECKREQS_MEMORY})) ]] ; then 264 if [[ ${actual_memory} -lt $((1024 * $(check-reqs_get_mebibytes ${size}))) ]] ; then
153 eend 1 265 eend 1
154 check_build_msg_ick "${CHECKREQS_MEMORY}" "MBytes" "RAM" 266 check-reqs_unsatisfied \
267 ${size} \
268 "RAM"
155 else 269 else
156 eend 0 270 eend 0
157 fi 271 fi
158 else 272 else
159 eend 1 273 eend 1
160 ewarn "Couldn't determine amount of memory, skipping ..." 274 ewarn "Couldn't determine amount of memory, skipping..."
161 fi 275 fi
162} 276}
163 277
164# internal use only! 278# @FUNCTION: check-reqs_disk
165check_build_disk() { 279# @DESCRIPTION:
166 [[ -z "${2}" ]] && die "Usage: check_build_disk where name needed" 280# Internal function that checks space on the harddrive.
167 check_build_msg_begin "${2}" "MBytes" \ 281check-reqs_disk() {
282 debug-print-function ${FUNCNAME} "$@"
283
284 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]"
285
286 local path=${1}
287 local size=${2}
288 local space_megs
289
290 check-reqs_start_phase \
291 ${size} \
168 "disk space at ${1}" 292 "disk space at \"${path}\""
169 actual_space=$(df -Pm ${1} 2>/dev/null | sed -n \ 293
170 '$s/\(\S\+\s\+\)\{3\}\([0-9]\+\).*/\2/p' 2>/dev/null ) 294 space_megs=$(df -Pm "${1}" 2>/dev/null | awk 'FNR == 2 {print $4}')
295
171 if [[ "$?" == "0" && -n "${actual_space}" ]] ; then 296 if [[ $? == 0 && -n ${space_megs} ]] ; then
172 if [[ ${actual_space} -lt ${2} ]] ; then 297 if [[ ${space_megs} -lt $(check-reqs_get_mebibytes ${size}) ]] ; then
173 eend 1 298 eend 1
174 check_build_msg_ick "${2}" "MBytes" \ 299 check-reqs_unsatisfied \
300 ${size} \
175 "disk space at ${1}" 301 "disk space at \"${path}\""
176 else 302 else
177 eend 0 303 eend 0
178 fi 304 fi
179 else 305 else
180 eend 1 306 eend 1
181 ewarn "Couldn't figure out disk space, skipping ..." 307 ewarn "Couldn't determine disk space, skipping..."
182 fi 308 fi
183} 309}
184 310
185# internal use only! 311# @FUNCTION: check-reqs_start_phase
186check_build_msg_begin() { 312# @DESCRIPTION:
313# Internal function that inform about started check
314check-reqs_start_phase() {
315 debug-print-function ${FUNCNAME} "$@"
316
317 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
318
319 local size=${1}
320 local location=${2}
321 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
322
187 ebegin "Checking for at least ${1}${2} ${3}" 323 ebegin "Checking for at least ${sizeunit} ${location}"
188} 324}
189 325
190# internal use only! 326# @FUNCTION: check-reqs_unsatisfied
191check_build_msg_skip() { 327# @DESCRIPTION:
192 ewarn "Skipping check for at least ${1}${2} ${3}" 328# Internal function that inform about check result.
193} 329# It has different output between pretend and setup phase,
330# where in pretend phase it is fatal.
331check-reqs_unsatisfied() {
332 debug-print-function ${FUNCNAME} "$@"
194 333
195# internal use only! 334 [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
196check_build_msg_ick() {
197 if [[ "${CHECKREQS_ACTION}" == "error" ]] ; then
198 eerror "Don't have at least ${1}${2} ${3}"
199 echo
200 export CHECKREQS_NEED_DIE="yes"
201 else
202 ewarn "Don't have at least ${1}${2} ${3}"
203 echo
204 export CHECKREQS_NEED_SLEEP="yes"
205 fi
206}
207 335
336 local msg="ewarn"
337 local size=${1}
338 local location=${2}
339 local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
340
341 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
342 ${msg} "There is NOT at least ${sizeunit} ${location}"
343
344 # @ECLASS-VARIABLE: CHECKREQS_FAILED
345 # @DESCRIPTION:
346 # @INTERNAL
347 # If set the checks failed and eclass should abort the build.
348 # Internal, do not set yourself.
349 CHECKREQS_FAILED="true"
350}
351

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.11

  ViewVC Help
Powered by ViewVC 1.1.20