An early PR filed that erroneously pointed at CMake as the cause. N.B. Comment 24

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208120#c24

Also See

The TLDR; Interim Workaround

export LD_PRELOAD=/usr/local/lib/gcc8/libgcc_s.so

The Why

If you compile with g++ and use our base libgcc it should DTRT provided our libgcc has defined functions that are up to date with current libgcc. We compile with g++, it needs foo() from libgcc to run (A typical function would be multi3) and so our libgcc provides a foo() and g++ is happy.

This means in theory, we can interchangeably use g++ and clang++ in ports. This also means it made the initial port work from from gcc in base to clang in base a lot easier.

The problems come when we try to use architectures not fully supported by our libgcc_s.so or when we use Fortran. Fortran (gnu fortran) like g++ also uses libgcc.

Our libgcc lies in two ways:

1) our libgcc is mostly not GPL code anymore, though there are bits and pieces of GPL depending on what we don't have.

2) It claims to be only up to date with GCC 4.2.4

The moment you load libgfortran, it has a requirement for GCC_4.6 or better, and if our libgcc is already loaded things fail.

The reason ports g++ now has this requirement on 4.6 or better is GNU changed gfortran to always support quad math (REAL(16)) and hence needs /usr/local/lib/gccXX/libquadmath.so They then changed the dependancy stated in libgfortran to always require a later libgcc.

We *could* lie in our libgcc_s and claim to be 4.6 which would simply mean libgfortran would not complain and simply load the missing libquadmath.

If we updated the claimed GCC version in our libgcc_s.so to claim GCC_4.6, we really also should provide a libquadmath substitute.

The other approach is to rename our libgcc_s.so to libclang_s.so or some such and link base with it instead of libgcc_s.so I frankly think this in the long term is the cleaner solution.

Workaround we do

In the ports world, we have papered over this problem by adding -Wl,-rpath=${_GCC_RUNTIME} or similar to force programs to link against /usr/local/lib/gcc${GCCVERSION}/libgcc_s.so Cmake does DTRT.

Why our workaround fails

The real problem comes when interpreters compiled with clang or gcc that do not use libgcc are run. The late binding that happens when a binary module is loaded that does reference a libgcc is what can trigger this bug at run time and this is independent of what our linker (not the run time linker rtld but ld/lld) IFF a binary module is loaded with a libgcc reference it can pull in the wrong libgcc e.g. the base /usr/lib/libgcc_.so

Usually it's a graphics package binary that is brought which are typically compiled with g++ or clang c++. Provided nothing needs libquadmath the two libraries are compatible enough.

Work around for this problem

If one forces the pre load of the gfortran libgcc or LD_PATH it so it comes first, everything works just peachy. I'm guessing python is the most likely to fail in this way. Another work around (tried by me personally) is loading the modules requiring gfortran first which binds the "right" libgcc_s functions and symbols. This still has a problem which is easily worked around. IFF the package used provides separate libraries which can be used independently of the interpreter in question (e.g. python), then the programs compiled against these libraries must use USES+= fortran to preload the right libgcc

Final thoughts and future work

N.B. at this time cmake does not realise flang is a valid fortran compiler.

Mixing gfortran and flang .obj's seem to work until I/O is involved. I'll be investigating this further as time permits.


CategoryPorts

Ports/libgcc_linking_problem (last edited 2021-04-25T02:56:10+0000 by KubilayKocak)