dev-qt/qtx11extras: stable 5.14.2 for ppc, bug #719732
[gentoo.git] / eclass / check-reqs.eclass
1 # Copyright 2004-2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: check-reqs.eclass
5 # @MAINTAINER:
6 # QA Team <qa@gentoo.org>
7 # @AUTHOR:
8 # Bo Ørsted Andresen <zlin@gentoo.org>
9 # Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
10 # @SUPPORTED_EAPIS: 4 5 6 7
11 # @BLURB: Provides a uniform way of handling ebuild which have very high build requirements
12 # @DESCRIPTION:
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().
16 #
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.
19 #
20 # @CODE
21 # # need this much memory (does *not* check swap)
22 # CHECKREQS_MEMORY="256M"
23 #
24 # # need this much temporary build space
25 # CHECKREQS_DISK_BUILD="2G"
26 #
27 # # install will need this much space in /usr
28 # CHECKREQS_DISK_USR="1G"
29 #
30 # # install will need this much space in /var
31 # CHECKREQS_DISK_VAR="1024M"
32 #
33 # @CODE
34 #
35 # If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not
36 # carried out.
37 #
38 # These checks should probably mostly work on non-Linux, and they should
39 # probably degrade gracefully if they don't. Probably.
40
41 if [[ ! ${_CHECK_REQS_ECLASS_} ]]; then
42
43 # @ECLASS-VARIABLE: CHECKREQS_MEMORY
44 # @DEFAULT_UNSET
45 # @DESCRIPTION:
46 # How much RAM is needed? Eg.: CHECKREQS_MEMORY=15M
47
48 # @ECLASS-VARIABLE:  CHECKREQS_DISK_BUILD
49 # @DEFAULT_UNSET
50 # @DESCRIPTION:
51 # How much diskspace is needed to build the package? Eg.: CHECKREQS_DISK_BUILD=2T
52
53 # @ECLASS-VARIABLE: CHECKREQS_DISK_USR
54 # @DEFAULT_UNSET
55 # @DESCRIPTION:
56 # How much space in /usr is needed to install the package? Eg.: CHECKREQS_DISK_USR=15G
57
58 # @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
59 # @DEFAULT_UNSET
60 # @DESCRIPTION:
61 # How much space is needed in /var? Eg.: CHECKREQS_DISK_VAR=3000M
62
63 case ${EAPI:-0} in
64         4|5|6|7) ;;
65         *) die "${ECLASS}: EAPI=${EAPI:-0} is not supported" ;;
66 esac
67
68 EXPORT_FUNCTIONS pkg_pretend pkg_setup
69
70 # Obsolete function executing all the checks and printing out results
71 check_reqs() {
72         eerror "Package calling old ${FUNCNAME} function."
73         eerror "It should call check-reqs_pkg_pretend and check-reqs_pkg_setup."
74         die "${FUNCNAME} is banned"
75 }
76
77 # @FUNCTION: check-reqs_pkg_setup
78 # @DESCRIPTION:
79 # Exported function running the resources checks in pkg_setup phase.
80 # It should be run in both phases to ensure condition changes between
81 # pkg_pretend and pkg_setup won't affect the build.
82 check-reqs_pkg_setup() {
83         debug-print-function ${FUNCNAME} "$@"
84
85         check-reqs_prepare
86         check-reqs_run
87         check-reqs_output
88 }
89
90 # @FUNCTION: check-reqs_pkg_pretend
91 # @DESCRIPTION:
92 # Exported function running the resources checks in pkg_pretend phase.
93 check-reqs_pkg_pretend() {
94         debug-print-function ${FUNCNAME} "$@"
95
96         check-reqs_pkg_setup "$@"
97 }
98
99 # @FUNCTION: check-reqs_prepare
100 # @INTERNAL
101 # @DESCRIPTION:
102 # Internal function that checks the variables that should be defined.
103 check-reqs_prepare() {
104         debug-print-function ${FUNCNAME} "$@"
105
106         if [[ -z ${CHECKREQS_MEMORY} &&
107                         -z ${CHECKREQS_DISK_BUILD} &&
108                         -z ${CHECKREQS_DISK_USR} &&
109                         -z ${CHECKREQS_DISK_VAR} ]]; then
110                 eerror "Set some check-reqs eclass variables if you want to use it."
111                 eerror "If you are user and see this message file a bug against the package."
112                 die "${FUNCNAME}: check-reqs eclass called but not actually used!"
113         fi
114 }
115
116 # @FUNCTION: check-reqs_run
117 # @INTERNAL
118 # @DESCRIPTION:
119 # Internal function that runs the check based on variable settings.
120 check-reqs_run() {
121         debug-print-function ${FUNCNAME} "$@"
122
123         # some people are *censored*
124         unset CHECKREQS_FAILED
125
126         if [[ ${MERGE_TYPE} != binary ]]; then
127                 [[ -n ${CHECKREQS_MEMORY} ]] && \
128                         check-reqs_memory \
129                                 ${CHECKREQS_MEMORY}
130
131                 [[ -n ${CHECKREQS_DISK_BUILD} ]] && \
132                         check-reqs_disk \
133                                 "${T}" \
134                                 "${CHECKREQS_DISK_BUILD}"
135         fi
136
137         if [[ ${MERGE_TYPE} != buildonly ]]; then
138                 [[ -n ${CHECKREQS_DISK_USR} ]] && \
139                         check-reqs_disk \
140                                 "${EROOT%/}/usr" \
141                                 "${CHECKREQS_DISK_USR}"
142
143                 [[ -n ${CHECKREQS_DISK_VAR} ]] && \
144                         check-reqs_disk \
145                                 "${EROOT%/}/var" \
146                                 "${CHECKREQS_DISK_VAR}"
147         fi
148 }
149
150 # @FUNCTION: check-reqs_get_kibibytes
151 # @INTERNAL
152 # @DESCRIPTION:
153 # Internal function that returns number in KiB.
154 # Returns 1024**2 for 1G or 1024**3 for 1T.
155 check-reqs_get_kibibytes() {
156         debug-print-function ${FUNCNAME} "$@"
157
158         [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
159
160         local unit=${1:(-1)}
161         local size=${1%[GMT]}
162
163         case ${unit} in
164                 M) echo $((1024 * size)) ;;
165                 G) echo $((1024 * 1024 * size)) ;;
166                 T) echo $((1024 * 1024 * 1024 * size)) ;;
167                 *)
168                         die "${FUNCNAME}: Unknown unit: ${unit}"
169                 ;;
170         esac
171 }
172
173 # @FUNCTION: check-reqs_get_number
174 # @INTERNAL
175 # @DESCRIPTION:
176 # Internal function that returns the numerical value without the unit.
177 # Returns "1" for "1G" or "150" for "150T".
178 check-reqs_get_number() {
179         debug-print-function ${FUNCNAME} "$@"
180
181         [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
182
183         local size=${1%[GMT]}
184         [[ ${size} == ${1} ]] && die "${FUNCNAME}: Missing unit: ${1}"
185
186         echo ${size}
187 }
188
189 # @FUNCTION: check-reqs_get_unit
190 # @INTERNAL
191 # @DESCRIPTION:
192 # Internal function that returns the unit without the numerical value.
193 # Returns "GiB" for "1G" or "TiB" for "150T".
194 check-reqs_get_unit() {
195         debug-print-function ${FUNCNAME} "$@"
196
197         [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
198
199         local unit=${1:(-1)}
200
201         case ${unit} in
202                 M) echo "MiB" ;;
203                 G) echo "GiB" ;;
204                 T) echo "TiB" ;;
205                 *)
206                         die "${FUNCNAME}: Unknown unit: ${unit}"
207                 ;;
208         esac
209 }
210
211 # @FUNCTION: check-reqs_output
212 # @INTERNAL
213 # @DESCRIPTION:
214 # Internal function that prints the warning and dies if required based on
215 # the test results.
216 check-reqs_output() {
217         debug-print-function ${FUNCNAME} "$@"
218
219         local msg="ewarn"
220
221         [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
222         if [[ -n ${CHECKREQS_FAILED} ]]; then
223                 ${msg}
224                 ${msg} "Space constraints set in the ebuild were not met!"
225                 ${msg} "The build will most probably fail, you should enhance the space"
226                 ${msg} "as per failed tests."
227                 ${msg}
228
229                 [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \
230                         die "Build requirements not met!"
231         fi
232 }
233
234 # @FUNCTION: check-reqs_memory
235 # @INTERNAL
236 # @DESCRIPTION:
237 # Internal function that checks size of RAM.
238 check-reqs_memory() {
239         debug-print-function ${FUNCNAME} "$@"
240
241         [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
242
243         local size=${1}
244         local actual_memory
245         local actual_swap
246
247         check-reqs_start_phase \
248                 ${size} \
249                 "RAM"
250
251         if [[ -r /proc/meminfo ]] ; then
252                 actual_memory=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
253                 actual_swap=$(awk '/SwapTotal/ { print $2 }' /proc/meminfo)
254         else
255                 actual_memory=$(sysctl hw.physmem 2>/dev/null)
256                 [[ $? -eq 0 ]] && actual_memory=$(echo "${actual_memory}" \
257                         | sed -e 's/^[^:=]*[:=][[:space:]]*//')
258                 actual_swap=$(sysctl vm.swap_total 2>/dev/null)
259                 [[ $? -eq 0 ]] && actual_swap=$(echo "${actual_swap}" \
260                         | sed -e 's/^[^:=]*[:=][[:space:]]*//')
261         fi
262         if [[ -n ${actual_memory} ]] ; then
263                 if [[ ${actual_memory} -ge $(check-reqs_get_kibibytes ${size}) ]] ; then
264                         eend 0
265                 elif [[ -n ${actual_swap} && $((${actual_memory} + ${actual_swap})) \
266                                 -ge $(check-reqs_get_kibibytes ${size}) ]] ; then
267                         ewarn "Amount of main memory is insufficient, but amount"
268                         ewarn "of main memory combined with swap is sufficient."
269                         ewarn "Build process may make computer very slow!"
270                         eend 0
271                 else
272                         eend 1
273                         check-reqs_unsatisfied \
274                                 ${size} \
275                                 "RAM"
276                 fi
277         else
278                 eend 1
279                 ewarn "Couldn't determine amount of memory, skipping..."
280         fi
281 }
282
283 # @FUNCTION: check-reqs_disk
284 # @INTERNAL
285 # @DESCRIPTION:
286 # Internal function that checks space on the harddrive.
287 check-reqs_disk() {
288         debug-print-function ${FUNCNAME} "$@"
289
290         [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]"
291
292         local path=${1}
293         local size=${2}
294         local space_kbi
295
296         check-reqs_start_phase \
297                 ${size} \
298                 "disk space at \"${path}\""
299
300         space_kbi=$(df -Pk "${1}" 2>/dev/null | awk 'FNR == 2 {print $4}')
301
302         if [[ $? == 0 && -n ${space_kbi} ]] ; then
303                 if [[ ${space_kbi} -lt $(check-reqs_get_kibibytes ${size}) ]] ; then
304                         eend 1
305                         check-reqs_unsatisfied \
306                                 ${size} \
307                                 "disk space at \"${path}\""
308                 else
309                         eend 0
310                 fi
311         else
312                 eend 1
313                 ewarn "Couldn't determine disk space, skipping..."
314         fi
315 }
316
317 # @FUNCTION: check-reqs_start_phase
318 # @INTERNAL
319 # @DESCRIPTION:
320 # Internal function that inform about started check
321 check-reqs_start_phase() {
322         debug-print-function ${FUNCNAME} "$@"
323
324         [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
325
326         local size=${1}
327         local location=${2}
328         local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
329
330         ebegin "Checking for at least ${sizeunit} ${location}"
331 }
332
333 # @FUNCTION: check-reqs_unsatisfied
334 # @INTERNAL
335 # @DESCRIPTION:
336 # Internal function that inform about check result.
337 # It has different output between pretend and setup phase,
338 # where in pretend phase it is fatal.
339 check-reqs_unsatisfied() {
340         debug-print-function ${FUNCNAME} "$@"
341
342         [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
343
344         local msg="ewarn"
345         local size=${1}
346         local location=${2}
347         local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
348
349         [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
350         ${msg} "There is NOT at least ${sizeunit} ${location}"
351
352         # @ECLASS-VARIABLE: CHECKREQS_FAILED
353         # @DESCRIPTION:
354         # @INTERNAL
355         # If set the checks failed and eclass should abort the build.
356         # Internal, do not set yourself.
357         CHECKREQS_FAILED="true"
358 }
359
360 _CHECK_REQS_ECLASS_=1
361 fi