kde-apps/ksirk: x86 stable (bug #661810)
[gentoo.git] / eclass / toolchain-funcs.eclass
1 # Copyright 1999-2018 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: toolchain-funcs.eclass
5 # @MAINTAINER:
6 # Toolchain Ninjas <toolchain@gentoo.org>
7 # @BLURB: functions to query common info about the toolchain
8 # @DESCRIPTION:
9 # The toolchain-funcs aims to provide a complete suite of functions
10 # for gleaning useful information about the toolchain and to simplify
11 # ugly things like cross-compiling and multilib.  All of this is done
12 # in such a way that you can rely on the function always returning
13 # something sane.
14
15 if [[ -z ${_TOOLCHAIN_FUNCS_ECLASS} ]]; then
16 _TOOLCHAIN_FUNCS_ECLASS=1
17
18 inherit multilib
19
20 # tc-getPROG <VAR [search vars]> <default> [tuple]
21 _tc-getPROG() {
22         local tuple=$1
23         local v var vars=$2
24         local prog=( $3 )
25
26         var=${vars%% *}
27         for v in ${vars} ; do
28                 if [[ -n ${!v} ]] ; then
29                         export ${var}="${!v}"
30                         echo "${!v}"
31                         return 0
32                 fi
33         done
34
35         local search=
36         [[ -n $4 ]] && search=$(type -p $4-${prog[0]})
37         [[ -z ${search} && -n ${!tuple} ]] && search=$(type -p ${!tuple}-${prog[0]})
38         [[ -n ${search} ]] && prog[0]=${search##*/}
39
40         export ${var}="${prog[*]}"
41         echo "${!var}"
42 }
43 tc-getBUILD_PROG() {
44         local vars="BUILD_$1 $1_FOR_BUILD HOST$1"
45         # respect host vars if not cross-compiling
46         # https://bugs.gentoo.org/630282
47         tc-is-cross-compiler || vars+=" $1"
48         _tc-getPROG CBUILD "${vars}" "${@:2}"
49 }
50 tc-getPROG() { _tc-getPROG CHOST "$@"; }
51
52 # @FUNCTION: tc-getAR
53 # @USAGE: [toolchain prefix]
54 # @RETURN: name of the archiver
55 tc-getAR() { tc-getPROG AR ar "$@"; }
56 # @FUNCTION: tc-getAS
57 # @USAGE: [toolchain prefix]
58 # @RETURN: name of the assembler
59 tc-getAS() { tc-getPROG AS as "$@"; }
60 # @FUNCTION: tc-getCC
61 # @USAGE: [toolchain prefix]
62 # @RETURN: name of the C compiler
63 tc-getCC() { tc-getPROG CC gcc "$@"; }
64 # @FUNCTION: tc-getCPP
65 # @USAGE: [toolchain prefix]
66 # @RETURN: name of the C preprocessor
67 tc-getCPP() { tc-getPROG CPP "${CC:-gcc} -E" "$@"; }
68 # @FUNCTION: tc-getCXX
69 # @USAGE: [toolchain prefix]
70 # @RETURN: name of the C++ compiler
71 tc-getCXX() { tc-getPROG CXX g++ "$@"; }
72 # @FUNCTION: tc-getLD
73 # @USAGE: [toolchain prefix]
74 # @RETURN: name of the linker
75 tc-getLD() { tc-getPROG LD ld "$@"; }
76 # @FUNCTION: tc-getSTRIP
77 # @USAGE: [toolchain prefix]
78 # @RETURN: name of the strip program
79 tc-getSTRIP() { tc-getPROG STRIP strip "$@"; }
80 # @FUNCTION: tc-getNM
81 # @USAGE: [toolchain prefix]
82 # @RETURN: name of the symbol/object thingy
83 tc-getNM() { tc-getPROG NM nm "$@"; }
84 # @FUNCTION: tc-getRANLIB
85 # @USAGE: [toolchain prefix]
86 # @RETURN: name of the archiver indexer
87 tc-getRANLIB() { tc-getPROG RANLIB ranlib "$@"; }
88 # @FUNCTION: tc-getOBJCOPY
89 # @USAGE: [toolchain prefix]
90 # @RETURN: name of the object copier
91 tc-getOBJCOPY() { tc-getPROG OBJCOPY objcopy "$@"; }
92 # @FUNCTION: tc-getOBJDUMP
93 # @USAGE: [toolchain prefix]
94 # @RETURN: name of the object dumper
95 tc-getOBJDUMP() { tc-getPROG OBJDUMP objdump "$@"; }
96 # @FUNCTION: tc-getF77
97 # @USAGE: [toolchain prefix]
98 # @RETURN: name of the Fortran 77 compiler
99 tc-getF77() { tc-getPROG F77 gfortran "$@"; }
100 # @FUNCTION: tc-getFC
101 # @USAGE: [toolchain prefix]
102 # @RETURN: name of the Fortran 90 compiler
103 tc-getFC() { tc-getPROG FC gfortran "$@"; }
104 # @FUNCTION: tc-getGCJ
105 # @USAGE: [toolchain prefix]
106 # @RETURN: name of the java compiler
107 tc-getGCJ() { tc-getPROG GCJ gcj "$@"; }
108 # @FUNCTION: tc-getGO
109 # @USAGE: [toolchain prefix]
110 # @RETURN: name of the Go compiler
111 tc-getGO() { tc-getPROG GO gccgo "$@"; }
112 # @FUNCTION: tc-getPKG_CONFIG
113 # @USAGE: [toolchain prefix]
114 # @RETURN: name of the pkg-config tool
115 tc-getPKG_CONFIG() { tc-getPROG PKG_CONFIG pkg-config "$@"; }
116 # @FUNCTION: tc-getRC
117 # @USAGE: [toolchain prefix]
118 # @RETURN: name of the Windows resource compiler
119 tc-getRC() { tc-getPROG RC windres "$@"; }
120 # @FUNCTION: tc-getDLLWRAP
121 # @USAGE: [toolchain prefix]
122 # @RETURN: name of the Windows dllwrap utility
123 tc-getDLLWRAP() { tc-getPROG DLLWRAP dllwrap "$@"; }
124
125 # @FUNCTION: tc-getBUILD_AR
126 # @USAGE: [toolchain prefix]
127 # @RETURN: name of the archiver for building binaries to run on the build machine
128 tc-getBUILD_AR() { tc-getBUILD_PROG AR ar "$@"; }
129 # @FUNCTION: tc-getBUILD_AS
130 # @USAGE: [toolchain prefix]
131 # @RETURN: name of the assembler for building binaries to run on the build machine
132 tc-getBUILD_AS() { tc-getBUILD_PROG AS as "$@"; }
133 # @FUNCTION: tc-getBUILD_CC
134 # @USAGE: [toolchain prefix]
135 # @RETURN: name of the C compiler for building binaries to run on the build machine
136 tc-getBUILD_CC() { tc-getBUILD_PROG CC gcc "$@"; }
137 # @FUNCTION: tc-getBUILD_CPP
138 # @USAGE: [toolchain prefix]
139 # @RETURN: name of the C preprocessor for building binaries to run on the build machine
140 tc-getBUILD_CPP() { tc-getBUILD_PROG CPP "$(tc-getBUILD_CC) -E" "$@"; }
141 # @FUNCTION: tc-getBUILD_CXX
142 # @USAGE: [toolchain prefix]
143 # @RETURN: name of the C++ compiler for building binaries to run on the build machine
144 tc-getBUILD_CXX() { tc-getBUILD_PROG CXX g++ "$@"; }
145 # @FUNCTION: tc-getBUILD_LD
146 # @USAGE: [toolchain prefix]
147 # @RETURN: name of the linker for building binaries to run on the build machine
148 tc-getBUILD_LD() { tc-getBUILD_PROG LD ld "$@"; }
149 # @FUNCTION: tc-getBUILD_STRIP
150 # @USAGE: [toolchain prefix]
151 # @RETURN: name of the strip program for building binaries to run on the build machine
152 tc-getBUILD_STRIP() { tc-getBUILD_PROG STRIP strip "$@"; }
153 # @FUNCTION: tc-getBUILD_NM
154 # @USAGE: [toolchain prefix]
155 # @RETURN: name of the symbol/object thingy for building binaries to run on the build machine
156 tc-getBUILD_NM() { tc-getBUILD_PROG NM nm "$@"; }
157 # @FUNCTION: tc-getBUILD_RANLIB
158 # @USAGE: [toolchain prefix]
159 # @RETURN: name of the archiver indexer for building binaries to run on the build machine
160 tc-getBUILD_RANLIB() { tc-getBUILD_PROG RANLIB ranlib "$@"; }
161 # @FUNCTION: tc-getBUILD_OBJCOPY
162 # @USAGE: [toolchain prefix]
163 # @RETURN: name of the object copier for building binaries to run on the build machine
164 tc-getBUILD_OBJCOPY() { tc-getBUILD_PROG OBJCOPY objcopy "$@"; }
165 # @FUNCTION: tc-getBUILD_PKG_CONFIG
166 # @USAGE: [toolchain prefix]
167 # @RETURN: name of the pkg-config tool for building binaries to run on the build machine
168 tc-getBUILD_PKG_CONFIG() { tc-getBUILD_PROG PKG_CONFIG pkg-config "$@"; }
169
170 # @FUNCTION: tc-export
171 # @USAGE: <list of toolchain variables>
172 # @DESCRIPTION:
173 # Quick way to export a bunch of compiler vars at once.
174 tc-export() {
175         local var
176         for var in "$@" ; do
177                 [[ $(type -t "tc-get${var}") != "function" ]] && die "tc-export: invalid export variable '${var}'"
178                 "tc-get${var}" > /dev/null
179         done
180 }
181
182 # @FUNCTION: tc-is-cross-compiler
183 # @RETURN: Shell true if we are using a cross-compiler, shell false otherwise
184 tc-is-cross-compiler() {
185         [[ ${CBUILD:-${CHOST}} != ${CHOST} ]]
186 }
187
188 # @FUNCTION: tc-is-softfloat
189 # @DESCRIPTION:
190 # See if this toolchain is a softfloat based one.
191 # @CODE
192 # The possible return values:
193 #  - only:   the target is always softfloat (never had fpu)
194 #  - yes:    the target should support softfloat
195 #  - softfp: (arm specific) the target should use hardfloat insns, but softfloat calling convention
196 #  - no:     the target doesn't support softfloat
197 # @CODE
198 # This allows us to react differently where packages accept
199 # softfloat flags in the case where support is optional, but
200 # rejects softfloat flags where the target always lacks an fpu.
201 tc-is-softfloat() {
202         local CTARGET=${CTARGET:-${CHOST}}
203         case ${CTARGET} in
204                 bfin*|h8300*)
205                         echo "only" ;;
206                 *)
207                         if [[ ${CTARGET//_/-} == *-softfloat-* ]] ; then
208                                 echo "yes"
209                         elif [[ ${CTARGET//_/-} == *-softfp-* ]] ; then
210                                 echo "softfp"
211                         else
212                                 echo "no"
213                         fi
214                         ;;
215         esac
216 }
217
218 # @FUNCTION: tc-is-static-only
219 # @DESCRIPTION:
220 # Return shell true if the target does not support shared libs, shell false
221 # otherwise.
222 tc-is-static-only() {
223         local host=${CTARGET:-${CHOST}}
224
225         # *MiNT doesn't have shared libraries, only platform so far
226         [[ ${host} == *-mint* ]]
227 }
228
229 # @FUNCTION: tc-stack-grows-down
230 # @DESCRIPTION:
231 # Return shell true if the stack grows down.  This is the default behavior
232 # for the vast majority of systems out there and usually projects shouldn't
233 # care about such internal details.
234 tc-stack-grows-down() {
235         # List the few that grow up.
236         case ${ARCH} in
237         hppa|metag) return 1 ;;
238         esac
239
240         # Assume all others grow down.
241         return 0
242 }
243
244 # @FUNCTION: tc-export_build_env
245 # @USAGE: [compiler variables]
246 # @DESCRIPTION:
247 # Export common build related compiler settings.
248 tc-export_build_env() {
249         tc-export "$@"
250         if tc-is-cross-compiler; then
251                 # Some build envs will initialize vars like:
252                 # : ${BUILD_LDFLAGS:-${LDFLAGS}}
253                 # So make sure all variables are non-empty. #526734
254                 : ${BUILD_CFLAGS:=-O1 -pipe}
255                 : ${BUILD_CXXFLAGS:=-O1 -pipe}
256                 : ${BUILD_CPPFLAGS:= }
257                 : ${BUILD_LDFLAGS:= }
258         else
259                 # https://bugs.gentoo.org/654424
260                 : ${BUILD_CFLAGS:=${CFLAGS}}
261                 : ${BUILD_CXXFLAGS:=${CXXFLAGS}}
262                 : ${BUILD_CPPFLAGS:=${CPPFLAGS}}
263                 : ${BUILD_LDFLAGS:=${LDFLAGS}}
264         fi
265         export BUILD_{C,CXX,CPP,LD}FLAGS
266
267         # Some packages use XXX_FOR_BUILD.
268         local v
269         for v in BUILD_{C,CXX,CPP,LD}FLAGS ; do
270                 export ${v#BUILD_}_FOR_BUILD="${!v}"
271         done
272 }
273
274 # @FUNCTION: tc-env_build
275 # @USAGE: <command> [command args]
276 # @INTERNAL
277 # @DESCRIPTION:
278 # Setup the compile environment to the build tools and then execute the
279 # specified command.  We use tc-getBUILD_XX here so that we work with
280 # all of the semi-[non-]standard env vars like $BUILD_CC which often
281 # the target build system does not check.
282 tc-env_build() {
283         tc-export_build_env
284         CFLAGS=${BUILD_CFLAGS} \
285         CXXFLAGS=${BUILD_CXXFLAGS} \
286         CPPFLAGS=${BUILD_CPPFLAGS} \
287         LDFLAGS=${BUILD_LDFLAGS} \
288         AR=$(tc-getBUILD_AR) \
289         AS=$(tc-getBUILD_AS) \
290         CC=$(tc-getBUILD_CC) \
291         CPP=$(tc-getBUILD_CPP) \
292         CXX=$(tc-getBUILD_CXX) \
293         LD=$(tc-getBUILD_LD) \
294         NM=$(tc-getBUILD_NM) \
295         PKG_CONFIG=$(tc-getBUILD_PKG_CONFIG) \
296         RANLIB=$(tc-getBUILD_RANLIB) \
297         "$@"
298 }
299
300 # @FUNCTION: econf_build
301 # @USAGE: [econf flags]
302 # @DESCRIPTION:
303 # Sometimes we need to locally build up some tools to run on CBUILD because
304 # the package has helper utils which are compiled+executed when compiling.
305 # This won't work when cross-compiling as the CHOST is set to a target which
306 # we cannot natively execute.
307 #
308 # For example, the python package will build up a local python binary using
309 # a portable build system (configure+make), but then use that binary to run
310 # local python scripts to build up other components of the overall python.
311 # We cannot rely on the python binary in $PATH as that often times will be
312 # a different version, or not even installed in the first place.  Instead,
313 # we compile the code in a different directory to run on CBUILD, and then
314 # use that binary when compiling the main package to run on CHOST.
315 #
316 # For example, with newer EAPIs, you'd do something like:
317 # @CODE
318 # src_configure() {
319 #       ECONF_SOURCE=${S}
320 #       if tc-is-cross-compiler ; then
321 #               mkdir "${WORKDIR}"/${CBUILD}
322 #               pushd "${WORKDIR}"/${CBUILD} >/dev/null
323 #               econf_build --disable-some-unused-stuff
324 #               popd >/dev/null
325 #       fi
326 #       ... normal build paths ...
327 # }
328 # src_compile() {
329 #       if tc-is-cross-compiler ; then
330 #               pushd "${WORKDIR}"/${CBUILD} >/dev/null
331 #               emake one-or-two-build-tools
332 #               ln/mv build-tools to normal build paths in ${S}/
333 #               popd >/dev/null
334 #       fi
335 #       ... normal build paths ...
336 # }
337 # @CODE
338 econf_build() {
339         local CBUILD=${CBUILD:-${CHOST}}
340         tc-env_build econf --build=${CBUILD} --host=${CBUILD} "$@"
341 }
342
343 # @FUNCTION: tc-ld-is-gold
344 # @USAGE: [toolchain prefix]
345 # @DESCRIPTION:
346 # Return true if the current linker is set to gold.
347 tc-ld-is-gold() {
348         local out
349
350         # First check the linker directly.
351         out=$($(tc-getLD "$@") --version 2>&1)
352         if [[ ${out} == *"GNU gold"* ]] ; then
353                 return 0
354         fi
355
356         # Then see if they're selecting gold via compiler flags.
357         # Note: We're assuming they're using LDFLAGS to hold the
358         # options and not CFLAGS/CXXFLAGS.
359         local base="${T}/test-tc-gold"
360         cat <<-EOF > "${base}.c"
361         int main() { return 0; }
362         EOF
363         out=$($(tc-getCC "$@") ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -Wl,--version "${base}.c" -o "${base}" 2>&1)
364         rm -f "${base}"*
365         if [[ ${out} == *"GNU gold"* ]] ; then
366                 return 0
367         fi
368
369         # No gold here!
370         return 1
371 }
372
373 # @FUNCTION: tc-ld-disable-gold
374 # @USAGE: [toolchain prefix]
375 # @DESCRIPTION:
376 # If the gold linker is currently selected, configure the compilation
377 # settings so that we use the older bfd linker instead.
378 tc-ld-disable-gold() {
379         if ! tc-ld-is-gold "$@" ; then
380                 # They aren't using gold, so nothing to do!
381                 return
382         fi
383
384         ewarn "Forcing usage of the BFD linker instead of GOLD"
385
386         # Set up LD to point directly to bfd if it's available.
387         # We need to extract the first word in case there are flags appended
388         # to its value (like multilib).  #545218
389         local ld=$(tc-getLD "$@")
390         local bfd_ld="${ld%% *}.bfd"
391         local path_ld=$(which "${bfd_ld}" 2>/dev/null)
392         [[ -e ${path_ld} ]] && export LD=${bfd_ld}
393
394         # Set up LDFLAGS to select gold based on the gcc / clang version.
395         local fallback="true"
396         if tc-is-gcc; then
397                 local major=$(gcc-major-version "$@")
398                 local minor=$(gcc-minor-version "$@")
399                 if [[ ${major} -gt 4 ]] || [[ ${major} -eq 4 && ${minor} -ge 8 ]]; then
400                         # gcc-4.8+ supports -fuse-ld directly.
401                         export LDFLAGS="${LDFLAGS} -fuse-ld=bfd"
402                         fallback="false"
403                 fi
404         elif tc-is-clang; then
405                 local major=$(clang-major-version "$@")
406                 local minor=$(clang-minor-version "$@")
407                 if [[ ${major} -gt 3 ]] || [[ ${major} -eq 3 && ${minor} -ge 5 ]]; then
408                         # clang-3.5+ supports -fuse-ld directly.
409                         export LDFLAGS="${LDFLAGS} -fuse-ld=bfd"
410                         fallback="false"
411                 fi
412         fi
413         if [[ ${fallback} == "true" ]] ; then
414                 # <=gcc-4.7 and <=clang-3.4 require some coercion.
415                 # Only works if bfd exists.
416                 if [[ -e ${path_ld} ]] ; then
417                         local d="${T}/bfd-linker"
418                         mkdir -p "${d}"
419                         ln -sf "${path_ld}" "${d}"/ld
420                         export LDFLAGS="${LDFLAGS} -B${d}"
421                 else
422                         die "unable to locate a BFD linker to bypass gold"
423                 fi
424         fi
425 }
426
427 # @FUNCTION: tc-has-openmp
428 # @USAGE: [toolchain prefix]
429 # @DESCRIPTION:
430 # See if the toolchain supports OpenMP.
431 tc-has-openmp() {
432         local base="${T}/test-tc-openmp"
433         cat <<-EOF > "${base}.c"
434         #include <omp.h>
435         int main() {
436                 int nthreads, tid, ret = 0;
437                 #pragma omp parallel private(nthreads, tid)
438                 {
439                 tid = omp_get_thread_num();
440                 nthreads = omp_get_num_threads(); ret += tid + nthreads;
441                 }
442                 return ret;
443         }
444         EOF
445         $(tc-getCC "$@") -fopenmp "${base}.c" -o "${base}" >&/dev/null
446         local ret=$?
447         rm -f "${base}"*
448         return ${ret}
449 }
450
451 # @FUNCTION: tc-check-openmp
452 # @DESCRIPTION:
453 # Test for OpenMP support with the current compiler and error out with
454 # a clear error message, telling the user how to rectify the missing
455 # OpenMP support that has been requested by the ebuild. Using this function
456 # to test for OpenMP support should be preferred over tc-has-openmp and
457 # printing a custom message, as it presents a uniform interface to the user.
458 tc-check-openmp() {
459         if ! tc-has-openmp; then
460                 eerror "Your current compiler does not support OpenMP!"
461
462                 if tc-is-gcc; then
463                         eerror "Enable OpenMP support by building sys-devel/gcc with USE=\"openmp\"."
464                 elif tc-is-clang; then
465                         eerror "OpenMP support in sys-devel/clang is provided by sys-libs/libomp."
466                 fi
467
468                 die "Active compiler does not have required support for OpenMP"
469         fi
470 }
471
472 # @FUNCTION: tc-has-tls
473 # @USAGE: [-s|-c|-l] [toolchain prefix]
474 # @DESCRIPTION:
475 # See if the toolchain supports thread local storage (TLS).  Use -s to test the
476 # compiler, -c to also test the assembler, and -l to also test the C library
477 # (the default).
478 tc-has-tls() {
479         local base="${T}/test-tc-tls"
480         cat <<-EOF > "${base}.c"
481         int foo(int *i) {
482                 static __thread int j = 0;
483                 return *i ? j : *i;
484         }
485         EOF
486         local flags
487         case $1 in
488                 -s) flags="-S";;
489                 -c) flags="-c";;
490                 -l) ;;
491                 -*) die "Usage: tc-has-tls [-c|-l] [toolchain prefix]";;
492         esac
493         : ${flags:=-fPIC -shared -Wl,-z,defs}
494         [[ $1 == -* ]] && shift
495         $(tc-getCC "$@") ${flags} "${base}.c" -o "${base}" >&/dev/null
496         local ret=$?
497         rm -f "${base}"*
498         return ${ret}
499 }
500
501
502 # Parse information from CBUILD/CHOST/CTARGET rather than
503 # use external variables from the profile.
504 tc-ninja_magic_to_arch() {
505 ninj() { [[ ${type} == "kern" ]] && echo $1 || echo $2 ; }
506
507         local type=$1
508         local host=$2
509         [[ -z ${host} ]] && host=${CTARGET:-${CHOST}}
510
511         case ${host} in
512                 aarch64*)       echo arm64;;
513                 alpha*)         echo alpha;;
514                 arm*)           echo arm;;
515                 avr*)           ninj avr32 avr;;
516                 bfin*)          ninj blackfin bfin;;
517                 c6x*)           echo c6x;;
518                 cris*)          echo cris;;
519                 frv*)           echo frv;;
520                 hexagon*)       echo hexagon;;
521                 hppa*)          ninj parisc hppa;;
522                 i?86*)
523                         # Starting with linux-2.6.24, the 'x86_64' and 'i386'
524                         # trees have been unified into 'x86'.
525                         # FreeBSD still uses i386
526                         if [[ ${type} == "kern" && ${host} == *freebsd* ]] ; then
527                                 echo i386
528                         else
529                                 echo x86
530                         fi
531                         ;;
532                 ia64*)          echo ia64;;
533                 m68*)           echo m68k;;
534                 metag*)         echo metag;;
535                 microblaze*)    echo microblaze;;
536                 mips*)          echo mips;;
537                 nios2*)         echo nios2;;
538                 nios*)          echo nios;;
539                 or1k|or32*)     echo openrisc;;
540                 powerpc*)
541                         # Starting with linux-2.6.15, the 'ppc' and 'ppc64' trees
542                         # have been unified into simply 'powerpc', but until 2.6.16,
543                         # ppc32 is still using ARCH="ppc" as default
544                         if [[ ${type} == "kern" ]] ; then
545                                 echo powerpc
546                         elif [[ ${host} == powerpc64* ]] ; then
547                                 echo ppc64
548                         else
549                                 echo ppc
550                         fi
551                         ;;
552                 riscv*)         echo riscv;;
553                 s390*)          echo s390;;
554                 score*)         echo score;;
555                 sh64*)          ninj sh64 sh;;
556                 sh*)            echo sh;;
557                 sparc64*)       ninj sparc64 sparc;;
558                 sparc*)         [[ ${PROFILE_ARCH} == "sparc64" ]] \
559                                                 && ninj sparc64 sparc \
560                                                 || echo sparc
561                                         ;;
562                 tile*)          echo tile;;
563                 vax*)           echo vax;;
564                 x86_64*freebsd*) echo amd64;;
565                 x86_64*)
566                         # Starting with linux-2.6.24, the 'x86_64' and 'i386'
567                         # trees have been unified into 'x86'.
568                         if [[ ${type} == "kern" ]] ; then
569                                 echo x86
570                         else
571                                 echo amd64
572                         fi
573                         ;;
574                 xtensa*)        echo xtensa;;
575
576                 # since our usage of tc-arch is largely concerned with
577                 # normalizing inputs for testing ${CTARGET}, let's filter
578                 # other cross targets (mingw and such) into the unknown.
579                 *)                      echo unknown;;
580         esac
581 }
582 # @FUNCTION: tc-arch-kernel
583 # @USAGE: [toolchain prefix]
584 # @RETURN: name of the kernel arch according to the compiler target
585 tc-arch-kernel() {
586         tc-ninja_magic_to_arch kern "$@"
587 }
588 # @FUNCTION: tc-arch
589 # @USAGE: [toolchain prefix]
590 # @RETURN: name of the portage arch according to the compiler target
591 tc-arch() {
592         tc-ninja_magic_to_arch portage "$@"
593 }
594
595 tc-endian() {
596         local host=$1
597         [[ -z ${host} ]] && host=${CTARGET:-${CHOST}}
598         host=${host%%-*}
599
600         case ${host} in
601                 aarch64*be)     echo big;;
602                 aarch64)        echo little;;
603                 alpha*)         echo little;;
604                 arm*b*)         echo big;;
605                 arm*)           echo little;;
606                 cris*)          echo little;;
607                 hppa*)          echo big;;
608                 i?86*)          echo little;;
609                 ia64*)          echo little;;
610                 m68*)           echo big;;
611                 mips*l*)        echo little;;
612                 mips*)          echo big;;
613                 powerpc*le)     echo little;;
614                 powerpc*)       echo big;;
615                 s390*)          echo big;;
616                 sh*b*)          echo big;;
617                 sh*)            echo little;;
618                 sparc*)         echo big;;
619                 x86_64*)        echo little;;
620                 *)                      echo wtf;;
621         esac
622 }
623
624 # @FUNCTION: tc-get-compiler-type
625 # @RETURN: keyword identifying the compiler: gcc, clang, pathcc, unknown
626 tc-get-compiler-type() {
627         local code='
628 #if defined(__PATHSCALE__)
629         HAVE_PATHCC
630 #elif defined(__clang__)
631         HAVE_CLANG
632 #elif defined(__GNUC__)
633         HAVE_GCC
634 #endif
635 '
636         local res=$($(tc-getCPP "$@") -E -P - <<<"${code}")
637
638         case ${res} in
639                 *HAVE_PATHCC*)  echo pathcc;;
640                 *HAVE_CLANG*)   echo clang;;
641                 *HAVE_GCC*)             echo gcc;;
642                 *)                              echo unknown;;
643         esac
644 }
645
646 # @FUNCTION: tc-is-gcc
647 # @RETURN: Shell true if the current compiler is GCC, false otherwise.
648 tc-is-gcc() {
649         [[ $(tc-get-compiler-type) == gcc ]]
650 }
651
652 # @FUNCTION: tc-is-clang
653 # @RETURN: Shell true if the current compiler is clang, false otherwise.
654 tc-is-clang() {
655         [[ $(tc-get-compiler-type) == clang ]]
656 }
657
658 # Internal func.  The first argument is the version info to expand.
659 # Query the preprocessor to improve compatibility across different
660 # compilers rather than maintaining a --version flag matrix. #335943
661 _gcc_fullversion() {
662         local ver="$1"; shift
663         set -- $($(tc-getCPP "$@") -E -P - <<<"__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__")
664         eval echo "$ver"
665 }
666
667 # @FUNCTION: gcc-fullversion
668 # @RETURN: compiler version (major.minor.micro: [3.4.6])
669 gcc-fullversion() {
670         _gcc_fullversion '$1.$2.$3' "$@"
671 }
672 # @FUNCTION: gcc-version
673 # @RETURN: compiler version (major.minor: [3.4].6)
674 gcc-version() {
675         _gcc_fullversion '$1.$2' "$@"
676 }
677 # @FUNCTION: gcc-major-version
678 # @RETURN: major compiler version (major: [3].4.6)
679 gcc-major-version() {
680         _gcc_fullversion '$1' "$@"
681 }
682 # @FUNCTION: gcc-minor-version
683 # @RETURN: minor compiler version (minor: 3.[4].6)
684 gcc-minor-version() {
685         _gcc_fullversion '$2' "$@"
686 }
687 # @FUNCTION: gcc-micro-version
688 # @RETURN: micro compiler version (micro: 3.4.[6])
689 gcc-micro-version() {
690         _gcc_fullversion '$3' "$@"
691 }
692
693 # Internal func. Based on _gcc_fullversion() above.
694 _clang_fullversion() {
695         local ver="$1"; shift
696         set -- $($(tc-getCPP "$@") -E -P - <<<"__clang_major__ __clang_minor__ __clang_patchlevel__")
697         eval echo "$ver"
698 }
699
700 # @FUNCTION: clang-fullversion
701 # @RETURN: compiler version (major.minor.micro: [3.4.6])
702 clang-fullversion() {
703         _clang_fullversion '$1.$2.$3' "$@"
704 }
705 # @FUNCTION: clang-version
706 # @RETURN: compiler version (major.minor: [3.4].6)
707 clang-version() {
708         _clang_fullversion '$1.$2' "$@"
709 }
710 # @FUNCTION: clang-major-version
711 # @RETURN: major compiler version (major: [3].4.6)
712 clang-major-version() {
713         _clang_fullversion '$1' "$@"
714 }
715 # @FUNCTION: clang-minor-version
716 # @RETURN: minor compiler version (minor: 3.[4].6)
717 clang-minor-version() {
718         _clang_fullversion '$2' "$@"
719 }
720 # @FUNCTION: clang-micro-version
721 # @RETURN: micro compiler version (micro: 3.4.[6])
722 clang-micro-version() {
723         _clang_fullversion '$3' "$@"
724 }
725
726 # Returns the installation directory - internal toolchain
727 # function for use by _gcc-specs-exists (for flag-o-matic).
728 _gcc-install-dir() {
729         echo "$(LC_ALL=C $(tc-getCC) -print-search-dirs 2> /dev/null |\
730                 awk '$1=="install:" {print $2}')"
731 }
732 # Returns true if the indicated specs file exists - internal toolchain
733 # function for use by flag-o-matic.
734 _gcc-specs-exists() {
735         [[ -f $(_gcc-install-dir)/$1 ]]
736 }
737
738 # Returns requested gcc specs directive unprocessed - for used by
739 # gcc-specs-directive()
740 # Note; later specs normally overwrite earlier ones; however if a later
741 # spec starts with '+' then it appends.
742 # gcc -dumpspecs is parsed first, followed by files listed by "gcc -v"
743 # as "Reading <file>", in order.  Strictly speaking, if there's a
744 # $(gcc_install_dir)/specs, the built-in specs aren't read, however by
745 # the same token anything from 'gcc -dumpspecs' is overridden by
746 # the contents of $(gcc_install_dir)/specs so the result is the
747 # same either way.
748 _gcc-specs-directive_raw() {
749         local cc=$(tc-getCC)
750         local specfiles=$(LC_ALL=C ${cc} -v 2>&1 | awk '$1=="Reading" {print $NF}')
751         ${cc} -dumpspecs 2> /dev/null | cat - ${specfiles} | awk -v directive=$1 \
752 'BEGIN  { pspec=""; spec=""; outside=1 }
753 $1=="*"directive":"  { pspec=spec; spec=""; outside=0; next }
754         outside || NF==0 || ( substr($1,1,1)=="*" && substr($1,length($1),1)==":" ) { outside=1; next }
755         spec=="" && substr($0,1,1)=="+" { spec=pspec " " substr($0,2); next }
756         { spec=spec $0 }
757 END     { print spec }'
758         return 0
759 }
760
761 # Return the requested gcc specs directive, with all included
762 # specs expanded.
763 # Note, it does not check for inclusion loops, which cause it
764 # to never finish - but such loops are invalid for gcc and we're
765 # assuming gcc is operational.
766 gcc-specs-directive() {
767         local directive subdname subdirective
768         directive="$(_gcc-specs-directive_raw $1)"
769         while [[ ${directive} == *%\(*\)* ]]; do
770                 subdname=${directive/*%\(}
771                 subdname=${subdname/\)*}
772                 subdirective="$(_gcc-specs-directive_raw ${subdname})"
773                 directive="${directive//\%(${subdname})/${subdirective}}"
774         done
775         echo "${directive}"
776         return 0
777 }
778
779 # Returns true if gcc sets relro
780 gcc-specs-relro() {
781         local directive
782         directive=$(gcc-specs-directive link_command)
783         [[ "${directive/\{!norelro:}" != "${directive}" ]]
784 }
785 # Returns true if gcc sets now
786 gcc-specs-now() {
787         local directive
788         directive=$(gcc-specs-directive link_command)
789         [[ "${directive/\{!nonow:}" != "${directive}" ]]
790 }
791 # Returns true if gcc builds PIEs
792 gcc-specs-pie() {
793         local directive
794         directive=$(gcc-specs-directive cc1)
795         [[ "${directive/\{!nopie:}" != "${directive}" ]]
796 }
797 # Returns true if gcc builds with the stack protector
798 gcc-specs-ssp() {
799         local directive
800         directive=$(gcc-specs-directive cc1)
801         [[ "${directive/\{!fno-stack-protector:}" != "${directive}" ]]
802 }
803 # Returns true if gcc upgrades fstack-protector to fstack-protector-all
804 gcc-specs-ssp-to-all() {
805         local directive
806         directive=$(gcc-specs-directive cc1)
807         [[ "${directive/\{!fno-stack-protector-all:}" != "${directive}" ]]
808 }
809 # Returns true if gcc builds with fno-strict-overflow
810 gcc-specs-nostrict() {
811         local directive
812         directive=$(gcc-specs-directive cc1)
813         [[ "${directive/\{!fstrict-overflow:}" != "${directive}" ]]
814 }
815 # Returns true if gcc builds with fstack-check
816 gcc-specs-stack-check() {
817         local directive
818         directive=$(gcc-specs-directive cc1)
819         [[ "${directive/\{!fno-stack-check:}" != "${directive}" ]]
820 }
821
822
823 # @FUNCTION: tc-enables-pie
824 # @RETURN: Truth if the current compiler generates position-independent code (PIC) which can be linked into executables
825 # @DESCRIPTION:
826 # Return truth if the current compiler generates position-independent code (PIC)
827 # which can be linked into executables.
828 tc-enables-pie() {
829         local ret="$($(tc-getCC) ${CPPFLAGS} ${CFLAGS} -E -P - <<-EOF 2> /dev/null | grep '^true$'
830                 #if defined(__PIE__)
831                 true
832                 #endif
833                 EOF
834         )"
835         [[ ${ret} == true ]]
836 }
837
838 # @FUNCTION: tc-enables-ssp
839 # @RETURN: Truth if the current compiler enables stack smashing protection (SSP) on at least minimal level
840 # @DESCRIPTION:
841 # Return truth if the current compiler enables stack smashing protection (SSP)
842 # on level corresponding to any of the following options:
843 #  -fstack-protector
844 #  -fstack-protector-strong
845 #  -fstack-protector-all
846 tc-enables-ssp() {
847         local ret="$($(tc-getCC) ${CPPFLAGS} ${CFLAGS} -E -P - <<-EOF 2> /dev/null | grep '^true$'
848                 #if defined(__SSP__) || defined(__SSP_STRONG__) || defined(__SSP_ALL__)
849                 true
850                 #endif
851                 EOF
852         )"
853         [[ ${ret} == true ]]
854 }
855
856 # @FUNCTION: tc-enables-ssp-strong
857 # @RETURN: Truth if the current compiler enables stack smashing protection (SSP) on at least middle level
858 # @DESCRIPTION:
859 # Return truth if the current compiler enables stack smashing protection (SSP)
860 # on level corresponding to any of the following options:
861 #  -fstack-protector-strong
862 #  -fstack-protector-all
863 tc-enables-ssp-strong() {
864         local ret="$($(tc-getCC) ${CPPFLAGS} ${CFLAGS} -E -P - <<-EOF 2> /dev/null | grep '^true$'
865                 #if defined(__SSP_STRONG__) || defined(__SSP_ALL__)
866                 true
867                 #endif
868                 EOF
869         )"
870         [[ ${ret} == true ]]
871 }
872
873 # @FUNCTION: tc-enables-ssp-all
874 # @RETURN: Truth if the current compiler enables stack smashing protection (SSP) on maximal level
875 # @DESCRIPTION:
876 # Return truth if the current compiler enables stack smashing protection (SSP)
877 # on level corresponding to any of the following options:
878 #  -fstack-protector-all
879 tc-enables-ssp-all() {
880         local ret="$($(tc-getCC) ${CPPFLAGS} ${CFLAGS} -E -P - <<-EOF 2> /dev/null | grep '^true$'
881                 #if defined(__SSP_ALL__)
882                 true
883                 #endif
884                 EOF
885         )"
886         [[ ${ret} == true ]]
887 }
888
889
890 # @FUNCTION: gen_usr_ldscript
891 # @USAGE: [-a] <list of libs to create linker scripts for>
892 # @DESCRIPTION:
893 # This function generate linker scripts in /usr/lib for dynamic
894 # libs in /lib.  This is to fix linking problems when you have
895 # the .so in /lib, and the .a in /usr/lib.  What happens is that
896 # in some cases when linking dynamic, the .a in /usr/lib is used
897 # instead of the .so in /lib due to gcc/libtool tweaking ld's
898 # library search path.  This causes many builds to fail.
899 # See bug #4411 for more info.
900 #
901 # Note that you should in general use the unversioned name of
902 # the library (libfoo.so), as ldconfig should usually update it
903 # correctly to point to the latest version of the library present.
904 gen_usr_ldscript() {
905         local lib libdir=$(get_libdir) output_format="" auto=false suffix=$(get_libname)
906         [[ -z ${ED+set} ]] && local ED=${D%/}${EPREFIX}/
907
908         tc-is-static-only && return
909
910         # We only care about stuffing / for the native ABI. #479448
911         if [[ $(type -t multilib_is_native_abi) == "function" ]] ; then
912                 multilib_is_native_abi || return 0
913         fi
914
915         # Eventually we'd like to get rid of this func completely #417451
916         case ${CTARGET:-${CHOST}} in
917         *-darwin*) ;;
918         *-android*) return 0 ;;
919         *linux*|*-freebsd*|*-openbsd*|*-netbsd*)
920                 use prefix && return 0 ;;
921         *) return 0 ;;
922         esac
923
924         # Just make sure it exists
925         dodir /usr/${libdir}
926
927         if [[ $1 == "-a" ]] ; then
928                 auto=true
929                 shift
930                 dodir /${libdir}
931         fi
932
933         # OUTPUT_FORMAT gives hints to the linker as to what binary format
934         # is referenced ... makes multilib saner
935         local flags=( ${CFLAGS} ${LDFLAGS} -Wl,--verbose )
936         if $(tc-getLD) --version | grep -q 'GNU gold' ; then
937                 # If they're using gold, manually invoke the old bfd. #487696
938                 local d="${T}/bfd-linker"
939                 mkdir -p "${d}"
940                 ln -sf $(which ${CHOST}-ld.bfd) "${d}"/ld
941                 flags+=( -B"${d}" )
942         fi
943         output_format=$($(tc-getCC) "${flags[@]}" 2>&1 | sed -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/\1/p')
944         [[ -n ${output_format} ]] && output_format="OUTPUT_FORMAT ( ${output_format} )"
945
946         for lib in "$@" ; do
947                 local tlib
948                 if ${auto} ; then
949                         lib="lib${lib}${suffix}"
950                 else
951                         # Ensure /lib/${lib} exists to avoid dangling scripts/symlinks.
952                         # This especially is for AIX where $(get_libname) can return ".a",
953                         # so /lib/${lib} might be moved to /usr/lib/${lib} (by accident).
954                         [[ -r ${ED}/${libdir}/${lib} ]] || continue
955                         #TODO: better die here?
956                 fi
957
958                 case ${CTARGET:-${CHOST}} in
959                 *-darwin*)
960                         if ${auto} ; then
961                                 tlib=$(scanmacho -qF'%S#F' "${ED}"/usr/${libdir}/${lib})
962                         else
963                                 tlib=$(scanmacho -qF'%S#F' "${ED}"/${libdir}/${lib})
964                         fi
965                         [[ -z ${tlib} ]] && die "unable to read install_name from ${lib}"
966                         tlib=${tlib##*/}
967
968                         if ${auto} ; then
969                                 mv "${ED}"/usr/${libdir}/${lib%${suffix}}.*${suffix#.} "${ED}"/${libdir}/ || die
970                                 # some install_names are funky: they encode a version
971                                 if [[ ${tlib} != ${lib%${suffix}}.*${suffix#.} ]] ; then
972                                         mv "${ED}"/usr/${libdir}/${tlib%${suffix}}.*${suffix#.} "${ED}"/${libdir}/ || die
973                                 fi
974                                 rm -f "${ED}"/${libdir}/${lib}
975                         fi
976
977                         # Mach-O files have an id, which is like a soname, it tells how
978                         # another object linking against this lib should reference it.
979                         # Since we moved the lib from usr/lib into lib this reference is
980                         # wrong.  Hence, we update it here.  We don't configure with
981                         # libdir=/lib because that messes up libtool files.
982                         # Make sure we don't lose the specific version, so just modify the
983                         # existing install_name
984                         if [[ ! -w "${ED}/${libdir}/${tlib}" ]] ; then
985                                 chmod u+w "${ED}${libdir}/${tlib}" # needed to write to it
986                                 local nowrite=yes
987                         fi
988                         install_name_tool \
989                                 -id "${EPREFIX}"/${libdir}/${tlib} \
990                                 "${ED}"/${libdir}/${tlib} || die "install_name_tool failed"
991                         [[ -n ${nowrite} ]] && chmod u-w "${ED}${libdir}/${tlib}"
992                         # Now as we don't use GNU binutils and our linker doesn't
993                         # understand linker scripts, just create a symlink.
994                         pushd "${ED}/usr/${libdir}" > /dev/null
995                         ln -snf "../../${libdir}/${tlib}" "${lib}"
996                         popd > /dev/null
997                         ;;
998                 *)
999                         if ${auto} ; then
1000                                 tlib=$(scanelf -qF'%S#F' "${ED}"/usr/${libdir}/${lib})
1001                                 [[ -z ${tlib} ]] && die "unable to read SONAME from ${lib}"
1002                                 mv "${ED}"/usr/${libdir}/${lib}* "${ED}"/${libdir}/ || die
1003                                 # some SONAMEs are funky: they encode a version before the .so
1004                                 if [[ ${tlib} != ${lib}* ]] ; then
1005                                         mv "${ED}"/usr/${libdir}/${tlib}* "${ED}"/${libdir}/ || die
1006                                 fi
1007                                 rm -f "${ED}"/${libdir}/${lib}
1008                         else
1009                                 tlib=${lib}
1010                         fi
1011                         cat > "${ED}/usr/${libdir}/${lib}" <<-END_LDSCRIPT
1012                         /* GNU ld script
1013                            Since Gentoo has critical dynamic libraries in /lib, and the static versions
1014                            in /usr/lib, we need to have a "fake" dynamic lib in /usr/lib, otherwise we
1015                            run into linking problems.  This "fake" dynamic lib is a linker script that
1016                            redirects the linker to the real lib.  And yes, this works in the cross-
1017                            compiling scenario as the sysroot-ed linker will prepend the real path.
1018
1019                            See bug https://bugs.gentoo.org/4411 for more info.
1020                          */
1021                         ${output_format}
1022                         GROUP ( ${EPREFIX}/${libdir}/${tlib} )
1023                         END_LDSCRIPT
1024                         ;;
1025                 esac
1026                 fperms a+x "/usr/${libdir}/${lib}" || die "could not change perms on ${lib}"
1027         done
1028 }
1029
1030 fi