# Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ # @ECLASS: gtk-doc.eclass # @MAINTAINER: # Greg Turner # @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: [] # @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: # @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: <--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