Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 358913 | Differences between
and this patch

Collapse All | Expand All

(-)check-reqs.eclass (-109 / +278 lines)
Lines 4-11 Link Here
4
4
5
# @ECLASS: check-reqs.eclass
5
# @ECLASS: check-reqs.eclass
6
# @MAINTAINER:
6
# @MAINTAINER:
7
# Bo Ørsted Andresen <zlin@gentoo.org>
7
# QA Team <qa@gentoo.org>
8
# @AUTHOR:
8
# @AUTHOR:
9
# Bo Ørsted Andresen <zlin@gentoo.org>
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:
Lines 13-61 Link Here
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!
33
#     # go!
46
#     check_reqs
34
# pkg_pretend() {
35
#    check-reqs_pkg_pretend
36
# }
37
# 
38
# # Run once again to ensure that environment didn't
39
# # change since the pretend phase.
40
# pkg_setup() {
41
#    check-reqs_pkg_setup
47
# }
42
# }
48
# @CODE
43
# @CODE
49
#
44
#
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
45
# If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not
60
# carried out.
46
# carried out.
61
#
47
#
Lines 66-145 Link Here
66
52
67
# @ECLASS-VARIABLE: CHECKREQS_MEMORY
53
# @ECLASS-VARIABLE: CHECKREQS_MEMORY
68
# @DESCRIPTION:
54
# @DESCRIPTION:
69
# How much RAM is needed in MB?
55
# @DEAULT_UNSET
56
# How much RAM is needed?
70
57
71
# @ECLASS-VARIABLE:  CHECKREQS_DISK_BUILD
58
# @ECLASS-VARIABLE:  CHECKREQS_DISK_BUILD
72
# @DESCRIPTION:
59
# @DESCRIPTION:
73
# How much diskspace is needed to build the package? In MB
60
# @DEAULT_UNSET
61
# How much diskspace is needed to build the package?
74
62
75
# @ECLASS-VARIABLE: CHECKREQS_DISK_USR
63
# @ECLASS-VARIABLE: CHECKREQS_DISK_USR
76
# @DESCRIPTION:
64
# @DESCRIPTION:
77
# How much space in /usr is needed to install the package? In MB
65
# @DEAULT_UNSET
66
# How much space in /usr is needed to install the package?
78
67
79
# @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
68
# @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
80
# @DESCRIPTION:
69
# @DESCRIPTION:
81
# How much space is needed in /var? In MB
70
# @DEAULT_UNSET
71
# How much space is needed in /var?
72
73
CHECKREQS_EXPORTED_FUNCTIONS="pkg_setup"
74
case "${EAPI:-0}" in
75
	0|1|2|3) ;;
76
	4) CHECKREQS_EXPORTED_FUNCTIONS="${EXPORTED_FUNCTIONS} pkg_pretend" ;;
77
	*) die "EAPI=${EAPI} is not supported" ;;
78
esac
82
79
83
# @FUNCTION: check_reqs
80
# @FUNCTION: check_reqs
84
# @DESCRIPTION:
81
# @DESCRIPTION:
85
# Checks the requirements given in the specific variables. If not reached,
82
# Obsolete function executing all the checks and priting out results
86
# either prints a warning or dies.
87
check_reqs() {
83
check_reqs() {
88
	[[ -n "${1}" ]] && die "Usage: check_reqs"
84
	debug-print-function ${FUNCNAME} "$@"
85
86
	echo
87
	ewarn "QA: Package calling old ${FUNCNAME} function."
88
	ewarn "QA: Please file a bug against the package."
89
	ewarn "QA: It should call check-reqs_pkg_pretend and check-reqs_pkg_setup"
90
	ewarn "QA: and possibly use EAPI=4 or later."
91
	echo
92
93
	check-reqs_pkg_setup "$@"
94
}
89
95
90
	export CHECKREQS_NEED_SLEEP="" CHECKREQS_NEED_DIE=""
96
# @FUNCTION: check-reqs_pkg_setup
91
	if [[ "$CHECKREQS_ACTION" != "ignore" ]] ; then
97
# @DESCRIPTION:
92
		[[ -n "$CHECKREQS_MEMORY" ]] && check_build_memory
98
# Exported function running the resources checks in pkg_setup phase.
93
		[[ -n "$CHECKREQS_DISK_BUILD" ]] && check_build_disk \
99
# It should be run in both phases to ensure condition changes between
94
			"${T}" "${CHECKREQS_DISK_BUILD}"
100
# pkg_pretend and pkg_setup won't affect the build.
95
		[[ -n "$CHECKREQS_DISK_USR" ]] && check_build_disk \
101
check-reqs_pkg_setup() {
96
			"${ROOT}/usr" "${CHECKREQS_DISK_USR}"
102
	debug-print-function ${FUNCNAME} "$@"
97
		[[ -n "$CHECKREQS_DISK_VAR" ]] && check_build_disk \
103
98
			"${ROOT}/var" "${CHECKREQS_DISK_VAR}"
104
	check-reqs_prepare
105
	check-reqs_run
106
	check-reqs_output
107
}
108
109
# @FUNCTION: check-reqs_pkg_pretend
110
# @DESCRIPTION:
111
# Exported function running the resources checks in pkg_pretend phase.
112
check-reqs_pkg_pretend() {
113
	debug-print-function ${FUNCNAME} "$@"
114
115
	check-reqs_pkg_setup "$@"
116
}
117
118
# @FUNCTION: check-reqs_prepare
119
# @DESCRIPTION:
120
# Internal function that checks the variables that should be defined.
121
check-reqs_prepare() {
122
	debug-print-function ${FUNCNAME} "$@"
123
124
	if [[ -z ${CHECKREQS_MEMORY} &&
125
			-z ${CHECKREQS_DISK_BUILD} &&
126
			-z ${CHECKREQS_DISK_USR} &&
127
			-z ${CHECKREQS_DISK_VAR} ]]; then
128
		eerror "Set some check-reqs eclass variables if you want to use it."
129
		eerror "If you are user and see this message fill a bug against the package."
130
		die "${FUNCNAME}: check-reqs eclass called but not actualy used!"
99
	fi
131
	fi
132
}
100
133
101
	if [[ -n "${CHECKREQS_NEED_SLEEP}" ]] ; then
134
# @FUNCTION: check-reqs_run
102
		echo
135
# @DESCRIPTION:
103
		ewarn "Bad things may happen! You may abort the build by pressing ctrl+c in"
136
# Internal function that runs the check based on variable settings.
104
		ewarn "the next 15 seconds."
137
check-reqs_run() {
105
		ewarn " "
138
	debug-print-function ${FUNCNAME} "$@"
106
		einfo "To make this kind of warning a fatal error, add a line to /etc/make.conf"
139
107
		einfo "setting CHECKREQS_ACTION=\"error\". To skip build requirements checking,"
140
	# some people are *censored*
108
		einfo "set CHECKREQS_ACTION=\"ignore\"."
141
	unset CHECKREQS_FAILED
109
		epause 15
142
143
	[[ -n ${CHECKREQS_MEMORY} ]] && \
144
		check-reqs_memory \
145
			${CHECKREQS_MEMORY}
146
147
	[[ -n ${CHECKREQS_DISK_BUILD} ]] && \
148
		check-reqs_disk \
149
			"${T}" \
150
			"${CHECKREQS_DISK_BUILD}"
151
152
	[[ -n ${CHECKREQS_DISK_USR} ]] && \
153
		check-reqs_disk \
154
			"${EROOT}/usr" \
155
			"${CHECKREQS_DISK_USR}"
156
157
	[[ -n ${CHECKREQS_DISK_VAR} ]] && \
158
		check-reqs_disk \
159
			"${EROOT}/var" \
160
			"${CHECKREQS_DISK_VAR}"
161
}
162
163
# @FUNCTION: check-reqs_get_mesg
164
# @DESCRIPTION:
165
# Internal function that returns number in megabites.
166
# Converts from 1G=1024 or 1T=1048576
167
check-reqs_get_megs() {
168
	debug-print-function ${FUNCNAME} "$@"
169
170
	[[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
171
172
	local unit=${1//[[:digit:]]/}
173
	local size=${1//[[:alpha:]]/}
174
175
	if [[ ${unit//[[:alpha:]]/} != "" ]]; then
176
		die "${FUNCNAME}: Failed to determine units, garbage in variables"
177
	else
178
		# temporary workaround for empty units
179
		unit="M"
180
	fi
181
182
	case ${unit} in
183
		[gG]) echo $((1024 * ${size})) ;;
184
		[mM]) echo ${size} ;;
185
		[tT]) echo $((1024 * 1024 * ${size})) ;;
186
		*)
187
			die "${FUNCNAME}: Unknown unit size: ${unit}"
188
		;;
189
	esac
190
}
191
192
# @FUNCTION: check-reqs_get_numbers
193
# @DESCRIPTION:
194
# Internal function that returns number without the unit.
195
# Converts from 1G=1 or 150T=150.
196
check-reqs_get_numbers() {
197
	debug-print-function ${FUNCNAME} "$@"
198
199
	[[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
200
201
	local size=${1//[[:alpha:]]/}
202
203
	# warn about un-united variables
204
	if [[ ${size} == ${1//[[:alpha:]]/} ]]; then
205
		ewarn "QA: Package does not specify unit for the size check"
206
		ewarn "QA: Assuming Megabytes."
207
		ewarn "QA: File bug against the package. It should specify it."
110
	fi
208
	fi
111
209
112
	if [[ -n "${CHECKREQS_NEED_DIE}" ]] ; then
210
	if [[ ${size//[[:digit:]]/} == "" ]]; then
113
		eerror "Bailing out as specified by CHECKREQS_ACTION"
211
		echo ${size}
114
		die "Build requirements not met"
212
	else
213
		die "${FUNCNAME}: Failed to determine size, garbage in variables."
115
	fi
214
	fi
116
}
215
}
117
216
118
# @FUNCTION: check_reqs_conditional
217
# @FUNCTION: check-reqs_get_unit
119
# @RETURN: True if requirements check passed, else False
120
# @DESCRIPTION:
218
# @DESCRIPTION:
121
# Checks the requirements given in the specific variables
219
# Internal function that returns number without the unit.
122
check_reqs_conditional() {
220
# Converts from 1G=1 or 150T=150.
123
	[[ -n "${1}" ]] && die "Usage: check_reqs"
221
check-reqs_get_unit() {
222
	debug-print-function ${FUNCNAME} "$@"
124
223
125
	export CHECKREQS_NEED_SLEEP="" CHECKREQS_NEED_DIE=""
224
	[[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
126
	if [[ "$CHECKREQS_ACTION" != "ignore" ]] ; then
225
127
		[[ -n "$CHECKREQS_MEMORY" ]] && check_build_memory
226
	local unit=${1//[[:digit:]]/}
128
		[[ -n "$CHECKREQS_DISK_BUILD" ]] && check_build_disk \
227
129
			"${T}" "${CHECKREQS_DISK_BUILD}"
228
	if [[ ${unit//[[:alpha:]]/} != "" ]]; then
130
		[[ -n "$CHECKREQS_DISK_USR" ]] && check_build_disk \
229
		die "${FUNCNAME}: Failed to determine units, garbage in variables."
131
			"${ROOT}/usr" "${CHECKREQS_DISK_USR}"
230
	else
132
		[[ -n "$CHECKREQS_DISK_VAR" ]] && check_build_disk \
231
		# temporary workaround for empty units
133
			"${ROOT}/var" "${CHECKREQS_DISK_VAR}"
232
		unit="M"
134
	fi
233
	fi
135
234
136
	[[ -z "${CHECKREQS_NEED_SLEEP}" && -z "${CHECKREQS_NEED_DIE}" ]]
235
	case ${unit} in
236
		[gG]) echo "Gigabytes" ;;
237
		[mM]) echo "Megabytes" ;;
238
		[tT]) echo "Terabytes" ;;
239
		*)
240
			die "${FUNCNAME}: Unknown unit size: ${unit}"
241
		;;
242
	esac
243
}
244
245
# @FUNCTION: check-reqs_output
246
# @DESCRIPTION:
247
# Internal function that prints the warning and dies if required based on
248
# the test results.
249
check-reqs_output() {
250
	debug-print-function ${FUNCNAME} "$@"
251
252
	local msg="ewarn"
253
254
	[[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
255
	if [[ -n ${CHECKREQS_FAILED} ]]; then
256
		${msg}
257
		${msg} "Space constrains set in the ebuild were not met!"
258
		${msg} "The build will most probably fail, you should enhance the space"
259
		${msg} "as per failed tests."
260
		${msg}
261
262
		[[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \
263
			die "Build requirements not met!"
264
	fi
137
}
265
}
138
266
139
# internal use only!
267
# @FUNCTION: check-reqs_memory
140
check_build_memory() {
268
# @DESCRIPTION:
141
	[[ -n "${1}" ]] && die "Usage: check_build_memory"
269
# Internal function that checks space on the RAM.
142
	check_build_msg_begin "${CHECKREQS_MEMORY}" "MBytes" "RAM"
270
check-reqs_memory() {
271
	debug-print-function ${FUNCNAME} "$@"
272
273
	[[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
274
275
	local size=${1}
276
	local actual_memory
277
278
	check-reqs_start_phase \
279
		$(check-reqs_get_numbers ${size}) \
280
		$(check-reqs_get_unit ${size}) \
281
		"RAM"
282
143
	if [[ -r /proc/meminfo ]] ; then
283
	if [[ -r /proc/meminfo ]] ; then
144
		actual_memory=$(sed -n -e '/MemTotal:/s/^[^:]*: *\([0-9]\+\) kB/\1/p' \
284
		actual_memory=$(sed -n -e '/MemTotal:/s/^[^:]*: *\([0-9]\+\) kB/\1/p' \
145
			/proc/meminfo)
285
			/proc/meminfo)
Lines 148-207 Link Here
148
		[[ "$?" == "0" ]] &&
288
		[[ "$?" == "0" ]] &&
149
			actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' )
289
			actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' )
150
	fi
290
	fi
151
	if [[ -n "${actual_memory}" ]] ; then
291
	if [[ -n ${actual_memory} ]] ; then
152
		if [[ ${actual_memory} -lt $((1024 * ${CHECKREQS_MEMORY})) ]] ; then
292
		if [[ ${actual_memory} -lt $((1024 * $(check-reqs_get_megs ${size}))) ]] ; then
153
			eend 1
293
			eend 1
154
			check_build_msg_ick "${CHECKREQS_MEMORY}" "MBytes" "RAM"
294
			check-reqs_unsattisfied \
295
				$(check-reqs_get_numbers ${size}) \
296
				$(check-reqs_get_unit ${size}) \
297
				"RAM"
155
		else
298
		else
156
			eend 0
299
			eend 0
157
		fi
300
		fi
158
	else
301
	else
159
		eend 1
302
		eend 1
160
		ewarn "Couldn't determine amount of memory, skipping ..."
303
		ewarn "Couldn't determine amount of memory, skipping..."
161
	fi
304
	fi
162
}
305
}
163
306
164
# internal use only!
307
# @FUNCTION: check-reqs_disk
165
check_build_disk() {
308
# @DESCRIPTION:
166
	[[ -z "${2}" ]] && die "Usage: check_build_disk where name needed"
309
# Internal function that checks space on the harddrive.
167
	check_build_msg_begin "${2}" "MBytes" \
310
check-reqs_disk() {
168
			"disk space at ${1}"
311
	debug-print-function ${FUNCNAME} "$@"
169
	actual_space=$(df -Pm ${1} 2>/dev/null | sed -n \
312
170
			'$s/\(\S\+\s\+\)\{3\}\([0-9]\+\).*/\2/p' 2>/dev/null )
313
	[[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]"
171
	if [[ "$?" == "0" && -n "${actual_space}" ]] ; then
314
172
		if [[ ${actual_space} -lt ${2} ]] ; then
315
	local path=${1}
316
	local size=${2}
317
	local space_megs
318
319
	check-reqs_start_phase \
320
		$(check-reqs_get_numbers ${size}) \
321
		$(check-reqs_get_unit ${size}) \
322
		"disk space at \"${path}\""
323
324
	space_megs=$(df -Pm ${1} 2>/dev/null | sed -n \
325
		'$s/\(\S\+\s\+\)\{3\}\([0-9]\+\).*/\2/p' 2>/dev/null)
326
327
	if [[ $? == 0 && -n ${space_megs} ]] ; then
328
		if [[ ${space_megs} -lt $(check-reqs_get_megs ${size}) ]] ; then
173
			eend 1
329
			eend 1
174
			check_build_msg_ick "${2}" "MBytes" \
330
			check-reqs_unsattisfied \
175
					"disk space at ${1}"
331
				$(check-reqs_get_numbers ${size}) \
332
				$(check-reqs_get_unit ${size}) \
333
				"disk space at \"${path}\""
176
		else
334
		else
177
			eend 0
335
			eend 0
178
		fi
336
		fi
179
	else
337
	else
180
		eend 1
338
		eend 1
181
		ewarn "Couldn't figure out disk space, skipping ..."
339
		ewarn "Couldn't determine disk space, skipping..."
182
	fi
340
	fi
183
}
341
}
184
342
185
# internal use only!
343
# @FUNCTION: check-reqs_start_phase
186
check_build_msg_begin() {
344
# @DESCRIPTION:
187
	ebegin "Checking for at least ${1}${2} ${3}"
345
# Internal function that inform about started check
188
}
346
check-reqs_start_phase() {
347
	debug-print-function ${FUNCNAME} "$@"
189
348
190
# internal use only!
349
	[[ -z ${3} ]] && die "Usage: ${FUNCNAME} [size] [unit] [location]"
191
check_build_msg_skip() {
350
192
	ewarn "Skipping check for at least ${1}${2} ${3}"
351
	ebegin "Checking for at least ${1}${2} ${3}"
193
}
352
}
194
353
195
# internal use only!
354
# @FUNCTION: check-reqs_unsattisfied
196
check_build_msg_ick() {
355
# @DESCRIPTION:
197
	if [[ "${CHECKREQS_ACTION}" == "error" ]] ; then
356
# Internal function that inform about check result.
198
		eerror "Don't have at least ${1}${2} ${3}"
357
# It has different output between pretend and setup phase,
199
		echo
358
# where in pretend phase it is fatal.
200
		export CHECKREQS_NEED_DIE="yes"
359
check-reqs_unsattisfied() {
201
	else
360
	debug-print-function ${FUNCNAME} "$@"
202
		ewarn "Don't have at least ${1}${2} ${3}"
361
203
		echo
362
	[[ -z ${3} ]] && die "Usage: ${FUNCNAME} [size] [unit] [location]"
204
		export CHECKREQS_NEED_SLEEP="yes"
363
205
	fi
364
	local msg="ewarn"
365
366
	[[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
367
	${msg} "Don't have at least ${1}${2} ${3}"
368
369
	# @ECLASS-VARIABLE: CHECKREQS_FAILED
370
	# @DESCRIPTION:
371
	# @DEAULT_UNSET
372
	# If set the checks failed and eclass should abort the build.
373
	# Internal, do not set yourself.
374
	CHECKREQS_FAILED="true"
206
}
375
}
207
376

Return to bug 358913