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

Return to bug 358913