Michał Górny <[email protected]> writes:

> Try linking the code created by C and Fortran compilers together.
> If it fails, try removing LTO flags in case we are combining two
> incompatible compilers (Clang and GNU Fortran).
>
> I don't love this implementation but I think it's the simplest solution
> that is quite reliable at the same time.  If compilers don't seem to
> work, it does not change anything.  In the worst case, it will disable
> LTO unnecessarily.
>

LGTM. Thanks for doing this.

> Closes: https://bugs.gentoo.org/965176
> Signed-off-by: Michał Górny <[email protected]>
> ---
>  eclass/fortran-2.eclass | 90 +++++++++++++++++++++++++++++++++++++----
>  1 file changed, 82 insertions(+), 8 deletions(-)
>
> diff --git a/eclass/fortran-2.eclass b/eclass/fortran-2.eclass
> index dcf7ee979d8af..5b64244bb70f4 100644
> --- a/eclass/fortran-2.eclass
> +++ b/eclass/fortran-2.eclass
> @@ -34,7 +34,7 @@ case ${EAPI} in
>       *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
>  esac
>  
> -inherit toolchain-funcs
> +inherit flag-o-matic toolchain-funcs
>  
>  # @ECLASS_VARIABLE: FORTRAN_NEED_OPENMP
>  # @DESCRIPTION:
> @@ -187,6 +187,66 @@ _fortran-has-openmp() {
>       return ${ret}
>  }
>  
> +# @FUNCTION: _fortran-test-lto
> +# @INTERNAL
> +# @DESCRIPTION:
> +# Test if C and Fortran files can be linked together.  If it fails, remove
> +# LTO flags.  This may be necessary if users are combining Clang
> +# with GNU Fortran, and enabling LTO, since this will result in two different
> +# kinds of bytecode being linked with a linker that's set up for only one
> +# of them.
> +_fortran-test-lto() {
> +     debug-print-function ${FUNCNAME} "$@"
> +
> +     local compiler=${1}
> +     local flags=${2}
> +     local fcode=${T}/test-fc.f
> +     local ccode=${T}/test-fc.c
> +     local fail=
> +
> +     einfo "Testing linking C and Fortran code ..."
> +
> +     cat <<- EOF > "${fcode}" || die
> +                    subroutine fsub()
> +                    end
> +     EOF
> +     cat <<- EOF > "${ccode}" || die
> +             void fsub_();
> +
> +             int main() {
> +                     fsub_();
> +                     return 0;
> +             }
> +     EOF
> +
> +     # Prepare test objects.  If either failed, do nothing.
> +
> +     set -- ${compiler} ${flags} -c "${fcode}" -o "${fcode}.o"
> +     echo "${@}" >&2
> +     "${@}" || return
> +
> +     set -- $(tc-getCC) ${CFLAGS} -c "${ccode}" -o "${ccode}.o"
> +     echo "${@}" >&2
> +     "${@}" || return
> +
> +     # Try cross-linking.
> +
> +     set -- ${compiler} ${flags} ${LDFLAGS} -o "${fcode}.exe" "${fcode}.o" 
> "${ccode}.o"
> +     echo "${@}" >&2
> +     "${@}" || fail=1
> +
> +     set -- $(tc-getCC) ${CFLAGS} ${LDFLAGS} -o "${fcode}.exe" "${fcode}.o" 
> "${ccode}.o"
> +     echo "${@}" >&2
> +     "${@}" || fail=1
> +
> +     if [[ ! ${fail} ]]; then
> +             einfo "Looks like we can link C and Fortran code together"
> +     else
> +             einfo "Cross-linking C and Fortran failed, force-disabling LTO"
> +             filter-lto
> +     fi
> +}
> +
>  # @FUNCTION: _fortran_die_msg
>  # @INTERNAL
>  # @DESCRIPTION:
> @@ -211,19 +271,31 @@ _fortran_die_msg() {
>  _fortran_test_function() {
>       debug-print-function ${FUNCNAME} "$@"
>  
> -     local dialect
> +     local compiler dialect flags
>  
>       : "${F77:=$(tc-getFC)}"
>  
>       : "${FORTRAN_STANDARD:=77}"
>       for dialect in ${FORTRAN_STANDARD}; do
>               case ${dialect} in
> -                     77) _fortran_compile_test "$(tc-getF77)" || \
> -                             _fortran_die_msg ;;
> -                     90|95) _fortran_compile_test "$(tc-getFC)" 90 || \
> -                             _fortran_die_msg ;;
> -                     2003) _fortran_compile_test "$(tc-getFC)" 03 || \
> -                             _fortran_die_msg ;;
> +                     77)
> +                             compiler=$(tc-getF77)
> +                             flags=${FFLAGS}
> +                             _fortran_compile_test "${compiler}" ||
> +                                     _fortran_die_msg 
> +                             ;;
> +                     90|95)
> +                             compiler=$(tc-getFC)
> +                             flags=${FCFLAGS}
> +                             _fortran_compile_test "${compiler}" 90 ||
> +                                     _fortran_die_msg
> +                             ;;
> +                     2003)
> +                             compiler=$(tc-getFC)
> +                             flags=${FCFLAGS}
> +                             _fortran_compile_test "${compiler}" 03 ||
> +                                     _fortran_die_msg
> +                             ;;
>                       2008) die "Future" ;;
>                       *) die "${dialect} is not a Fortran dialect." ;;
>               esac
> @@ -241,6 +313,8 @@ _fortran_test_function() {
>                       die "Please install current gcc with USE=openmp or set 
> the FC variable to a compiler that supports OpenMP"
>               fi
>       fi
> +
> +     _fortran-test-lto "${compiler}" "${flags}"
>  }
>  
>  # @FUNCTION: _fortran-2_pkg_setup

Reply via email to