mirror of
https://github.com/gentoo-mirror/gentoo.git
synced 2026-08-23 18:38:08 -07:00
Revert multiple meaningless eclass documentation changes, notably adding a lot of placeholders and documenting implementation details. These changes were aimed at silencing (valid) documentation warnings without actually providing valuable documentation to the end users. While some of these changes were beneficial, it would take a lot of effort to review them all and the author is unwilling to fix his mistakes. Signed-off-by: Michał Górny <mgorny@gentoo.org>
777 lines
20 KiB
Bash
777 lines
20 KiB
Bash
# Copyright 1999-2020 Gentoo Authors
|
|
# Distributed under the terms of the GNU General Public License v2
|
|
|
|
# @ECLASS: flag-o-matic.eclass
|
|
# @MAINTAINER:
|
|
# toolchain@gentoo.org
|
|
# @BLURB: common functions to manipulate and query toolchain flags
|
|
# @DESCRIPTION:
|
|
# This eclass contains a suite of functions to help developers sanely
|
|
# and safely manage toolchain flags in their builds.
|
|
|
|
if [[ -z ${_FLAG_O_MATIC_ECLASS} ]]; then
|
|
_FLAG_O_MATIC_ECLASS=1
|
|
|
|
inherit eutils toolchain-funcs multilib
|
|
|
|
# Return all the flag variables that our high level funcs operate on.
|
|
all-flag-vars() {
|
|
echo {ADA,C,CPP,CXX,CCAS,F,FC,LD}FLAGS
|
|
}
|
|
|
|
# {C,CPP,CXX,CCAS,F,FC,LD}FLAGS that we allow in strip-flags
|
|
# Note: shell globs and character lists are allowed
|
|
setup-allowed-flags() {
|
|
ALLOWED_FLAGS=(
|
|
-pipe -O '-O[12sg]' -mcpu -march -mtune
|
|
'-fstack-protector*' '-fsanitize*' '-fstack-check*' -fno-stack-check
|
|
-fbounds-check -fbounds-checking -fno-strict-overflow
|
|
-fno-PIE -fno-pie -nopie -no-pie -fno-unit-at-a-time
|
|
|
|
# debugging symbols should generally be very safe to add
|
|
-g '-g[0-9]'
|
|
-ggdb '-ggdb[0-9]'
|
|
-gdwarf '-gdwarf-*'
|
|
-gstabs -gstabs+
|
|
-gz
|
|
|
|
-fno-ident -fpermissive -frecord-gcc-switches
|
|
'-fdiagnostics*' '-fplugin*'
|
|
'-W*' -w
|
|
|
|
# CPPFLAGS and LDFLAGS
|
|
'-[DUILR]*' '-Wl,*'
|
|
|
|
# Linker choice flag
|
|
'-fuse-ld'
|
|
)
|
|
|
|
# allow a bunch of flags that negate features / control ABI
|
|
ALLOWED_FLAGS+=(
|
|
'-fno-stack-protector*' '-fabi-version=*'
|
|
-fno-strict-aliasing -fno-bounds-check -fno-bounds-checking -fstrict-overflow
|
|
-fno-omit-frame-pointer '-fno-builtin*'
|
|
)
|
|
ALLOWED_FLAGS+=(
|
|
-mregparm -mno-app-regs -mapp-regs -mno-mmx -mno-sse
|
|
-mno-sse2 -mno-sse3 -mno-ssse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2
|
|
-mno-avx -mno-aes -mno-pclmul -mno-sse4a -mno-3dnow -mno-popcnt
|
|
-mno-abm -mips1 -mips2 -mips3 -mips4 -mips32 -mips64 -mips16 -mplt
|
|
-msoft-float -mno-soft-float -mhard-float -mno-hard-float -mfpu
|
|
-mieee -mieee-with-inexact -mschedule -mfloat-gprs -mspe -mno-spe
|
|
-mtls-direct-seg-refs -mno-tls-direct-seg-refs -mflat -mno-flat
|
|
-mno-faster-structs -mfaster-structs -m32 -m64 -mx32 -mabi
|
|
-mlittle-endian -mbig-endian -EL -EB -fPIC -mlive-g0 -mcmodel
|
|
-mstack-bias -mno-stack-bias -msecure-plt '-m*-toc' -mfloat-abi
|
|
-mfix-r4000 -mno-fix-r4000 -mfix-r4400 -mno-fix-r4400
|
|
-mfix-rm7000 -mno-fix-rm7000 -mfix-r10000 -mno-fix-r10000
|
|
-mr10k-cache-barrier -mthumb -marm
|
|
|
|
# gcc 4.5
|
|
-mno-fma4 -mno-movbe -mno-xop -mno-lwp
|
|
# gcc 4.6
|
|
-mno-fsgsbase -mno-rdrnd -mno-f16c -mno-bmi -mno-tbm
|
|
# gcc 4.7
|
|
-mno-avx2 -mno-bmi2 -mno-fma -mno-lzcnt
|
|
# gcc 4.8
|
|
-mno-fxsr -mno-hle -mno-rtm -mno-xsave -mno-xsaveopt
|
|
# gcc 4.9
|
|
-mno-avx512cd -mno-avx512er -mno-avx512f -mno-avx512pf -mno-sha
|
|
)
|
|
|
|
# Allow some safe individual flags. Should come along with the bug reference.
|
|
ALLOWED_FLAGS+=(
|
|
# Allow explicit stack realignment to run non-conformant
|
|
# binaries: bug #677852
|
|
-mstackrealign
|
|
)
|
|
}
|
|
|
|
# inverted filters for hardened compiler. This is trying to unpick
|
|
# the hardened compiler defaults.
|
|
_filter-hardened() {
|
|
local f
|
|
for f in "$@" ; do
|
|
case "${f}" in
|
|
# Ideally we should only concern ourselves with PIE flags,
|
|
# not -fPIC or -fpic, but too many places filter -fPIC without
|
|
# thinking about -fPIE.
|
|
-fPIC|-fpic|-fPIE|-fpie|-Wl,pie|-pie)
|
|
gcc-specs-pie || continue
|
|
if ! is-flagq -nopie && ! is-flagq -no-pie ; then
|
|
# Support older Gentoo form first (-nopie) before falling
|
|
# back to the official gcc-6+ form (-no-pie).
|
|
if test-flags -nopie >/dev/null ; then
|
|
append-flags -nopie
|
|
else
|
|
append-flags -no-pie
|
|
fi
|
|
fi
|
|
;;
|
|
-fstack-protector)
|
|
gcc-specs-ssp || continue
|
|
is-flagq -fno-stack-protector || append-flags $(test-flags -fno-stack-protector);;
|
|
-fstack-protector-all)
|
|
gcc-specs-ssp-to-all || continue
|
|
is-flagq -fno-stack-protector-all || append-flags $(test-flags -fno-stack-protector-all);;
|
|
-fno-strict-overflow)
|
|
gcc-specs-nostrict || continue
|
|
is-flagq -fstrict-overflow || append-flags $(test-flags -fstrict-overflow);;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Remove occurrences of strings from variable given in $1
|
|
# Strings removed are matched as globs, so for example
|
|
# '-O*' would remove -O1, -O2 etc.
|
|
_filter-var() {
|
|
local f x var=$1 new=()
|
|
shift
|
|
|
|
for f in ${!var} ; do
|
|
for x in "$@" ; do
|
|
# Note this should work with globs like -O*
|
|
[[ ${f} == ${x} ]] && continue 2
|
|
done
|
|
new+=( "${f}" )
|
|
done
|
|
export ${var}="${new[*]}"
|
|
}
|
|
|
|
# @FUNCTION: filter-flags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Remove particular <flags> from {C,CPP,CXX,CCAS,F,FC,LD}FLAGS. Accepts shell globs.
|
|
filter-flags() {
|
|
_filter-hardened "$@"
|
|
local v
|
|
for v in $(all-flag-vars) ; do
|
|
_filter-var ${v} "$@"
|
|
done
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: filter-lfs-flags
|
|
# @DESCRIPTION:
|
|
# Remove flags that enable Large File Support.
|
|
filter-lfs-flags() {
|
|
[[ $# -ne 0 ]] && die "filter-lfs-flags takes no arguments"
|
|
# http://www.gnu.org/s/libc/manual/html_node/Feature-Test-Macros.html
|
|
# _LARGEFILE_SOURCE: enable support for new LFS funcs (ftello/etc...)
|
|
# _LARGEFILE64_SOURCE: enable support for 64bit variants (off64_t/fseeko64/etc...)
|
|
# _FILE_OFFSET_BITS: default to 64bit variants (off_t is defined as off64_t)
|
|
filter-flags -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
|
|
}
|
|
|
|
# @FUNCTION: filter-ldflags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Remove particular <flags> from LDFLAGS. Accepts shell globs.
|
|
filter-ldflags() {
|
|
_filter-var LDFLAGS "$@"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: append-cppflags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Add extra <flags> to the current CPPFLAGS.
|
|
append-cppflags() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
export CPPFLAGS+=" $*"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: append-cflags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Add extra <flags> to the current CFLAGS. If a flag might not be supported
|
|
# with different compilers (or versions), then use test-flags-CC like so:
|
|
# @CODE
|
|
# append-cflags $(test-flags-CC -funky-flag)
|
|
# @CODE
|
|
append-cflags() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
# Do not do automatic flag testing ourselves. #417047
|
|
export CFLAGS+=" $*"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: append-cxxflags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Add extra <flags> to the current CXXFLAGS. If a flag might not be supported
|
|
# with different compilers (or versions), then use test-flags-CXX like so:
|
|
# @CODE
|
|
# append-cxxflags $(test-flags-CXX -funky-flag)
|
|
# @CODE
|
|
append-cxxflags() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
# Do not do automatic flag testing ourselves. #417047
|
|
export CXXFLAGS+=" $*"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: append-fflags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Add extra <flags> to the current {F,FC}FLAGS. If a flag might not be supported
|
|
# with different compilers (or versions), then use test-flags-F77 like so:
|
|
# @CODE
|
|
# append-fflags $(test-flags-F77 -funky-flag)
|
|
# @CODE
|
|
append-fflags() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
# Do not do automatic flag testing ourselves. #417047
|
|
export FFLAGS+=" $*"
|
|
export FCFLAGS+=" $*"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: append-lfs-flags
|
|
# @DESCRIPTION:
|
|
# Add flags that enable Large File Support.
|
|
append-lfs-flags() {
|
|
[[ $# -ne 0 ]] && die "append-lfs-flags takes no arguments"
|
|
# see comments in filter-lfs-flags func for meaning of these
|
|
append-cppflags -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
|
|
}
|
|
|
|
# @FUNCTION: append-ldflags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Add extra <flags> to the current LDFLAGS.
|
|
append-ldflags() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
local flag
|
|
for flag in "$@"; do
|
|
[[ ${flag} == -l* ]] && \
|
|
eqawarn "Appending a library link instruction (${flag}); libraries to link to should not be passed through LDFLAGS"
|
|
done
|
|
|
|
export LDFLAGS="${LDFLAGS} $*"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: append-flags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Add extra <flags> to your current {C,CXX,F,FC}FLAGS.
|
|
append-flags() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
case " $* " in
|
|
*' '-[DIU]*) eqawarn 'please use append-cppflags for preprocessor flags' ;;
|
|
*' '-L*|\
|
|
*' '-Wl,*) eqawarn 'please use append-ldflags for linker flags' ;;
|
|
esac
|
|
append-cflags "$@"
|
|
append-cxxflags "$@"
|
|
append-fflags "$@"
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: replace-flags
|
|
# @USAGE: <old> <new>
|
|
# @DESCRIPTION:
|
|
# Replace the <old> flag with <new>. Accepts shell globs for <old>.
|
|
replace-flags() {
|
|
[[ $# != 2 ]] && die "Usage: replace-flags <old flag> <new flag>"
|
|
|
|
local f var new
|
|
for var in $(all-flag-vars) ; do
|
|
# Looping over the flags instead of using a global
|
|
# substitution ensures that we're working with flag atoms.
|
|
# Otherwise globs like -O* have the potential to wipe out the
|
|
# list of flags.
|
|
new=()
|
|
for f in ${!var} ; do
|
|
# Note this should work with globs like -O*
|
|
[[ ${f} == ${1} ]] && f=${2}
|
|
new+=( "${f}" )
|
|
done
|
|
export ${var}="${new[*]}"
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: replace-cpu-flags
|
|
# @USAGE: <old> <new>
|
|
# @DESCRIPTION:
|
|
# Replace cpu flags (like -march/-mcpu/-mtune) that select the <old> cpu
|
|
# with flags that select the <new> cpu. Accepts shell globs for <old>.
|
|
replace-cpu-flags() {
|
|
local newcpu="$#" ; newcpu="${!newcpu}"
|
|
while [ $# -gt 1 ] ; do
|
|
# quote to make sure that no globbing is done (particularly on
|
|
# ${oldcpu}) prior to calling replace-flags
|
|
replace-flags "-march=${1}" "-march=${newcpu}"
|
|
replace-flags "-mcpu=${1}" "-mcpu=${newcpu}"
|
|
replace-flags "-mtune=${1}" "-mtune=${newcpu}"
|
|
shift
|
|
done
|
|
return 0
|
|
}
|
|
|
|
_is_flagq() {
|
|
local x var="$1[*]"
|
|
for x in ${!var} ; do
|
|
[[ ${x} == $2 ]] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# @FUNCTION: is-flagq
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is in {C,CXX,F,FC}FLAGS, else returns shell false. Accepts shell globs.
|
|
is-flagq() {
|
|
[[ -n $2 ]] && die "Usage: is-flag <flag>"
|
|
|
|
local var
|
|
for var in $(all-flag-vars) ; do
|
|
_is_flagq ${var} "$1" && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# @FUNCTION: is-flag
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Echo's "true" if flag is set in {C,CXX,F,FC}FLAGS. Accepts shell globs.
|
|
is-flag() {
|
|
is-flagq "$@" && echo true
|
|
}
|
|
|
|
# @FUNCTION: is-ldflagq
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is in LDFLAGS, else returns shell false. Accepts shell globs.
|
|
is-ldflagq() {
|
|
[[ -n $2 ]] && die "Usage: is-ldflag <flag>"
|
|
_is_flagq LDFLAGS $1
|
|
}
|
|
|
|
# @FUNCTION: is-ldflag
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Echo's "true" if flag is set in LDFLAGS. Accepts shell globs.
|
|
is-ldflag() {
|
|
is-ldflagq "$@" && echo true
|
|
}
|
|
|
|
# @FUNCTION: filter-mfpmath
|
|
# @USAGE: <math types>
|
|
# @DESCRIPTION:
|
|
# Remove specified math types from the fpmath flag. For example, if the user
|
|
# has -mfpmath=sse,386, running `filter-mfpmath sse` will leave the user with
|
|
# -mfpmath=386.
|
|
filter-mfpmath() {
|
|
local orig_mfpmath new_math prune_math
|
|
|
|
# save the original -mfpmath flag
|
|
orig_mfpmath=$(get-flag -mfpmath)
|
|
# get the value of the current -mfpmath flag
|
|
new_math=$(get-flag mfpmath)
|
|
# convert "both" to something we can filter
|
|
new_math=${new_math/both/387,sse}
|
|
new_math=" ${new_math//[,+]/ } "
|
|
# figure out which math values are to be removed
|
|
prune_math=""
|
|
for prune_math in "$@" ; do
|
|
new_math=${new_math/ ${prune_math} / }
|
|
done
|
|
new_math=$(echo ${new_math})
|
|
new_math=${new_math// /,}
|
|
|
|
if [[ -z ${new_math} ]] ; then
|
|
# if we're removing all user specified math values are
|
|
# slated for removal, then we just filter the flag
|
|
filter-flags ${orig_mfpmath}
|
|
else
|
|
# if we only want to filter some of the user specified
|
|
# math values, then we replace the current flag
|
|
replace-flags ${orig_mfpmath} -mfpmath=${new_math}
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: strip-flags
|
|
# @DESCRIPTION:
|
|
# Strip *FLAGS of everything except known good/safe flags. This runs over all
|
|
# flags returned by all_flag_vars().
|
|
strip-flags() {
|
|
[[ $# -ne 0 ]] && die "strip-flags takes no arguments"
|
|
local x y var
|
|
|
|
local ALLOWED_FLAGS
|
|
setup-allowed-flags
|
|
|
|
set -f # disable pathname expansion
|
|
|
|
for var in $(all-flag-vars) ; do
|
|
local new=()
|
|
|
|
for x in ${!var} ; do
|
|
local flag=${x%%=*}
|
|
for y in "${ALLOWED_FLAGS[@]}" ; do
|
|
if [[ -z ${flag%%${y}} ]] ; then
|
|
new+=( "${x}" )
|
|
break
|
|
fi
|
|
done
|
|
done
|
|
|
|
# In case we filtered out all optimization flags fallback to -O2
|
|
if _is_flagq ${var} "-O*" && ! _is_flagq new "-O*" ; then
|
|
new+=( -O2 )
|
|
fi
|
|
|
|
if [[ ${!var} != "${new[*]}" ]] ; then
|
|
einfo "strip-flags: ${var}: changed '${!var}' to '${new[*]}'"
|
|
fi
|
|
export ${var}="${new[*]}"
|
|
done
|
|
|
|
set +f # re-enable pathname expansion
|
|
|
|
return 0
|
|
}
|
|
|
|
test-flag-PROG() {
|
|
local comp=$1
|
|
local lang=$2
|
|
shift 2
|
|
|
|
if [[ -z ${comp} ]]; then
|
|
return 1
|
|
fi
|
|
if [[ -z $1 ]]; then
|
|
return 1
|
|
fi
|
|
|
|
# verify selected compiler exists before using it
|
|
comp=($(tc-get${comp}))
|
|
# 'comp' can already contain compiler options.
|
|
# 'type' needs a binary name
|
|
if ! type -p ${comp[0]} >/dev/null; then
|
|
return 1
|
|
fi
|
|
|
|
# Set up test file.
|
|
local in_src in_ext cmdline_extra=()
|
|
case "${lang}" in
|
|
# compiler/assembler only
|
|
c)
|
|
in_ext='c'
|
|
in_src='int main(void) { return 0; }'
|
|
cmdline_extra+=(-xc -c)
|
|
;;
|
|
c++)
|
|
in_ext='cc'
|
|
in_src='int main(void) { return 0; }'
|
|
cmdline_extra+=(-xc++ -c)
|
|
;;
|
|
f77)
|
|
in_ext='f'
|
|
# fixed source form
|
|
in_src=' end'
|
|
cmdline_extra+=(-xf77 -c)
|
|
;;
|
|
f95)
|
|
in_ext='f90'
|
|
in_src='end'
|
|
cmdline_extra+=(-xf95 -c)
|
|
;;
|
|
|
|
# C compiler/assembler/linker
|
|
c+ld)
|
|
in_ext='c'
|
|
in_src='int main(void) { return 0; }'
|
|
cmdline_extra+=(-xc)
|
|
;;
|
|
esac
|
|
local test_in=${T}/test-flag.${in_ext}
|
|
local test_out=${T}/test-flag.exe
|
|
|
|
printf "%s\n" "${in_src}" > "${test_in}" || die "Failed to create '${test_in}'"
|
|
|
|
# Currently we rely on warning-free output of a compiler
|
|
# before the flag to see if a flag prduces any warnings.
|
|
# This has a few drawbacks:
|
|
# - if compiler already generates warnings we filter out
|
|
# every single flag: bug #712488
|
|
# - if user actually wants to see warnings we just strip
|
|
# them regardless of warnings type.
|
|
#
|
|
# We can add more selective detection of no-op flags via
|
|
# '-Werror=ignored-optimization-argument' and similar error options
|
|
# similar to what we are doing with '-Qunused-arguments'.
|
|
local cmdline=(
|
|
"${comp[@]}"
|
|
# Clang will warn about unknown gcc flags but exit 0.
|
|
# Need -Werror to force it to exit non-zero.
|
|
-Werror
|
|
"$@"
|
|
# -x<lang> options need to go before first source file
|
|
"${cmdline_extra[@]}"
|
|
|
|
"${test_in}" -o "${test_out}"
|
|
)
|
|
|
|
if ! "${cmdline[@]}" &>/dev/null; then
|
|
# -Werror makes clang bail out on unused arguments as well;
|
|
# try to add -Qunused-arguments to work-around that
|
|
# other compilers don't support it but then, it's failure like
|
|
# any other
|
|
cmdline+=( -Qunused-arguments )
|
|
"${cmdline[@]}" &>/dev/null
|
|
fi
|
|
}
|
|
|
|
# @FUNCTION: test-flag-CC
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is supported by the C compiler, else returns shell false.
|
|
test-flag-CC() { test-flag-PROG "CC" c "$@"; }
|
|
|
|
# @FUNCTION: test-flag-CXX
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is supported by the C++ compiler, else returns shell false.
|
|
test-flag-CXX() { test-flag-PROG "CXX" c++ "$@"; }
|
|
|
|
# @FUNCTION: test-flag-F77
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is supported by the Fortran 77 compiler, else returns shell false.
|
|
test-flag-F77() { test-flag-PROG "F77" f77 "$@"; }
|
|
|
|
# @FUNCTION: test-flag-FC
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is supported by the Fortran 90 compiler, else returns shell false.
|
|
test-flag-FC() { test-flag-PROG "FC" f95 "$@"; }
|
|
|
|
# @FUNCTION: test-flag-CCLD
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flag> is supported by the C compiler and linker, else returns shell false.
|
|
test-flag-CCLD() { test-flag-PROG "CC" c+ld "$@"; }
|
|
|
|
test-flags-PROG() {
|
|
local comp=$1
|
|
local flags=()
|
|
local x
|
|
|
|
shift
|
|
|
|
[[ -z ${comp} ]] && return 1
|
|
|
|
while (( $# )); do
|
|
case "$1" in
|
|
# '-B /foo': bug # 687198
|
|
--param|-B)
|
|
if test-flag-${comp} "$1" "$2"; then
|
|
flags+=( "$1" "$2" )
|
|
fi
|
|
shift 2
|
|
;;
|
|
*)
|
|
if test-flag-${comp} "$1"; then
|
|
flags+=( "$1" )
|
|
fi
|
|
shift 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
echo "${flags[*]}"
|
|
|
|
# Just bail if we dont have any flags
|
|
[[ ${#flags[@]} -gt 0 ]]
|
|
}
|
|
|
|
# @FUNCTION: test-flags-CC
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flags> are supported by the C compiler, else returns shell false.
|
|
test-flags-CC() { test-flags-PROG "CC" "$@"; }
|
|
|
|
# @FUNCTION: test-flags-CXX
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flags> are supported by the C++ compiler, else returns shell false.
|
|
test-flags-CXX() { test-flags-PROG "CXX" "$@"; }
|
|
|
|
# @FUNCTION: test-flags-F77
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flags> are supported by the Fortran 77 compiler, else returns shell false.
|
|
test-flags-F77() { test-flags-PROG "F77" "$@"; }
|
|
|
|
# @FUNCTION: test-flags-FC
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flags> are supported by the Fortran 90 compiler, else returns shell false.
|
|
test-flags-FC() { test-flags-PROG "FC" "$@"; }
|
|
|
|
# @FUNCTION: test-flags-CCLD
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if <flags> are supported by the C compiler and default linker, else returns shell false.
|
|
test-flags-CCLD() { test-flags-PROG "CCLD" "$@"; }
|
|
|
|
# @FUNCTION: test-flags
|
|
# @USAGE: <flags>
|
|
# @DESCRIPTION:
|
|
# Short-hand that should hopefully work for both C and C++ compiler, but
|
|
# its really only present due to the append-flags() abomination.
|
|
test-flags() { test-flags-CC "$@"; }
|
|
|
|
# @FUNCTION: test_version_info
|
|
# @USAGE: <version>
|
|
# @DESCRIPTION:
|
|
# Returns shell true if the current C compiler version matches <version>, else returns shell false.
|
|
# Accepts shell globs.
|
|
test_version_info() {
|
|
if [[ $($(tc-getCC) --version 2>&1) == *$1* ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# @FUNCTION: strip-unsupported-flags
|
|
# @DESCRIPTION:
|
|
# Strip {C,CXX,F,FC}FLAGS of any flags not supported by the active toolchain.
|
|
strip-unsupported-flags() {
|
|
[[ $# -ne 0 ]] && die "strip-unsupported-flags takes no arguments"
|
|
export CFLAGS=$(test-flags-CC ${CFLAGS})
|
|
export CXXFLAGS=$(test-flags-CXX ${CXXFLAGS})
|
|
export FFLAGS=$(test-flags-F77 ${FFLAGS})
|
|
export FCFLAGS=$(test-flags-FC ${FCFLAGS})
|
|
export LDFLAGS=$(test-flags-CCLD ${LDFLAGS})
|
|
}
|
|
|
|
# @FUNCTION: get-flag
|
|
# @USAGE: <flag>
|
|
# @DESCRIPTION:
|
|
# Find and echo the value for a particular flag. Accepts shell globs.
|
|
get-flag() {
|
|
[[ $# -ne 1 ]] && die "usage: <flag>"
|
|
local f var findflag="$1"
|
|
|
|
# this code looks a little flaky but seems to work for
|
|
# everything we want ...
|
|
# for example, if CFLAGS="-march=i686":
|
|
# `get-flag -march` == "-march=i686"
|
|
# `get-flag march` == "i686"
|
|
for var in $(all-flag-vars) ; do
|
|
for f in ${!var} ; do
|
|
if [ "${f/${findflag}}" != "${f}" ] ; then
|
|
printf "%s\n" "${f/-${findflag}=}"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# @FUNCTION: replace-sparc64-flags
|
|
# @DESCRIPTION:
|
|
# Sets mcpu to v8 and uses the original value as mtune if none specified.
|
|
replace-sparc64-flags() {
|
|
[[ $# -ne 0 ]] && die "replace-sparc64-flags takes no arguments"
|
|
local SPARC64_CPUS="ultrasparc3 ultrasparc v9"
|
|
|
|
if [ "${CFLAGS/mtune}" != "${CFLAGS}" ]; then
|
|
for x in ${SPARC64_CPUS}; do
|
|
CFLAGS="${CFLAGS/-mcpu=${x}/-mcpu=v8}"
|
|
done
|
|
else
|
|
for x in ${SPARC64_CPUS}; do
|
|
CFLAGS="${CFLAGS/-mcpu=${x}/-mcpu=v8 -mtune=${x}}"
|
|
done
|
|
fi
|
|
|
|
if [ "${CXXFLAGS/mtune}" != "${CXXFLAGS}" ]; then
|
|
for x in ${SPARC64_CPUS}; do
|
|
CXXFLAGS="${CXXFLAGS/-mcpu=${x}/-mcpu=v8}"
|
|
done
|
|
else
|
|
for x in ${SPARC64_CPUS}; do
|
|
CXXFLAGS="${CXXFLAGS/-mcpu=${x}/-mcpu=v8 -mtune=${x}}"
|
|
done
|
|
fi
|
|
|
|
export CFLAGS CXXFLAGS
|
|
}
|
|
|
|
# @FUNCTION: append-libs
|
|
# @USAGE: <libs>
|
|
# @DESCRIPTION:
|
|
# Add extra <libs> to the current LIBS. All arguments should be prefixed with
|
|
# either -l or -L. For compatibility, if arguments are not prefixed as
|
|
# options, they are given a -l prefix automatically.
|
|
append-libs() {
|
|
[[ $# -eq 0 ]] && return 0
|
|
local flag
|
|
for flag in "$@"; do
|
|
if [[ -z "${flag// }" ]]; then
|
|
eqawarn "Appending an empty argument to LIBS is invalid! Skipping."
|
|
continue
|
|
fi
|
|
case $flag in
|
|
-[lL]*)
|
|
export LIBS="${LIBS} ${flag}"
|
|
;;
|
|
-*)
|
|
eqawarn "Appending non-library to LIBS (${flag}); Other linker flags should be passed via LDFLAGS"
|
|
export LIBS="${LIBS} ${flag}"
|
|
;;
|
|
*)
|
|
export LIBS="${LIBS} -l${flag}"
|
|
esac
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
# @FUNCTION: raw-ldflags
|
|
# @USAGE: [flags]
|
|
# @DESCRIPTION:
|
|
# Turn C style ldflags (-Wl,-foo) into straight ldflags - the results
|
|
# are suitable for passing directly to 'ld'; note LDFLAGS is usually passed
|
|
# to gcc where it needs the '-Wl,'.
|
|
#
|
|
# If no flags are specified, then default to ${LDFLAGS}.
|
|
raw-ldflags() {
|
|
local x input="$@"
|
|
[[ -z ${input} ]] && input=${LDFLAGS}
|
|
set --
|
|
for x in ${input} ; do
|
|
case ${x} in
|
|
-Wl,*)
|
|
x=${x#-Wl,}
|
|
set -- "$@" ${x//,/ }
|
|
;;
|
|
*) # Assume it's a compiler driver flag, so throw it away #441808
|
|
;;
|
|
esac
|
|
done
|
|
echo "$@"
|
|
}
|
|
|
|
# @FUNCTION: no-as-needed
|
|
# @RETURN: Flag to disable asneeded behavior for use with append-ldflags.
|
|
no-as-needed() {
|
|
[[ $# -ne 0 ]] && die "no-as-needed takes no arguments"
|
|
case $($(tc-getLD) -v 2>&1 </dev/null) in
|
|
*GNU*) # GNU ld
|
|
echo "-Wl,--no-as-needed" ;;
|
|
esac
|
|
}
|
|
|
|
fi
|