dev-python/objgraph: keyworded 3.4.1 for ia64, bug #717946
[gentoo.git] / eclass / flag-o-matic.eclass
1 # Copyright 1999-2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: flag-o-matic.eclass
5 # @MAINTAINER:
6 # toolchain@gentoo.org
7 # @BLURB: common functions to manipulate and query toolchain flags
8 # @DESCRIPTION:
9 # This eclass contains a suite of functions to help developers sanely
10 # and safely manage toolchain flags in their builds.
11
12 if [[ -z ${_FLAG_O_MATIC_ECLASS} ]]; then
13 _FLAG_O_MATIC_ECLASS=1
14
15 inherit eutils toolchain-funcs multilib
16
17 # Return all the flag variables that our high level funcs operate on.
18 all-flag-vars() {
19         echo {ADA,C,CPP,CXX,CCAS,F,FC,LD}FLAGS
20 }
21
22 # {C,CPP,CXX,CCAS,F,FC,LD}FLAGS that we allow in strip-flags
23 # Note: shell globs and character lists are allowed
24 setup-allowed-flags() {
25         ALLOWED_FLAGS=(
26                 -pipe -O '-O[12sg]' -mcpu -march -mtune
27                 '-fstack-protector*' '-fsanitize*' '-fstack-check*' -fno-stack-check
28                 -fbounds-check -fbounds-checking -fno-strict-overflow
29                 -fno-PIE -fno-pie -nopie -no-pie -fno-unit-at-a-time
30                 -g '-g[0-9]' -ggdb '-ggdb[0-9]' '-gdwarf-*' gstabs -gstabs+ -gz
31                 -fno-ident -fpermissive -frecord-gcc-switches
32                 '-fdiagnostics*' '-fplugin*'
33                 '-W*' -w
34
35                 # CPPFLAGS and LDFLAGS
36                 '-[DUILR]*' '-Wl,*'
37
38                 # Linker choice flag
39                 '-fuse-ld'
40         )
41
42         # allow a bunch of flags that negate features / control ABI
43         ALLOWED_FLAGS+=(
44                 '-fno-stack-protector*' '-fabi-version=*'
45                 -fno-strict-aliasing -fno-bounds-check -fno-bounds-checking -fstrict-overflow
46                 -fno-omit-frame-pointer '-fno-builtin*'
47         )
48         ALLOWED_FLAGS+=(
49                 -mregparm -mno-app-regs -mapp-regs -mno-mmx -mno-sse
50                 -mno-sse2 -mno-sse3 -mno-ssse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2
51                 -mno-avx -mno-aes -mno-pclmul -mno-sse4a -mno-3dnow -mno-popcnt
52                 -mno-abm -mips1 -mips2 -mips3 -mips4 -mips32 -mips64 -mips16 -mplt
53                 -msoft-float -mno-soft-float -mhard-float -mno-hard-float -mfpu
54                 -mieee -mieee-with-inexact -mschedule -mfloat-gprs -mspe -mno-spe
55                 -mtls-direct-seg-refs -mno-tls-direct-seg-refs -mflat -mno-flat
56                 -mno-faster-structs -mfaster-structs -m32 -m64 -mx32 -mabi
57                 -mlittle-endian -mbig-endian -EL -EB -fPIC -mlive-g0 -mcmodel
58                 -mstack-bias -mno-stack-bias -msecure-plt '-m*-toc' -mfloat-abi
59                 -mfix-r4000 -mno-fix-r4000 -mfix-r4400 -mno-fix-r4400
60                 -mfix-rm7000 -mno-fix-rm7000 -mfix-r10000 -mno-fix-r10000
61                 -mr10k-cache-barrier -mthumb -marm
62
63                 # gcc 4.5
64                 -mno-fma4 -mno-movbe -mno-xop -mno-lwp
65                 # gcc 4.6
66                 -mno-fsgsbase -mno-rdrnd -mno-f16c -mno-bmi -mno-tbm
67                 # gcc 4.7
68                 -mno-avx2 -mno-bmi2 -mno-fma -mno-lzcnt
69                 # gcc 4.8
70                 -mno-fxsr -mno-hle -mno-rtm -mno-xsave -mno-xsaveopt
71                 # gcc 4.9
72                 -mno-avx512cd -mno-avx512er -mno-avx512f -mno-avx512pf -mno-sha
73         )
74
75         # Allow some safe individual flags. Should come along with the bug reference.
76         ALLOWED_FLAGS+=(
77                 # Allow explicit stack realignment to run non-conformant
78                 # binaries: bug #677852
79                 -mstackrealign
80         )
81 }
82
83 # inverted filters for hardened compiler.  This is trying to unpick
84 # the hardened compiler defaults.
85 _filter-hardened() {
86         local f
87         for f in "$@" ; do
88                 case "${f}" in
89                         # Ideally we should only concern ourselves with PIE flags,
90                         # not -fPIC or -fpic, but too many places filter -fPIC without
91                         # thinking about -fPIE.
92                         -fPIC|-fpic|-fPIE|-fpie|-Wl,pie|-pie)
93                                 gcc-specs-pie || continue
94                                 if ! is-flagq -nopie && ! is-flagq -no-pie ; then
95                                         # Support older Gentoo form first (-nopie) before falling
96                                         # back to the official gcc-6+ form (-no-pie).
97                                         if test-flags -nopie >/dev/null ; then
98                                                 append-flags -nopie
99                                         else
100                                                 append-flags -no-pie
101                                         fi
102                                 fi
103                                 ;;
104                         -fstack-protector)
105                                 gcc-specs-ssp || continue
106                                 is-flagq -fno-stack-protector || append-flags $(test-flags -fno-stack-protector);;
107                         -fstack-protector-all)
108                                 gcc-specs-ssp-to-all || continue
109                                 is-flagq -fno-stack-protector-all || append-flags $(test-flags -fno-stack-protector-all);;
110                         -fno-strict-overflow)
111                                 gcc-specs-nostrict || continue
112                                 is-flagq -fstrict-overflow || append-flags $(test-flags -fstrict-overflow);;
113                 esac
114         done
115 }
116
117 # Remove occurrences of strings from variable given in $1
118 # Strings removed are matched as globs, so for example
119 # '-O*' would remove -O1, -O2 etc.
120 _filter-var() {
121         local f x var=$1 new=()
122         shift
123
124         for f in ${!var} ; do
125                 for x in "$@" ; do
126                         # Note this should work with globs like -O*
127                         [[ ${f} == ${x} ]] && continue 2
128                 done
129                 new+=( "${f}" )
130         done
131         export ${var}="${new[*]}"
132 }
133
134 # @FUNCTION: filter-flags
135 # @USAGE: <flags>
136 # @DESCRIPTION:
137 # Remove particular <flags> from {C,CPP,CXX,CCAS,F,FC,LD}FLAGS.  Accepts shell globs.
138 filter-flags() {
139         _filter-hardened "$@"
140         local v
141         for v in $(all-flag-vars) ; do
142                 _filter-var ${v} "$@"
143         done
144         return 0
145 }
146
147 # @FUNCTION: filter-lfs-flags
148 # @DESCRIPTION:
149 # Remove flags that enable Large File Support.
150 filter-lfs-flags() {
151         [[ $# -ne 0 ]] && die "filter-lfs-flags takes no arguments"
152         # http://www.gnu.org/s/libc/manual/html_node/Feature-Test-Macros.html
153         # _LARGEFILE_SOURCE: enable support for new LFS funcs (ftello/etc...)
154         # _LARGEFILE64_SOURCE: enable support for 64bit variants (off64_t/fseeko64/etc...)
155         # _FILE_OFFSET_BITS: default to 64bit variants (off_t is defined as off64_t)
156         filter-flags -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
157 }
158
159 # @FUNCTION: filter-ldflags
160 # @USAGE: <flags>
161 # @DESCRIPTION:
162 # Remove particular <flags> from LDFLAGS.  Accepts shell globs.
163 filter-ldflags() {
164         _filter-var LDFLAGS "$@"
165         return 0
166 }
167
168 # @FUNCTION: append-cppflags
169 # @USAGE: <flags>
170 # @DESCRIPTION:
171 # Add extra <flags> to the current CPPFLAGS.
172 append-cppflags() {
173         [[ $# -eq 0 ]] && return 0
174         export CPPFLAGS+=" $*"
175         return 0
176 }
177
178 # @FUNCTION: append-cflags
179 # @USAGE: <flags>
180 # @DESCRIPTION:
181 # Add extra <flags> to the current CFLAGS.  If a flag might not be supported
182 # with different compilers (or versions), then use test-flags-CC like so:
183 # @CODE
184 # append-cflags $(test-flags-CC -funky-flag)
185 # @CODE
186 append-cflags() {
187         [[ $# -eq 0 ]] && return 0
188         # Do not do automatic flag testing ourselves. #417047
189         export CFLAGS+=" $*"
190         return 0
191 }
192
193 # @FUNCTION: append-cxxflags
194 # @USAGE: <flags>
195 # @DESCRIPTION:
196 # Add extra <flags> to the current CXXFLAGS.  If a flag might not be supported
197 # with different compilers (or versions), then use test-flags-CXX like so:
198 # @CODE
199 # append-cxxflags $(test-flags-CXX -funky-flag)
200 # @CODE
201 append-cxxflags() {
202         [[ $# -eq 0 ]] && return 0
203         # Do not do automatic flag testing ourselves. #417047
204         export CXXFLAGS+=" $*"
205         return 0
206 }
207
208 # @FUNCTION: append-fflags
209 # @USAGE: <flags>
210 # @DESCRIPTION:
211 # Add extra <flags> to the current {F,FC}FLAGS.  If a flag might not be supported
212 # with different compilers (or versions), then use test-flags-F77 like so:
213 # @CODE
214 # append-fflags $(test-flags-F77 -funky-flag)
215 # @CODE
216 append-fflags() {
217         [[ $# -eq 0 ]] && return 0
218         # Do not do automatic flag testing ourselves. #417047
219         export FFLAGS+=" $*"
220         export FCFLAGS+=" $*"
221         return 0
222 }
223
224 # @FUNCTION: append-lfs-flags
225 # @DESCRIPTION:
226 # Add flags that enable Large File Support.
227 append-lfs-flags() {
228         [[ $# -ne 0 ]] && die "append-lfs-flags takes no arguments"
229         # see comments in filter-lfs-flags func for meaning of these
230         append-cppflags -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
231 }
232
233 # @FUNCTION: append-ldflags
234 # @USAGE: <flags>
235 # @DESCRIPTION:
236 # Add extra <flags> to the current LDFLAGS.
237 append-ldflags() {
238         [[ $# -eq 0 ]] && return 0
239         local flag
240         for flag in "$@"; do
241                 [[ ${flag} == -l* ]] && \
242                         eqawarn "Appending a library link instruction (${flag}); libraries to link to should not be passed through LDFLAGS"
243         done
244
245         export LDFLAGS="${LDFLAGS} $*"
246         return 0
247 }
248
249 # @FUNCTION: append-flags
250 # @USAGE: <flags>
251 # @DESCRIPTION:
252 # Add extra <flags> to your current {C,CXX,F,FC}FLAGS.
253 append-flags() {
254         [[ $# -eq 0 ]] && return 0
255         case " $* " in
256         *' '-[DIU]*) eqawarn 'please use append-cppflags for preprocessor flags' ;;
257         *' '-L*|\
258         *' '-Wl,*)  eqawarn 'please use append-ldflags for linker flags' ;;
259         esac
260         append-cflags "$@"
261         append-cxxflags "$@"
262         append-fflags "$@"
263         return 0
264 }
265
266 # @FUNCTION: replace-flags
267 # @USAGE: <old> <new>
268 # @DESCRIPTION:
269 # Replace the <old> flag with <new>.  Accepts shell globs for <old>.
270 replace-flags() {
271         [[ $# != 2 ]] && die "Usage: replace-flags <old flag> <new flag>"
272
273         local f var new
274         for var in $(all-flag-vars) ; do
275                 # Looping over the flags instead of using a global
276                 # substitution ensures that we're working with flag atoms.
277                 # Otherwise globs like -O* have the potential to wipe out the
278                 # list of flags.
279                 new=()
280                 for f in ${!var} ; do
281                         # Note this should work with globs like -O*
282                         [[ ${f} == ${1} ]] && f=${2}
283                         new+=( "${f}" )
284                 done
285                 export ${var}="${new[*]}"
286         done
287
288         return 0
289 }
290
291 # @FUNCTION: replace-cpu-flags
292 # @USAGE: <old> <new>
293 # @DESCRIPTION:
294 # Replace cpu flags (like -march/-mcpu/-mtune) that select the <old> cpu
295 # with flags that select the <new> cpu.  Accepts shell globs for <old>.
296 replace-cpu-flags() {
297         local newcpu="$#" ; newcpu="${!newcpu}"
298         while [ $# -gt 1 ] ; do
299                 # quote to make sure that no globbing is done (particularly on
300                 # ${oldcpu}) prior to calling replace-flags
301                 replace-flags "-march=${1}" "-march=${newcpu}"
302                 replace-flags "-mcpu=${1}" "-mcpu=${newcpu}"
303                 replace-flags "-mtune=${1}" "-mtune=${newcpu}"
304                 shift
305         done
306         return 0
307 }
308
309 _is_flagq() {
310         local x var="$1[*]"
311         for x in ${!var} ; do
312                 [[ ${x} == $2 ]] && return 0
313         done
314         return 1
315 }
316
317 # @FUNCTION: is-flagq
318 # @USAGE: <flag>
319 # @DESCRIPTION:
320 # Returns shell true if <flag> is in {C,CXX,F,FC}FLAGS, else returns shell false.  Accepts shell globs.
321 is-flagq() {
322         [[ -n $2 ]] && die "Usage: is-flag <flag>"
323
324         local var
325         for var in $(all-flag-vars) ; do
326                 _is_flagq ${var} "$1" && return 0
327         done
328         return 1
329 }
330
331 # @FUNCTION: is-flag
332 # @USAGE: <flag>
333 # @DESCRIPTION:
334 # Echo's "true" if flag is set in {C,CXX,F,FC}FLAGS.  Accepts shell globs.
335 is-flag() {
336         is-flagq "$@" && echo true
337 }
338
339 # @FUNCTION: is-ldflagq
340 # @USAGE: <flag>
341 # @DESCRIPTION:
342 # Returns shell true if <flag> is in LDFLAGS, else returns shell false.  Accepts shell globs.
343 is-ldflagq() {
344         [[ -n $2 ]] && die "Usage: is-ldflag <flag>"
345         _is_flagq LDFLAGS $1
346 }
347
348 # @FUNCTION: is-ldflag
349 # @USAGE: <flag>
350 # @DESCRIPTION:
351 # Echo's "true" if flag is set in LDFLAGS.  Accepts shell globs.
352 is-ldflag() {
353         is-ldflagq "$@" && echo true
354 }
355
356 # @FUNCTION: filter-mfpmath
357 # @USAGE: <math types>
358 # @DESCRIPTION:
359 # Remove specified math types from the fpmath flag.  For example, if the user
360 # has -mfpmath=sse,386, running `filter-mfpmath sse` will leave the user with
361 # -mfpmath=386.
362 filter-mfpmath() {
363         local orig_mfpmath new_math prune_math
364
365         # save the original -mfpmath flag
366         orig_mfpmath=$(get-flag -mfpmath)
367         # get the value of the current -mfpmath flag
368         new_math=$(get-flag mfpmath)
369         # convert "both" to something we can filter
370         new_math=${new_math/both/387,sse}
371         new_math=" ${new_math//[,+]/ } "
372         # figure out which math values are to be removed
373         prune_math=""
374         for prune_math in "$@" ; do
375                 new_math=${new_math/ ${prune_math} / }
376         done
377         new_math=$(echo ${new_math})
378         new_math=${new_math// /,}
379
380         if [[ -z ${new_math} ]] ; then
381                 # if we're removing all user specified math values are
382                 # slated for removal, then we just filter the flag
383                 filter-flags ${orig_mfpmath}
384         else
385                 # if we only want to filter some of the user specified
386                 # math values, then we replace the current flag
387                 replace-flags ${orig_mfpmath} -mfpmath=${new_math}
388         fi
389         return 0
390 }
391
392 # @FUNCTION: strip-flags
393 # @DESCRIPTION:
394 # Strip *FLAGS of everything except known good/safe flags.  This runs over all
395 # flags returned by all_flag_vars().
396 strip-flags() {
397         [[ $# -ne 0 ]] && die "strip-flags takes no arguments"
398         local x y var
399
400         local ALLOWED_FLAGS
401         setup-allowed-flags
402
403         set -f  # disable pathname expansion
404
405         for var in $(all-flag-vars) ; do
406                 local new=()
407
408                 for x in ${!var} ; do
409                         local flag=${x%%=*}
410                         for y in "${ALLOWED_FLAGS[@]}" ; do
411                                 if [[ -z ${flag%%${y}} ]] ; then
412                                         new+=( "${x}" )
413                                         break
414                                 fi
415                         done
416                 done
417
418                 # In case we filtered out all optimization flags fallback to -O2
419                 if _is_flagq ${var} "-O*" && ! _is_flagq new "-O*" ; then
420                         new+=( -O2 )
421                 fi
422
423                 if [[ ${!var} != "${new[*]}" ]] ; then
424                         einfo "strip-flags: ${var}: changed '${!var}' to '${new[*]}'"
425                 fi
426                 export ${var}="${new[*]}"
427         done
428
429         set +f  # re-enable pathname expansion
430
431         return 0
432 }
433
434 test-flag-PROG() {
435         local comp=$1
436         local lang=$2
437         shift 2
438
439         if [[ -z ${comp} ]]; then
440                 return 1
441         fi
442         if [[ -z $1 ]]; then
443                 return 1
444         fi
445
446         # verify selected compiler exists before using it
447         comp=($(tc-get${comp}))
448         # 'comp' can already contain compiler options.
449         # 'type' needs a binary name
450         if ! type -p ${comp[0]} >/dev/null; then
451                 return 1
452         fi
453
454         # Set up test file.
455         local in_src in_ext cmdline_extra=()
456         case "${lang}" in
457                 # compiler/assembler only
458                 c)
459                         in_ext='c'
460                         in_src='int main(void) { return 0; }'
461                         cmdline_extra+=(-xc -c)
462                         ;;
463                 c++)
464                         in_ext='cc'
465                         in_src='int main(void) { return 0; }'
466                         cmdline_extra+=(-xc++ -c)
467                         ;;
468                 f77)
469                         in_ext='f'
470                         # fixed source form
471                         in_src='      end'
472                         cmdline_extra+=(-xf77 -c)
473                         ;;
474                 f95)
475                         in_ext='f90'
476                         in_src='end'
477                         cmdline_extra+=(-xf95 -c)
478                         ;;
479
480                 # C compiler/assembler/linker
481                 c+ld)
482                         in_ext='c'
483                         in_src='int main(void) { return 0; }'
484                         cmdline_extra+=(-xc)
485                         ;;
486         esac
487         local test_in=${T}/test-flag.${in_ext}
488         local test_out=${T}/test-flag.exe
489
490         printf "%s\n" "${in_src}" > "${test_in}" || die "Failed to create '${test_in}'"
491
492         # Currently we rely on warning-free output of a compiler
493         # before the flag to see if a flag prduces any warnings.
494         # This has a few drawbacks:
495         # - if compiler already generates warnings we filter out
496         #   every single flag: bug #712488
497         # - if user actually wants to see warnings we just strip
498         #   them regardless of warnings type.
499         #
500         # We can add more selective detection of no-op flags via
501         # '-Werror=ignored-optimization-argument' and similar error options
502         # similar to what we are doing with '-Qunused-arguments'.
503         local cmdline=(
504                 "${comp[@]}"
505                 # Clang will warn about unknown gcc flags but exit 0.
506                 # Need -Werror to force it to exit non-zero.
507                 -Werror
508                 "$@"
509                 # -x<lang> options need to go before first source file
510                 "${cmdline_extra[@]}"
511
512                 "${test_in}" -o "${test_out}"
513         )
514
515         if ! "${cmdline[@]}" &>/dev/null; then
516                 # -Werror makes clang bail out on unused arguments as well;
517                 # try to add -Qunused-arguments to work-around that
518                 # other compilers don't support it but then, it's failure like
519                 # any other
520                 cmdline+=( -Qunused-arguments )
521                 "${cmdline[@]}" &>/dev/null
522         fi
523 }
524
525 # @FUNCTION: test-flag-CC
526 # @USAGE: <flag>
527 # @DESCRIPTION:
528 # Returns shell true if <flag> is supported by the C compiler, else returns shell false.
529 test-flag-CC() { test-flag-PROG "CC" c "$@"; }
530
531 # @FUNCTION: test-flag-CXX
532 # @USAGE: <flag>
533 # @DESCRIPTION:
534 # Returns shell true if <flag> is supported by the C++ compiler, else returns shell false.
535 test-flag-CXX() { test-flag-PROG "CXX" c++ "$@"; }
536
537 # @FUNCTION: test-flag-F77
538 # @USAGE: <flag>
539 # @DESCRIPTION:
540 # Returns shell true if <flag> is supported by the Fortran 77 compiler, else returns shell false.
541 test-flag-F77() { test-flag-PROG "F77" f77 "$@"; }
542
543 # @FUNCTION: test-flag-FC
544 # @USAGE: <flag>
545 # @DESCRIPTION:
546 # Returns shell true if <flag> is supported by the Fortran 90 compiler, else returns shell false.
547 test-flag-FC() { test-flag-PROG "FC" f95 "$@"; }
548
549 # @FUNCTION: test-flag-CCLD
550 # @USAGE: <flag>
551 # @DESCRIPTION:
552 # Returns shell true if <flag> is supported by the C compiler and linker, else returns shell false.
553 test-flag-CCLD() { test-flag-PROG "CC" c+ld "$@"; }
554
555 test-flags-PROG() {
556         local comp=$1
557         local flags=()
558         local x
559
560         shift
561
562         [[ -z ${comp} ]] && return 1
563
564         while (( $# )); do
565                 case "$1" in
566                         # '-B /foo': bug # 687198
567                         --param|-B)
568                                 if test-flag-${comp} "$1" "$2"; then
569                                         flags+=( "$1" "$2" )
570                                 fi
571                                 shift 2
572                                 ;;
573                         *)
574                                 if test-flag-${comp} "$1"; then
575                                         flags+=( "$1" )
576                                 fi
577                                 shift 1
578                                 ;;
579                 esac
580         done
581
582         echo "${flags[*]}"
583
584         # Just bail if we dont have any flags
585         [[ ${#flags[@]} -gt 0 ]]
586 }
587
588 # @FUNCTION: test-flags-CC
589 # @USAGE: <flags>
590 # @DESCRIPTION:
591 # Returns shell true if <flags> are supported by the C compiler, else returns shell false.
592 test-flags-CC() { test-flags-PROG "CC" "$@"; }
593
594 # @FUNCTION: test-flags-CXX
595 # @USAGE: <flags>
596 # @DESCRIPTION:
597 # Returns shell true if <flags> are supported by the C++ compiler, else returns shell false.
598 test-flags-CXX() { test-flags-PROG "CXX" "$@"; }
599
600 # @FUNCTION: test-flags-F77
601 # @USAGE: <flags>
602 # @DESCRIPTION:
603 # Returns shell true if <flags> are supported by the Fortran 77 compiler, else returns shell false.
604 test-flags-F77() { test-flags-PROG "F77" "$@"; }
605
606 # @FUNCTION: test-flags-FC
607 # @USAGE: <flags>
608 # @DESCRIPTION:
609 # Returns shell true if <flags> are supported by the Fortran 90 compiler, else returns shell false.
610 test-flags-FC() { test-flags-PROG "FC" "$@"; }
611
612 # @FUNCTION: test-flags-CCLD
613 # @USAGE: <flags>
614 # @DESCRIPTION:
615 # Returns shell true if <flags> are supported by the C compiler and default linker, else returns shell false.
616 test-flags-CCLD() { test-flags-PROG "CCLD" "$@"; }
617
618 # @FUNCTION: test-flags
619 # @USAGE: <flags>
620 # @DESCRIPTION:
621 # Short-hand that should hopefully work for both C and C++ compiler, but
622 # its really only present due to the append-flags() abomination.
623 test-flags() { test-flags-CC "$@"; }
624
625 # @FUNCTION: test_version_info
626 # @USAGE: <version>
627 # @DESCRIPTION:
628 # Returns shell true if the current C compiler version matches <version>, else returns shell false.
629 # Accepts shell globs.
630 test_version_info() {
631         if [[ $($(tc-getCC) --version 2>&1) == *$1* ]]; then
632                 return 0
633         else
634                 return 1
635         fi
636 }
637
638 # @FUNCTION: strip-unsupported-flags
639 # @DESCRIPTION:
640 # Strip {C,CXX,F,FC}FLAGS of any flags not supported by the active toolchain.
641 strip-unsupported-flags() {
642         [[ $# -ne 0 ]] && die "strip-unsupported-flags takes no arguments"
643         export CFLAGS=$(test-flags-CC ${CFLAGS})
644         export CXXFLAGS=$(test-flags-CXX ${CXXFLAGS})
645         export FFLAGS=$(test-flags-F77 ${FFLAGS})
646         export FCFLAGS=$(test-flags-FC ${FCFLAGS})
647         export LDFLAGS=$(test-flags-CCLD ${LDFLAGS})
648 }
649
650 # @FUNCTION: get-flag
651 # @USAGE: <flag>
652 # @DESCRIPTION:
653 # Find and echo the value for a particular flag.  Accepts shell globs.
654 get-flag() {
655         [[ $# -ne 1 ]] && die "usage: <flag>"
656         local f var findflag="$1"
657
658         # this code looks a little flaky but seems to work for
659         # everything we want ...
660         # for example, if CFLAGS="-march=i686":
661         # `get-flag -march` == "-march=i686"
662         # `get-flag march` == "i686"
663         for var in $(all-flag-vars) ; do
664                 for f in ${!var} ; do
665                         if [ "${f/${findflag}}" != "${f}" ] ; then
666                                 printf "%s\n" "${f/-${findflag}=}"
667                                 return 0
668                         fi
669                 done
670         done
671         return 1
672 }
673
674 # @FUNCTION: replace-sparc64-flags
675 # @DESCRIPTION:
676 # Sets mcpu to v8 and uses the original value as mtune if none specified.
677 replace-sparc64-flags() {
678         [[ $# -ne 0 ]] && die "replace-sparc64-flags takes no arguments"
679         local SPARC64_CPUS="ultrasparc3 ultrasparc v9"
680
681         if [ "${CFLAGS/mtune}" != "${CFLAGS}" ]; then
682                 for x in ${SPARC64_CPUS}; do
683                         CFLAGS="${CFLAGS/-mcpu=${x}/-mcpu=v8}"
684                 done
685         else
686                 for x in ${SPARC64_CPUS}; do
687                         CFLAGS="${CFLAGS/-mcpu=${x}/-mcpu=v8 -mtune=${x}}"
688                 done
689         fi
690
691         if [ "${CXXFLAGS/mtune}" != "${CXXFLAGS}" ]; then
692                 for x in ${SPARC64_CPUS}; do
693                         CXXFLAGS="${CXXFLAGS/-mcpu=${x}/-mcpu=v8}"
694                 done
695         else
696                 for x in ${SPARC64_CPUS}; do
697                         CXXFLAGS="${CXXFLAGS/-mcpu=${x}/-mcpu=v8 -mtune=${x}}"
698                 done
699         fi
700
701         export CFLAGS CXXFLAGS
702 }
703
704 # @FUNCTION: append-libs
705 # @USAGE: <libs>
706 # @DESCRIPTION:
707 # Add extra <libs> to the current LIBS. All arguments should be prefixed with
708 # either -l or -L.  For compatibility, if arguments are not prefixed as
709 # options, they are given a -l prefix automatically.
710 append-libs() {
711         [[ $# -eq 0 ]] && return 0
712         local flag
713         for flag in "$@"; do
714                 if [[ -z "${flag// }" ]]; then
715                         eqawarn "Appending an empty argument to LIBS is invalid! Skipping."
716                         continue
717                 fi
718                 case $flag in
719                         -[lL]*)
720                                 export LIBS="${LIBS} ${flag}"
721                                 ;;
722                         -*)
723                                 eqawarn "Appending non-library to LIBS (${flag}); Other linker flags should be passed via LDFLAGS"
724                                 export LIBS="${LIBS} ${flag}"
725                                 ;;
726                         *)
727                                 export LIBS="${LIBS} -l${flag}"
728                 esac
729         done
730
731         return 0
732 }
733
734 # @FUNCTION: raw-ldflags
735 # @USAGE: [flags]
736 # @DESCRIPTION:
737 # Turn C style ldflags (-Wl,-foo) into straight ldflags - the results
738 # are suitable for passing directly to 'ld'; note LDFLAGS is usually passed
739 # to gcc where it needs the '-Wl,'.
740 #
741 # If no flags are specified, then default to ${LDFLAGS}.
742 raw-ldflags() {
743         local x input="$@"
744         [[ -z ${input} ]] && input=${LDFLAGS}
745         set --
746         for x in ${input} ; do
747                 case ${x} in
748                 -Wl,*)
749                         x=${x#-Wl,}
750                         set -- "$@" ${x//,/ }
751                         ;;
752                 *)      # Assume it's a compiler driver flag, so throw it away #441808
753                         ;;
754                 esac
755         done
756         echo "$@"
757 }
758
759 # @FUNCTION: no-as-needed
760 # @RETURN: Flag to disable asneeded behavior for use with append-ldflags.
761 no-as-needed() {
762         [[ $# -ne 0 ]] && die "no-as-needed takes no arguments"
763         case $($(tc-getLD) -v 2>&1 </dev/null) in
764                 *GNU*) # GNU ld
765                 echo "-Wl,--no-as-needed" ;;
766         esac
767 }
768
769 fi