x11-misc/alock: Take ownership of package
[gentoo.git] / eclass / gnat.eclass
1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Id$
4 #
5 # Author: George Shapovalov <george@gentoo.org>
6 # Belongs to: ada herd <ada@gentoo.org>
7 #
8 # This eclass provides the framework for ada lib installation with the split and
9 # SLOTted gnat compilers (gnat-xxx, gnatbuild.eclass). Each lib gets built once
10 # for every installed gnat compiler. Activation of a particular bunary module is
11 # performed by eselect-gnat, when the active compiler gets switched
12 #
13 # The ebuilds should define the lib_compile and lib_install functions that are
14 # called from the (exported) gnat_src_compile function of eclass. These
15 # functions should operate similarly to the starndard src_compile and
16 # src_install. The only difference, that they should use $SL variable instead of
17 # $S (this is where the working copy of source is held) and $DL instead of $D as
18 # its installation point.
19
20 inherit flag-o-matic eutils multilib
21
22 # The environment is set locally in src_compile and src_install functions
23 # by the common code sourced here and in gnat-eselect module.
24 # This is the standard location for this code (belongs to eselect-gnat,
25 # since eselect should work even in the absense of portage tree and we can
26 # guarantee to some extent presence of gnat-eselect when anything gnat-related
27 # gets processed. See #192505)
28 #
29 # Note!
30 # It may not be safe to source this at top level. Only source inside local
31 # functions!
32 GnatCommon="/usr/share/gnat/lib/gnat-common.bash"
33
34 # !!NOTE!!
35 # src_install should not be exported!
36 # Instead gnat_src_install should be explicitly called from within src_install.
37 EXPORT_FUNCTIONS pkg_setup pkg_postinst src_compile
38
39 DESCRIPTION="Common procedures for building Ada libs using split gnat compilers"
40
41 # make sure we have an appropriately recent eselect-gnat installed, as we are
42 # using some common code here.
43 DEPEND=">=app-eselect/eselect-gnat-1.3"
44
45
46 # ----------------------------------
47 # Globals
48
49 # Lib install locations
50 #
51 # Gnat profile dependent files go under ${LibTop}/${Gnat_Profile}/${PN}
52 # and common files go under SpecsDir, DataDir..
53 # In order not to pollute PATH and LDPATH attempt should be mabe to install
54 # binaries and what makes sence for individual packages under
55 # ${AdalibLibTop}/${Gnat_Profile}/bin
56 PREFIX=/usr
57 AdalibSpecsDir=${PREFIX}/include/ada
58 AdalibDataDir=${PREFIX}/share/ada
59 AdalibLibTop=${PREFIX}/$(get_libdir)/ada
60
61 # build-time locations
62 # SL is a "localized" S, - location where sources are copied for
63 #bi profile-specific build
64 SL=${WORKDIR}/LocalSource
65
66 # DL* are "localized destinations" where ARCH/SLOT dependent stuff should be
67 # installed in lib_install.   There are three:
68 #
69 DL=${WORKDIR}/LocalDest
70 #       a generic location for the lib (.a, .so) files
71 #
72 DLbin=${WORKDIR}/LocalBinDest
73 #       binaries that should be in the PATH, will be moved to common Ada bin dir
74 #
75 DLgpr=${WORKDIR}/LocalGPRDest
76 #       gpr's should go here.
77
78 # file containing environment formed by gnat-eselect (build-time)
79 BuildEnv=${WORKDIR}/BuildEnv
80
81 # environment for installed lib. Profile-specific stuff should use %DL% as a top
82 # of their location. This (%DL%) will be substituted with a proper location upon
83 # install
84 LibEnv=${WORKDIR}/LibEnv
85
86
87 # env file prepared by gnat.eselect only lists new settings for env vars
88 # we need to change that to prepend, rather than replace action..
89 # Takes one argument - the file to expand. This file should contain only
90 # var=value like lines.. (commenst are Ok)
91 expand_BuildEnv() {
92         local line
93         for line in $(cat $1); do
94                 EnvVar=$(echo ${line}|cut -d"=" -f1)
95                 if [[ "${EnvVar}" == "PATH" ]] ; then
96                         echo "export ${line}:\${${EnvVar}}" >> $1.tmp
97                 else
98                         echo "export ${line}" >> $1.tmp
99                 fi
100         done
101         mv $1.tmp $1
102 }
103
104
105 # ------------------------------------
106 # Dependency processing related stuff
107
108 # A simple wrapper to get the relevant part of the DEPEND
109 # params:
110 #  $1 - should contain dependency specification analogous to DEPEND,
111 #       if omitted, DEPEND is processed
112 get_ada_dep() {
113         [[ -z "$1" ]] && DEP="${DEPEND}" || DEP="$1"
114         local TempStr
115         for fn in $DEP; do # here $DEP should *not* be in ""
116                 [[ $fn =~ "virtual/ada" ]] && TempStr=${fn/*virtual\//}
117                 # above match should be to full virtual/ada, as simply "ada" is a common
118                 # part of ${PN}, even for some packages under dev-ada
119         done
120 #       debug-print-function $FUNCNAME "TempStr=${TempStr:0:8}"
121         [[ -n ${TempStr} ]] && echo ${TempStr:0:8}
122 }
123
124 # This function is used to check whether the requested gnat profile matches the
125 # requested Ada standard
126 # !!ATTN!!
127 # This must match dependencies as specified in vitrual/ada !!!
128 #
129 # params:
130 #  $1 - the requested gnat profile in usual form (e.g. x86_64-pc-linux-gnu-gnat-gcc-4.1)
131 #  $2 - Ada standard specification, as would be specified in DEPEND.
132 #       Valid  values: ada-1995, ada-2005, ada
133 #
134 #       This used to treat ada-1995 and ada alike, but some packages (still
135 #       requested by users) no longer compile with new compilers (not the
136 #       standard issue, but rather compiler becoming stricter most of the time).
137 #       Plus there are some "intermediary versions", not fully 2005 compliant
138 #       but already causing problems.  Therefore, now we do exact matching.
139 belongs_to_standard() {
140 #       debug-print-function $FUNCNAME $*
141         . ${GnatCommon} || die "failed to source gnat-common lib"
142         local GnatSlot=$(get_gnat_SLOT $1)
143         local ReducedSlot=${GnatSlot//\./}
144         #
145         if [[ $2 == 'ada' ]] ; then
146 #               debug-print-function "ada or ada-1995 match"
147                 return 0 # no restrictions imposed
148         elif [[ "$2" == 'ada-1995' ]] ; then
149                 if [[ $(get_gnat_Pkg $1) == "gcc" ]]; then
150 #                       debug-print-function "got gcc profile, GnatSlot=${ReducedSlot}"
151                         [[ ${ReducedSlot} -le "42" ]] && return 0 || return 1
152                 elif [[ $(get_gnat_Pkg $1) == "gpl" ]]; then
153 #                       debug-print-function "got gpl profile, GnatSlot=${ReducedSlot}"
154                         [[ ${ReducedSlot} -lt "41" ]] && return 0 || return 1
155                 else
156                         return 1 # unknown compiler encountered
157                 fi
158         elif [[ "$2" == 'ada-2005' ]] ; then
159                 if [[ $(get_gnat_Pkg $1) == "gcc" ]]; then
160 #                       debug-print-function "got gcc profile, GnatSlot=${ReducedSlot}"
161                         [[ ${ReducedSlot} -ge "43" ]] && return 0 || return 1
162                 elif [[ $(get_gnat_Pkg $1) == "gpl" ]]; then
163 #                       debug-print-function "got gpl profile, GnatSlot=${ReducedSlot}"
164                         [[ ${ReducedSlot} -ge "41" ]] && return 0 || return 1
165                 else
166                         return 1 # unknown compiler encountered
167                 fi
168         else
169                 return 1 # unknown standard requested, check spelling!
170         fi
171 }
172
173
174 # ------------------------------------
175 # Helpers
176 #
177
178
179 # The purpose of this one is to remove all parts of the env entry specific to a
180 # given lib. Usefull when some lib wants to act differently upon detecting
181 # itself installed..
182 #
183 # params:
184 #  $1 - name of env var to process
185 #  $2 (opt) - name of the lib to filter out (defaults to ${PN})
186 filter_env_var() {
187         local entries=(${!1//:/ })
188         local libName=${2:-${PN}}
189         local env_str
190         for entry in ${entries[@]} ; do
191                 # this simply checks if $libname is a substring of the $entry, should
192                 # work fine with all the present libs
193                 if [[ ${entry/${libName}/} == ${entry} ]] ; then
194                         env_str="${env_str}:${entry}"
195                 fi
196         done
197         echo ${env_str}
198 }
199
200 # A simpler helper, for the libs that need to extract active gnat location
201 # Returns a first entry for a specified env var. Relies on the (presently true)
202 # convention that first gnat's entries are listed and then of the other
203 # installed libs.
204 #
205 # params:
206 #  $1 - name of env var to process
207 get_gnat_value() {
208         local entries=(${!1//:/ })
209         echo ${entries[0]}
210 }
211
212
213 # Returns a name of active gnat profile. Performs some validity checks. No input
214 # parameters, analyzes the system setup directly.
215 get_active_profile() {
216         # get common code and settings
217         . ${GnatCommon} || die "failed to source gnat-common lib"
218
219         local profiles=( $(get_env_list) )
220
221         if [[ ${profiles[@]} == "${MARKER}*" ]]; then
222                 return
223                 # returning empty string
224         fi
225
226         if (( 1 == ${#profiles[@]} )); then
227                 local active=${profiles[0]#${MARKER}}
228         else
229                 die "${ENVDIR} contains multiple gnat profiles, please cleanup!"
230         fi
231
232         if [[ -f ${SPECSDIR}/${active} ]]; then
233                 echo ${active}
234         else
235                 die "The profile active in ${ENVDIR} does not correspond to any installed gnat!"
236         fi
237 }
238
239
240
241 # ------------------------------------
242 # Functions
243
244 # Checks the gnat backend SLOT and filters flags correspondingly
245 # To be called from scr_compile for each profile, before actual compilation
246 # Parameters:
247 #  $1 - gnat profile, e.g. x86_64-pc-linux-gnu-gnat-gcc-3.4
248 gnat_filter_flags() {
249         debug-print-function $FUNCNAME $*
250
251         # We only need to filter so severely if backends < 3.4 is detected, which
252         # means basically gnat-3.15
253         GnatProfile=$1
254         if [ -z ${GnatProfile} ]; then
255                 # should not get here!
256                 die "please specify a valid gnat profile for flag stripping!"
257         fi
258
259         local GnatSLOT="${GnatProfile//*-/}"
260         if [[ ${GnatSLOT} < 3.4 ]] ; then
261                 filter-mfpmath sse 387
262
263                 filter-flags -mmmx -msse -mfpmath -frename-registers \
264                         -fprefetch-loop-arrays -falign-functions=4 -falign-jumps=4 \
265                         -falign-loops=4 -msse2 -frerun-loop-opt -maltivec -mabi=altivec \
266                         -fsigned-char -fno-strict-aliasing -pipe
267
268                 export ADACFLAGS=${ADACFLAGS:-${CFLAGS}}
269                 export ADACFLAGS=${ADACFLAGS//-Os/-O2}
270                 export ADACFLAGS=${ADACFLAGS//pentium-mmx/i586}
271                 export ADACFLAGS=${ADACFLAGS//pentium[234]/i686}
272                 export ADACFLAGS=${ADACFLAGS//k6-[23]/k6}
273                 export ADACFLAGS=${ADACFLAGS//athlon-tbird/i686}
274                 export ADACFLAGS=${ADACFLAGS//athlon-4/i686}
275                 export ADACFLAGS=${ADACFLAGS//athlon-[xm]p/i686}
276                 # gcc-2.8.1 has no amd64 support, so the following two are safe
277                 export ADACFLAGS=${ADACFLAGS//athlon64/i686}
278                 export ADACFLAGS=${ADACFLAGS//athlon/i686}
279         else
280                 export ADACFLAGS=${ADACFLAGS:-${CFLAGS}}
281         fi
282
283         export ADAMAKEFLAGS=${ADAMAKEFLAGS:-"-cargs ${ADACFLAGS} -margs"}
284         export ADABINDFLAGS=${ADABINDFLAGS:-""}
285 }
286
287 gnat_pkg_setup() {
288         debug-print-function $FUNCNAME $*
289
290         # check whether all the primary compilers are installed
291         . ${GnatCommon} || die "failed to source gnat-common lib"
292         for fn in $(cat ${PRIMELIST}); do
293                 if [[ ! -f ${SPECSDIR}/${fn} ]]; then
294                         elog "The ${fn} Ada compiler profile is specified as primary, but is not installed."
295                         elog "Please rectify the situation before emerging Ada library!"
296                         elog "Please either install again all the missing compilers listed"
297                         elog "as primary, or edit /etc/ada/primary_compilers and update the"
298                         elog "list of primary compilers there."
299                         einfo ""
300                         ewarn "If you do the latter, please don't forget to rebuild all"
301                         ewarn "affected libs!"
302                         die "Primary compiler is missing"
303                 fi
304         done
305
306         export ADAC=${ADAC:-gnatgcc}
307         export ADAMAKE=${ADAMAKE:-gnatmake}
308         export ADABIND=${ADABIND:-gnatbind}
309 }
310
311
312 gnat_pkg_postinst() {
313         einfo "Updating gnat configuration to pick up ${PN} library..."
314         eselect gnat update
315         elog "The environment has been set up to make gnat automatically find files"
316         elog "for the installed library. In order to immediately activate these"
317         elog "settings please run:"
318         elog
319         #elog "env-update"
320         elog "source /etc/profile"
321         einfo
322         einfo "Otherwise the settings will become active next time you login"
323 }
324
325
326
327
328 # standard lib_compile plug. Adapted from base.eclass
329 lib_compile() {
330         debug-print-function $FUNCNAME $*
331         [ -z "$1" ] && lib_compile all
332
333         cd ${SL}
334
335         while [ "$1" ]; do
336         case $1 in
337                 configure)
338                         debug-print-section configure
339                         econf || die "died running econf, $FUNCNAME:configure"
340                 ;;
341                 make)
342                         debug-print-section make
343                         emake || die "died running emake, $FUNCNAME:make"
344                 ;;
345                 all)
346                         debug-print-section all
347                         lib_compile configure make
348                 ;;
349         esac
350         shift
351         done
352 }
353
354 # Cycles through installed gnat profiles and calls lib_compile and then
355 # lib_install in turn.
356 # Use this function to build/install profile-specific binaries. The code
357 # building/installing common stuff (docs, etc) can go before/after, as needed,
358 # so that it is called only once..
359 #
360 # lib_compile and lib_install are passed the active gnat profile name - may be used or
361 # discarded as needed..
362 gnat_src_compile() {
363         debug-print-function $FUNCNAME $*
364
365         # We source the eselect-gnat module and use its functions directly, instead of
366         # duplicating code or trying to violate sandbox in some way..
367         . ${GnatCommon} || die "failed to source gnat-common lib"
368
369         compilers=( $(find_primary_compilers ) )
370         if [[ -n ${compilers[@]} ]] ; then
371                 local i
372                 local AdaDep=$(get_ada_dep)
373                 for (( i = 0 ; i < ${#compilers[@]} ; i = i + 1 )) ; do
374                         if $(belongs_to_standard ${compilers[${i}]} ${AdaDep}); then
375                                 einfo "compiling for gnat profile ${compilers[${i}]}"
376
377                                 # copy sources
378                                 mkdir "${DL}" "${DLbin}" "${DLgpr}"
379                                 cp -dpR "${S}" "${SL}"
380
381                                 # setup environment
382                                 # As eselect-gnat also manages the libs, this will ensure the right
383                                 # lib profiles are activated too (in case we depend on some Ada lib)
384                                 generate_envFile ${compilers[${i}]} ${BuildEnv} && \
385                                 expand_BuildEnv "${BuildEnv}" && \
386                                 . "${BuildEnv}"  || die "failed to switch to ${compilers[${i}]}"
387                                 # many libs (notably xmlada and gtkada) do not like to see
388                                 # themselves installed. Need to strip them from ADA_*_PATH
389                                 # NOTE: this should not be done in pkg_setup, as we setup
390                                 # environment right above
391                                 export ADA_INCLUDE_PATH=$(filter_env_var ADA_INCLUDE_PATH)
392                                 export ADA_OBJECTS_PATH=$(filter_env_var ADA_OBJECTS_PATH)
393
394                                 # call compilation callback
395                                 cd "${SL}"
396                                 gnat_filter_flags ${compilers[${i}]}
397                                 lib_compile ${compilers[${i}]} || die "failed compiling for ${compilers[${i}]}"
398
399                                 # call install callback
400                                 cd "${SL}"
401                                 lib_install ${compilers[${i}]} || die "failed installing profile-specific part for ${compilers[${i}]}"
402                                 # move installed and cleanup
403                                 mv "${DL}" "${DL}-${compilers[${i}]}"
404                                 mv "${DLbin}" "${DLbin}-${compilers[${i}]}"
405                                 mv "${DLgpr}" "${DLgpr}-${compilers[${i}]}"
406                                 rm -rf "${SL}"
407                         else
408                                 einfo "skipping gnat profile ${compilers[${i}]}"
409                         fi
410                 done
411         else
412                 ewarn "Please note!"
413                 elog "Treatment of installed Ada compilers has recently changed!"
414                 elog "Libs are now being built only for \"primary\" compilers."
415                 elog "Please list gnat profiles (as reported by \"eselect gnat list\")"
416                 elog "that you want to regularly use (i.e., not just for testing)"
417                 elog "in ${PRIMELIST}, one per line."
418                 die "please make sure you have at least one gnat compiler installed and set as primary!"
419         fi
420 }
421
422
423 # This function simply moves gnat-profile-specific stuff into proper locations.
424 # Use src_install in ebuild to install the rest of the package
425 gnat_src_install() {
426         debug-print-function $FUNCNAME $*
427
428         # prep lib specs directory
429         . ${GnatCommon} || die "failed to source gnat-common lib"
430         dodir ${SPECSDIR}/${PN}
431
432         compilers=( $(find_primary_compilers) )
433         if [[ -n ${compilers[@]} ]] ; then
434                 local i
435                 local AdaDep=$(get_ada_dep)
436                 for (( i = 0 ; i < ${#compilers[@]} ; i = i + 1 )) ; do
437                         if $(belongs_to_standard ${compilers[${i}]} ${AdaDep}); then
438                                 debug-print-section "installing for gnat profile ${compilers[${i}]}"
439
440                                 local DLlocation=${AdalibLibTop}/${compilers[${i}]}
441                                 dodir ${DLlocation}
442                                 cp -dpR "${DL}-${compilers[${i}]}" "${D}/${DLlocation}/${PN}"
443                                 cp -dpR "${DLbin}-${compilers[${i}]}" "${D}/${DLlocation}"/bin
444                                 cp -dpR "${DLgpr}-${compilers[${i}]}" "${D}/${DLlocation}"/gpr
445                                 # create profile-specific specs file
446                                 cp ${LibEnv} "${D}/${SPECSDIR}/${PN}/${compilers[${i}]}"
447                                 sed -i -e "s:%DL%:${DLlocation}/${PN}:g" "${D}/${SPECSDIR}/${PN}/${compilers[${i}]}"
448                                 sed -i -e "s:%DLbin%:${DLlocation}/bin:g" "${D}/${SPECSDIR}/${PN}/${compilers[${i}]}"
449                                 sed -i -e "s:%DLgpr%:${DLlocation}/gpr:g" "${D}/${SPECSDIR}/${PN}/${compilers[${i}]}"
450                         else
451                                 einfo "skipping gnat profile ${compilers[${i}]}"
452                         fi
453                 done
454         else
455                 die "please make sure you have at least one gnat compiler installed!"
456         fi
457 }