aboutsummaryrefslogtreecommitdiff
blob: 930ea294990b7d35eb7897587fa881e7343159df (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
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

# @ECLASS: gtk-doc.eclass
# @MAINTAINER:
# Greg Turner <gmt@be-evil.net>
# @BLURB: Gentoo gtk-doc enhancements
# @DESCRIPTION:
# gtk-doc.eclass automatically enhances gtk-doc for Gentoo builds
# by applying patches to gtk-doc.make before/after src_prepare.  The
# patches are applied via the gtk_doc_enhance hook which will
# be fired automatically so long as gtk-doc_src_prepare is
# invoked, or any one of the following hooks are fired:
# autotools-utils-{pre,post}_src_prepare, cmake-utils-{pre,post}_src_prepare,
# qt4-build-multilib-{pre,post}_src_prepare.
#
# The nature of the enhancement is, thus-far, only to fix the
# code for automatically installing pre-generated html directories
# when disable-gtk-doc is supplied to configure.  This means
# that if you build in-tree, there is probably no reason to
# use this eclass; however, it should be harmless to do so anyhow.
#
# NB: There is, thus far, no reason to believe that the upstream
# gtk-doc maintainers wouldn't be able to merge patches equivalent
# to those applied by this eclass.  Failing to install the
# prebuilt documentation when building out-of-tree is almost certainly
# a bug or at best a rather pointless limitation of gtk-doc.make.
# See (FIXME: reference to gtk-doc bug report once filed)
#
# During automatic processing, only gtk-doc.make is patched during
# pre_src_prepare hook processing, and Makefile.in files are
# patched afterward if neccesary.  This should help avoid triggering
# maintainer-mode problems in cases where eautoreconf is used.
# However, if eautoreconf is not used, and the Makefile.in files
# are patched, then it is quite probable that maintainer-mode will
# be triggered by this patching, if it is left enabled.
# Consumers of this eclass will have to figure out how to solve this
# problem on their own, no mechanism exists here to prevent it.

# @ECLASS-VARIABLE: GTK_DOC_NO_AUTOMATIC
# @DEFAULT_UNSET
# @DESCRIPTION:
# If set to a nonempty value, no modifications of any kind
# will be made automatically by gtk-doc.eclass using the ehooks.
# However, if gtk-doc_patch_gtk_doc_make or gtk-doc_patch_autotools_files
# are invoked, they will still patch their respective target files

# @ECLASS-VARIABLE: GTK_DOC_AUTO_SRC_PREPARE
# @DEFAULT_UNSET
# @DESCRIPTION:
# If set to a nonempty value, the src_prepare phase will be taken
# over by gtk-doc_src_prepare.  Since this would uninstall any
# previously installed src_prepare phase function, possibly
# invonveniencing ebuild and eclass authors, it is not done
# by default.

case "${EAPI:-0}" in
	2|3|4|5)
		[[ -n ${GTK_DOC_AUTO_SRC_PREPARE} ]] && \
			EXPORT_FUNCTIONS src_prepare
		;;
	*) die "EAPI=${EAPI} is not supported" ;;
esac

if [[ ${___ECLASS_ONCE_GTK_DOC} != "recur -_+^+_- spank" ]] ; then
___ECLASS_ONCE_GTK_DOC="recur -_+^+_- spank"

inherit ehooker

# stores an array of previosly processed gtk-doc.make files
# so that we can respond appropriately to gtkdocize invocations
# the file is only reprocessed if it was processed once already.
declare -a _gtk_doc_patched_gtk_doc_make_files

# @FUNCTION: _gtk_doc_install_src_prepare_notify_ehooks
# @INTERNAL
# @USAGE:
# @DESCRIPTION:
# Installs listners for various ehooks.  Always runs automatically
# upon inheritance of gtk-doc.eclass
_gtk_doc_install_src_prepare_notify_ehooks() {
	debug-print-function "${FUNCNAME}" "$@"
	local prefix prepost
	for prefix in autotools-utils cmake-utils qt4-build-multilib ; do
		for prepost in pre post ; do
			ehook ${prefix}-${prepost}_src_prepare _gtk_doc_${prepost}_src_prepare_notify
		done
	done
}

_gtk_doc_install_src_prepare_notify_ehooks

# @FUNCTION: gtk-doc_src_prepare
# @USAGE:
# @DESCRIPTION:
# src_prepare phase func for gtk-doc. Not wired up unless
# GTK_DOC_AUTO_SRC_PREPARE is nonempty upon gtk-doc inheritance
# Sends internal notifications and invokes default_src_prepare.
gtk-doc_src_prepare() {
	debug-print-function "${FUNCNAME}" "$@"
	_gtk_doc_pre_src_prepare_notify
	default
	local result=$?
	_gtk_doc_post_src_prepare_notify
	return $result
}

# @FUNCTION: _gtk_doc_pre_src_prepare_notify
# @INTERNAL
# @USAGE:
# @DESCRIPTION:
# ehook listener function for various ehooks indiciating that a
# src_prepare phase is about to begin.  gtk-doc.eclass takes
# this opportunity to dink around with gtk-doc.make such that
# if eautoreconf is run, gtk-doc-generating Makefile.in's will
# be generated with the patched logic to support out-of-tree building
_gtk_doc_pre_src_prepare_notify() {
	debug-print-function "${FUNCNAME}" "$@"
	[[ -n ${GTK_DOC_NO_AUTOMATIC} ]] && return 0
	# if "${S}" doesn't exist then who knows what the hell we should do...
	if [[ -d "${S}" ]] ; then
		gtk-doc_patch_gtk_doc_make "${S}/gtk-doc.make"
	fi
	return 0
}

# @FUNCTION: _gtk_doc_post_src_prepare_notify
# @INTERNAL
# @USAGE:
# @DESCRIPTION:
# ehook listener function for various ehooks indiciating that a
# src_prepare phase has just completed.  gtk-doc.eclass takes this
# opportunity to ensure that all patches relevant to out-of-tree
# build support have been applied to various files in "${S}".
_gtk_doc_post_src_prepare_notify() {
	debug-print-function "${FUNCNAME}" "$@"
	[[ -n ${GTK_DOC_NO_AUTOMATIC} ]] && return 0

	# if "${S}" doesn't exist then who knows what the hell we should do...
	if [[ -d "${S}" ]] ; then
		# just in case gtkdocize got called somehow and we missed it.
		gtk-doc_patch_gtk_doc_make "${S}/gtk-doc.make"

		gtk-doc_patch_autotools_files "${S}"
	fi

	return 0
}

# egtkdocize will undo our changes, so listen for that and reapply
# patches any time this happens.
ehook autotools-post_egtkdocize _gtk_doc_post_egtkdocize_notify

# @FUNCTION: _gtk_doc_post_egtkdocize_notify
# @INTERNAL
# @USAGE:
# @DESCRIPTION:
# Automagically installed autotools-post_egtkdocize ehook listener.
# If gtkdocize may have removed gtk-doc.make patches after they were
# applied, by gtk-doc.eclass, re-apply them -- otherwise, do nothing.
_gtk_doc_post_egtkdocize_notify() {
	debug-print-function "${FUNCNAME}" "$@"

	[[ -f gtk-doc.make ]] || return 0
	local f="$(pwd)/gtk-doc.make"
	if has "${f}" "${_gtk_doc_patched_gtk_doc_make_files[@]}" ; then
		gtk-doc_patch_gtk_doc_make "${f}"
	fi
	return 0
}

# @FUNCTION: gtk-doc_patch_gtk_doc_make
# @USAGE: [<gtk-doc.make file>]
# @DESCRIPTION:
# Analyses gtk-doc.make (or a similar, but differently named file)
# and, if needed, patches the file to support out-of-tree building.
# Memorizes that the patch was installed, so that future calls to
# egtkdocize in autotools.eclass will not overwrite the patches
# (the patches are re-applied in this case, when the
# autotools-post_egtkdocize ehook is fired)
gtk-doc_patch_gtk_doc_make() {
	debug-print-function "${FUNCNAME}" "$@"

	[[ $# -gt 1 ]] && die "Too many arguments"

	local _gtk_doc_make_file
	if [[ $# -eq 1 ]] ; then
		_gtk_doc_make_file="$1"
	else
		_gtk_doc_make_file="${S}"/gtk-doc.make
	fi

	[[ ${_gtk_doc_make_file} == /* ]] || die "absolute path not supplied/determined"

	[[ -f "${_gtk_doc_make_file}" ]] && \
		_do_gtk_doc_make_patch "${_gtk_doc_make_file}"

	return 0
}

# @FUNCTION: gtk-doc_patch_gtk_doc_make
# @INTERNAL
# @USAGE: <gtk-doc.make file>
# @DESCRIPTION:
# patch file if neccesary and ensure it's represented in
# _gtk_doc_patched_gtk_doc_make_files
_do_gtk_doc_make_patch() {
	debug-print-function "${FUNCNAME}" "$@"
    _do_gtk_doc_patch_file "$1" --gtkdocmake
	has "$1" "${_gtk_doc_patched_gtk_doc_make_files[@]}" || \
		_gtk_doc_patched_gtk_doc_make_files+=("$1")
	return 0
}

# @FUNCTION: gtk-doc_patch_autotools_files
# @INTERNAL
# @USAGE: [list-of-directories]
# @DESCRIPTION:
# In each of the provided directories and all of its subdirectories,
# patch each Makefile.in file (if neccesary) with changes corresponding
# to the patches in gtk-doc.make
gtk-doc_patch_autotools_files() {
	debug-print-function "${FUNCNAME}" "$@"

	declare -a dirs
	if [[ $# -gt 0 ]] ; then
		dirs=("$@")
	else
		dirs=( "${S}" )
	fi

	local f
	while read f ; do
		_do_gtk_doc_patch_file "${f}" --makefilein
	done < <(
		local d
		for d in "${dirs[@]}" ; do
			pushd "${d}" >/dev/null || die "cannot chdir to \"${d}\" for autotools files processing"
			d="$(pwd)"
			popd >/dev/null || die
			# Serious brute-force approach here...
			find "${d}" -type f -name 'Makefile.in' -print
		done
	)
}

# @FUNCTION: _do_gtk_doc_patch_file
# @INTERNAL
# @USAGE: <file-name> <--gtkdocmake|--makefilein>
# @DESCRIPTION:
# Analyze the provided file and, if out-of-tree build patches
# have not been applied, apply them.
_do_gtk_doc_patch_file() {
	debug-print-function "${FUNCNAME}" "$@"

	[[ $# -eq 2 ]] || die "_do_gtk_doc_patch_file: $# arguments are not 2"
	local f="$1"
	local is_gtk_doc_make=no
	if [[ $2 == --gtkdocmake ]] ; then
		is_gtk_doc_make=yes
	elif [[ $2 != --makefilein ]] ; then
		die "invalid second argument to _do_gtk_doc_patch_file: \"$2\""
	fi
	[[ -f "${f}" ]] || die "no such file as \"${f}\""

	local sedscript='/^\t\(@\|(\)installfiles=`echo \$(builddir)\/html/,'
    sedscript="${sedscript}"'/^[[:space:]]*\((which gtkdoc-rebase\|\$(GTKDOC_REBASE)\)/'
    sedscript="${sedscript}"' s|(builddir)|(installhtmlfromdir)|g'

	# slurp entire file into buffer so we can s/// first pattern occurence only
	local sedscript2=':a;$!{N;ba};'
	if [[ ${is_gtk_doc_make} == yes ]] ; then
		sedscript2="${sedscript2}"'s/\nif ENABLE_GTK_DOC/'
		sedscript2="${sedscript2}"'\nif ENABLE_GTK_DOC\n'
		sedscript2="${sedscript2}"'installhtmlfromdir=$(builddir)\n'
		sedscript2="${sedscript2}"'else\n'
		sedscript2="${sedscript2}"'installhtmlfromdir=$(srcdir)\n'
		sedscript2="${sedscript2}"'endif&/'
	else
		sedscript2="${sedscript2}"'s/\n@ENABLE_GTK_DOC_\(TRUE\|FALSE\)@/'
		sedscript2="${sedscript2}"'\n@ENABLE_GTK_DOC_FALSE@installhtmlfromdir = $(srcdir)\n'
		sedscript2="${sedscript2}"'@ENABLE_GTK_DOC_TRUE@installhtmlfromdir = $(builddir)&/'
	fi

	local orig_file_contents=$(cat "${f}")
	# basic recipe: apply sedscript; if anything changed, apply sedscript2
	# as well, and finally, announce what happened via einfo
	sed -e "${sedscript}" -i "${f}" || die
	local new_file_contents=$(cat "${f}")
	if [[ "${orig_file_contents}" != "${new_file_contents}" ]] ; then
		sed -e "${sedscript2}" -i "${f}" || die
		new_file_contents=$(cat "${f}")
		einfo "gtk-doc: modified \"${f}\" for out-of-tree build support"
		if [[ -n ${ECLASS_DEBUG_OUTPUT} ]] ; then
			debug-print "${FUNCNAME}: ==== ${f} changes injected ===="
			local aline
			while IFS= read -r aline ; do
				debug-print "${FUNCNAME}:	${aline}"
			done < <("$(type -P colordiff diff cat | head -n 1)" -u <(echo "${orig_file_contents}") <(echo "${new_file_contents}"); echo)
		fi
	fi
	return 0
}

# @FUNCTION: gtk-doc_do_patches
# @USAGE: [list-of-directories]
# @DESCRIPTION:
# Within the provided list of directories (or "${S}", if none
# are provided), execute any patching neccesary for gtk-doc to
# support out-of-tree builds.
gtk-doc_do_patches() {
	debug-print-function "${FUNCNAME}" "$@"
	local srcdir
	declare -a srcdirs
	if [[ -n "$*" ]] ; then
		srcdirs=( "$@" )
	else
		srcdirs=( "${S}" )
	fi
	for srcdir in "${srcdirs[@]}" ; do
		pushd "${srcdir}" >/dev/null || die "unable to cd to \"${srcdir}\""
		gtk-doc_patch_gtk_doc_make "$(pwd)"/gtk-doc.make
		gtk-doc_patch_autotools_files "$(pwd)"
		popd >/dev/null || die
	done
}

fi # ___ECLASS_ONCE_GTK_DOC