aboutsummaryrefslogtreecommitdiff
blob: e3a02312c4156bf8ea0fa1ac92b01be0bbf46131 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

# @ECLASS: autotools-multilib.eclass
# @MAINTAINER:
# Michał Górny <mgorny@gentoo.org>
# @AUTHOR:
# Michał Górny <mgorny@gentoo.org>
# Gregory M. Turner <gmt@be-evil.net>
# @BLURB: autotools-utils wrapper for multilib builds
# @DESCRIPTION:
# The autotools-multilib.eclass is an autotools-utils.eclass(5) wrapper
# introducing support for building for more than one ABI (multilib).
#
# Inheriting this eclass sets the USE flags and exports autotools-utils
# phase function wrappers which build the package for each supported ABI
# when the relevant flag is enabled. Other than that, it works like
# regular autotools-utils.
#
# Note that AUTOTOOLS_IN_SOURCE_BUILD is supported; this is a reversal
# from previous versions, where it was unsupported.  When activated,
# this will cause the source to be cloned into the build dirs
# instead of the usual out-of-source build recipe (this could mean
# a lot of stuff gets copied for some projects, so please use it
# sparingly).

# EAPI=4 is required for meaningful MULTILIB_USEDEP.
case ${EAPI:-0} in
	4|5) ;;
	*) die "EAPI=${EAPI} is not supported" ;;
esac

# @ECLASS-VARIABLE: MULTILIB_PARALLEL_PHASES
# @DESCRIPTION:
# An string containing a list of phase-functions that will be executed
# in parallel, when invoked via their corresponding autotools-multilib-<phase>
# functions.  For example, for parallel execution of the src_test and
# src_compile phases, this string could be set to "src_test src_compile"
# It is safe to add extra "bonus" whitespace to this variable, or to
# include duplicate values.  If the variable is changed, the new values
# take effect immediately upon invocation of the corresponding function.
# Does not (and could not) affect non-autotools-multilib functions unless
# they happen, in turn, to invoke the autotools-multilib function.
#
# By default, contains only "src_configure".
#
# Supported values may be any subset of src_configure, src_compile,
# src_test, and src_install.  However, usage of src_install is tricky
# and discouraged.  Aside from being a generally untested feature and
# therefore potentially prone to unexpected behavior, parallel src_install
# disables the header-wrapping features of autotools-multilib_src_install.
#
# If src_install is included in MULTILIB_PARALLEL_PHASES, but the
# variable MULTILIB_INSECURE_INSTALL is not also set, a big, ugly
# warning will issue forth and the script will die.
#
# don't execute src_install in parallel unless you are 100% sure that
# it makes sense to do so.  Presumably this would only be the case in the
# case of ebuilds which are guaranteed never to install any header files, or
# for which header-compatibility issues are handled via some external means.
#
# As src_prepare does not run on a per-ABI basis, it is not a supported
# phase in MULTILIB_PARALLEL_PHASES -- including it would
# have no effect.

# consider EAPI5's parallel src_test policy to apply equally
# to multi-abi src_test (this might cause some unexpected surprises
# for ebuild authors migrating EAPIs -- tough cookies for them, I suppose)
case ${EAPI:-0} in
	5)
		: ${MULTILIB_PARALLEL_PHASES:=src_configure src_test}
		;;
	*)
		: ${MULTILIB_PARALLEL_PHASES:=src_configure}
		;;
esac

# @ECLASS-VARIABLE: MULTILIB_INSECURE_INSTALL
# @DEFAULT-UNSET
# @DESCRIPTION:
# If set to a nonempty value, autotools-multilib_src_install will not perform
# automatic checking of headers for conflicts and automatable wrapping of
# header files.  Instead, autotools-utils_src_install will beinvoked
# normally for each abi, without any special protection against such conflicts.
#
# This variable must be non-empty if src_install is in
# MULTILIB_PARALLEL_PHASES or else die will be invoked during
# autotools-multilib_src_install if ever it is invoked.
#
# if MULTILIB_PARALLEL_PHASES is set before inherit we can catch that
# here at the global level and prevent "heartbreakers," down the line, during
# src_install.  Admittedly, concievably they might set MULTILIB_INSECURE_INSTALL
# later in which case we die unneccesarily -- however it's not unreasonable to require
# both variables to be set either before or after inherit, but not in a split configuration.
#
# Since an empty MULTILIB_PARALLEL_PHASES causes the default value of "src_configure"
# to be substituted, a dummy value of "none" may be used to signify a request for
# total serialization of all phases
if has src_install ${MULTILIB_PARALLEL_PHASES} ; then
	[[ -n ${MULTILIB_INSECURE_INSTALL} ]] || \
		die "src_install in MULTILIB_PARALLEL_PHASES requries MULTILIB_INSECURE_INSTALL"
fi

inherit my-god-its-full-of-quotation-marks ehooker autotools-utils multilib-build

EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install

_wrap_srcdir() {
	debug-print-function "${FUNCNAME}" "$@"
	if [[ ${REAL_AUTOTOOLS_IN_SOURCE_BUILD} ]] ; then
		# stop whispering lies into multilib-build's ear... and start telling them to autotools-utils instead :)
		ECONF_SOURCE="${BUILD_DIR}" S="${BUILD_DIR}" AUTOTOOLS_IN_SOURCE_BUILD="${REAL_AUTOTOOLS_IN_SOURCE_BUILD}" "$@"
	else
		"$@"
	fi
}

# @FUNCTION: autotools_multilib_src_prepare
# @USAGE: [list of arguments]
# @RETURN: Either the results of autotools-utils_src_prepare, or zero,
# if autotools-utils_src_prepare is not executed due to ehook firing results
# @INTERNAL
# @DESCRIPTION:
# Fires the autotools-multilib-global-pre_src_prepare ehook, and, if
# no hook listeners return a nonzero result code, invokes
# autotools-utils_src_prepare with the provided arguments.  Finally,
# fires the autotools-multilib-global-post_src_prepare ehook.
autotools-multilib_src_prepare() {
	debug-print-function "${FUNCNAME}" "$@"

	local _autotools_multilib_src_prepare_result=0
	if ehook_fire autotools-multilib-global-pre_src_prepare ; then
		autotools-utils_src_prepare "${@}"
		_autotools_multilib_src_prepare_result=$?
		[[ ${AUTOTOOLS_IN_SOURCE_BUILD} ]] && \
			AUTOTOOLS_IN_SOURCE_BUILD="" multilib_copy_sources
	fi
	ehook_fire autotools-multilib-global-post_src_prepare -u
	return ${_autotools_multilib_src_prepare_result}
}

# @FUNCTION: _autotools_multilib_phasic_abi_wrapper
# @USAGE: <phase-name> [list of arguments]
# @RETURN: Either the results of autotools-utils_<phase-name>, or zero,
# if autotools-utils_<phase-name> is not executed due to ehook firing results
# @INTERNAL
# @DESCRIPTION:
# Implements the standard per-abi invocation pattern using
# autotools-utils phase functions.  <phase-name> must be one
# of src_configure, src_compile, src_test, or src_install, or will die
#
# Substitutes any occurance of @GET_LIBDIR@ in the argument list
# with the results of the $(get_libdir) function from multilib.eclass
#
# Stores the argument list into an array named
# autotools_multilib_<phase-name>_args
#
# Fires the autotools-multilib-per-abi-pre_<phase-name> ehook, and, if no
# listeners return nonzero error codes, invokes
# autotools-utils_<phase-name> with the arguments listed
# in autotools_multilib_<phase-name>_args (which may have been
# modified by the autotools-multilib-pre_<phase-name> hook listeners).
#
# Fires the autotools-multilib-per-abi-post_<phase-name> ehook
_autotools_multilib_phasic_abi_wrapper() {
	debug-print-function "${FUNCNAME}" "$@"
	local _autotools_multilib_phase="$1"
	case ${_autotools_multilib_phase} in
		src_configure|src_compile|src_test|src_install) shift ;;
		*) die "Unsupported phase name: \"${_autotools_multilib_phase}\""
	esac
	declare -a autotools_multilib_invocation_args
	local invocation_arg
	for invocation_arg in "$@" ; do
		autotools_multilib_invocation_args+=( "$(get_libdir_subst "${invocation_arg}")" )
	done
	if [[ -n ${ECLASS_DEBUG_OUTPUT} ]] ; then
		debug-print "${FUNCNAME}: autotools_multilib hook (abi=${ABI}; pre-pre-${_autotools_multilib_phase}): autotools_multilib_invocation_args is ($(
			my-god-its-full-of-quotation-marks "${autotools_multilib_invocation_args[@]}"
		))"
	fi
	unset invocation_arg
	local _autotools_multilib_phasic_result=0
	if autotools-utils_run_in_build_dir ehook_fire autotools-multilib-per-abi-pre_${_autotools_multilib_phase} ; then
		if [[ -n ${ECLASS_DEBUG_OUTPUT} ]] ; then
			debug-print "${FUNCNAME}: autotools_multilib hook (abi=${ABI}; post-pre-${_autotools_multilib_phase}): autotools_multilib_invocation_args is ($(
				my-god-its-full-of-quotation-marks "${autotools_multilib_invocation_args[@]}"
			))"
		fi
		autotools-utils_${_autotools_multilib_phase} "${autotools_multilib_invocation_args[@]}"
		_autotools_multilib_phasic_result=$?
	else
		debug-print "${FUNCNAME}: autotools-utils_${_autotools_multilib_phase} invocation skipped for ABI ${ABI} due to ehook override"
	fi
	autotools-utils_run_in_build_dir ehook_fire autotools-multilib-per-abi-post_${_autotools_multilib_phase} -u
	return ${_autotools_multilib_phasic_result}
}

# @FUNCTION: _autotools_multilib_phasic_foreach_abi
# @USAGE: <phase-name> [list of arguments]
# @RETURN: nonzero if and only if any autotools-utils_<phase-name> function returns nonzero
# @INTERNAL
# @DESCRIPTION:
# Implements the standard multi-abi invocation pattern using
# autotools-utils phase functions.  <phase-name> must be one
# of src_configure, src_compile, or src_test or die will be invoked.
# Fires autotools-multilib-global-{pre,post}_<phase-name> ehooks.
_autotools_multilib_phasic_foreach_abi() {
	debug-print-function "${FUNCNAME}" "$@"

	local _autotools_multilib_phase="$1"
	case ${_autotools_multilib_phase} in
		src_configure|src_compile|src_test|src_install) shift ;;
		*) die "Unsupported phase name: \"${_autotools_multilib_phase}\""
	esac
	local _autotools_multilib_foreach_result=0
	if ehook_fire autotools-multilib-global-pre_${_autotools_multilib_phase} ; then
		if has ${_autotools_multilib_phase} ${MULTILIB_PARALLEL_PHASES} ; then
			REAL_AUTOTOOLS_IN_SOURCE_BUILD="${AUTOTOOLS_IN_SOURCE_BUILD}" \
				AUTOTOOLS_IN_SOURCE_BUILD="" \
				multilib_parallel_foreach_abi _wrap_srcdir \
					_autotools_multilib_phasic_abi_wrapper \
						"${_autotools_multilib_phase}" "$@"
		else
			REAL_AUTOTOOLS_IN_SOURCE_BUILD="${AUTOTOOLS_IN_SOURCE_BUILD}" \
				AUTOTOOLS_IN_SOURCE_BUILD="" \
				multilib_foreach_abi _wrap_srcdir \
					_autotools_multilib_phasic_abi_wrapper \
						"${_autotools_multilib_phase}" "$@"
		fi
		_autotools_multilib_foreach_result=$?
	fi
	ehook_fire autotools-multilib-global-post_${_autotools_multilib_phase} -u
	return ${_autotools_multilib_foreach_result}
}

# @FUNCTION: autotools-multilib_src_configure
# @USAGE: [list of arguments]
# @RETURN: nonzero if and only if any autotools-utils_src_configure function returns nonzero
# @DESCRIPTION:
# This is the standard src_configure phase function for autotools-multilib.
# Accepts a list of arguments on the command-line; additional arguments passed
# in via the myeconfargs array will also be respected by autotools-utils_src_configure.
# Fires the autotools-multilib-{global,per-abi}-{pre,post}_src_configure ehooks to allow
# consuming ebuilds and eclasses to hook in implementation code on a per-abi or global basis.
autotools-multilib_src_configure() {
	debug-print-function "${FUNCNAME}" "$@"
	_autotools_multilib_phasic_foreach_abi src_configure "$@"
}

# @FUNCTION: autotools-multilib_src_compile
# @USAGE: [list of arguments]
# @RETURN: nonzero if and only if any autotools-utils_src_compile function returns nonzero
# @DESCRIPTION:
# This is the standard src_compile phase function for autotools-multilib.
# Accepts a list of arguments on the command-line; additional arguments passed
# in via the myeconfargs array will also be respected by autotools-utils_src_compile.
# Fires the autotools-multilib-{global,per-abi}-{pre,post}_src_compile ehooks to allow
# consuming ebuilds and eclasses to hook in implementation code on a per-abi or global basis.
autotools-multilib_src_compile() {
	debug-print-function "${FUNCNAME}" "$@"
	_autotools_multilib_phasic_foreach_abi src_compile "$@"
}

# @FUNCTION: autotools-multilib_src_test
# @USAGE: [list of arguments]
# @RETURN: nonzero if and only if any autotools-utils_src_test function returns nonzero
# @DESCRIPTION:
# This is the standard src_test phase function for autotools-multilib.
# Accepts a list of arguments on the command-line; additional arguments passed
# in via the myeconfargs array will also be respected by autotools-utils_src_test.
# Fires the autotools-multilib-{global,per-abi}-{pre,post}_src_test ehooks to allow
# consuming ebuilds and eclasses to hook in implementation code, on a per-abi or global basis.
autotools-multilib_src_test() {
	debug-print-function "${FUNCNAME}" "$@"
	_autotools_multilib_phasic_foreach_abi src_test "$@"
}

# @FUNCTION: _autotools_multilib_secure_src_install
# @USAGE: [list of arguments]
# @RETURN: Either the results of autotools-utils_src_install or zero,
# if autotools-utils_src_install is not executed (as may happen due to
# ehook listeners suppressing the call)
# @INTERNAL
# @DESCRIPTION:
# per-abi src_install wrapper.  Runs _autotools_multilib_phasic_abi_wrapper
# to perform standard autotools-multilib-style per-abi phase function
# handling, but upon completion also invokes, when appropriate,
# multilib_prepare_wrappers and multilib_check_headers from multilib-build.eclass
# After all abi's complete, the header wrapping process must be finalized.
_autotools_multilib_secure_src_install() {
	debug-print-function "${FUNCNAME}" "$@"

	local _autotools_multilib_secure_src_install_result
	_autotools_multilib_phasic_abi_wrapper src_install "$@"
	_autotools_multilib_secure_src_install_result=$?

	# We always perform these steps here as this is only invoked when
	# all prerequisites have been checked already.
	multilib_prepare_wrappers

	# Make sure all headers are the same for each ABI.
	multilib_check_headers

	return ${_autotools_multilib_secure_src_install_result}
}

# @FUNCTION: autotools-multilib_src_install
# @USAGE: [list of arguments]
# @RETURN: nonzero if and only if any autotools-utils_src_install function returns nonzero
# @DESCRIPTION:
# This is the standard src_install phase function for autotools-multilib.
# Accepts a list of arguments on the command-line; additional arguments passed
# in via the myeconfargs array will also be respected by autotools-utils_src_install.
# Fires the autotools-multilib-{global,per-abi}-{pre,post}_src_install ehooks to allow
# consuming ebuilds and eclasses to hook in implementation code, on a per-abi or global basis.
#
# Additionally, when possible, provides automatic checking of header files for cross-abi
# conflicts.  If a conflict is detected, the script will die.  This feature is not available
# if src_install is added to the MULTILIB_PARALLEL_PHASES variable, as it
# works by taking a checksum-based "snapshot" of the files installed by each ABI and comparing
# these snapshots.
#
# When this feature is available, any header files listed in the MULTILIB_WRAPPED_HEADERS variable
# will be automatically wrapped using the multilib-build.eclass framework.
autotools-multilib_src_install() {
	debug-print-function "${FUNCNAME}" "$@"

	local _autotools_multilib_src_install_result=0

	if has src_install ${MULTILIB_PARALLEL_PHASES} ; then
		[[ -n ${MULTILIB_INSECURE_INSTALL} ]] || \
			die "src_install in MULTILIB_PARALLEL_PHASES requries MULTILIB_INSECURE_INSTALL"
	fi

	if [[ -n ${MULTILIB_INSECURE_INSTALL} || ${#MULTIBUILD_VARIANTS[@]} -le 1 ]] ; then
		# perform standard src_install without _autotools_multilib_secure_src_install
		# multi-abi header-wrapping magic
		_autotools_multilib_phasic_foreach_abi src_install "$@"
		return $?
	fi

	if ehook_fire autotools-multilib-global-pre_src_install ; then
		multilib_foreach_abi _autotools_multilib_secure_src_install "$@"
		_autotools_multilib_src_install_result=$?
	fi
	ehook_fire autotools-multilib-global-post_src_install -u

	# merge the wrappers
	multilib_install_wrappers

	return ${_autotools_multilib_src_install_result}
}