Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| ports:libgcc_linking_problem [2017/10/24 16:31] – Initial summary of libgcc_s problems DianeBruce | ports:libgcc_linking_problem [2021/04/25 02:56] (current) – Add CategoryPorts KubilayKocak | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | If you compile with gcc and use our base libgcc it should DTRT | + | ===== See Related PR's all the same problem ===== |
| - | *provided* our libgcc has defined functions that are up to date | + | |
| - | with current libgcc | + | |
| - | We compile with gcc, it needs foo() from libgcc to run | + | |
| - | doesn't matter what foo() is (A typical function would be T __multi3)__ | + | |
| - | So our libgcc provides a foo() and gcc is happy | + | An early PR filed that erroneously pointed at CMake as the cause. N.B. Comment 24 |
| - | This means in theory, we can interchangeably use gcc and clang in ports. | + | https:// |
| - | 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 | + | * https:// |
| - | supported by our libgcc_s.so or when we use fortran. | + | * https:// |
| + | * https:// | ||
| - | However, our libgcc lies in two ways | + | ===== Also See ===== |
| - | 1) our libgcc is mostly not GPL code anymore, though there are | + | |
| - | bits and pieces of GPL depending on what we don't have. | + | |
| - | This includes (or did) some of the work ian@ was trying to do with arm, | + | * https:// |
| - | various bits that arm libgcc provides from gcc were missing. | + | |
| - | 2) It claims to be only up to date with GCC 4.2.4 | + | ===== The TLDR; Interim Workaround ===== |
| - | Everything is peachy keen until someone references a symbol which is in | + | export LD_PRELOAD=/ |
| - | anything gcc compiled using a newer > GCC 4.2.4 compiler. | + | |
| - | The moment you load libgfortran, | + | ====== |
| - | and if our libgcc is already loaded things fail. | + | |
| - | The reason ports gcc now has this requirment on 4.6 or better is | + | If you compile with g++ and use our base libgcc it should DTRT //provided// our libgcc has defined functions that are up to date |
| - | GNU changed gfortran to always support quad math (*8) and hence needs | + | with current libgcc. We compile with g++, it needs foo() from libgcc |
| - | /usr/local/lib/gccXX/ | + | __so our **libgcc** provides a foo() and g++ is happy.__ |
| - | We *could* lie in our libgcc_s | + | 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. |
| - | mean libgfortran would not complain and simply load the missing libquadmath. | + | |
| - | If we updated the claimed GCC version in our libgcc_s.so | + | The problems come when we try to use architectures not fully supported by our libgcc_s.so |
| - | GCC_4.6, | + | Fortran (gnu fortran) like g++ also uses libgcc. |
| - | The other approach is to rename our libgcc_s.so to libclang_s.so or | + | Our libgcc lies in two ways: |
| - | some such and link base with it instead of libgcc_s.so | + | |
| - | I frankly think this in the long term is the cleaner solution. | + | 1) our libgcc |
| - | In the ports world, we have papered over this problem by adding | + | This includes (or did) some of the work ian@ was trying to do with arm, various bits that arm libgcc |
| - | -Wl, | + | |
| - | against / | + | |
| - | cmake does DTRT but programs | + | |
| - | prior knowledge that a binary module they are going to load during | + | |
| - | execution will be gfortran built and need libquadmath therefore asking for a later libgcc | + | |
| - | Hence if one forces the pre load of gfortran libgcc or LD_PATH | + | |
| - | it so it comes first, everything works just peachy. I'm guessing python | + | |
| - | is the biggest user of loaded gfortran binary modules but the problem | + | |
| - | could come up in other interpreters. | + | |
| - | N.B. at this time clang does not realise flang is a valid fortran compiler. | + | 2) It claims to be only up to date with GCC 4.2.4 |
| - | Mixing gfortran and flang .obj's seem to work until I/O is involved. | + | Everything is peachy keen until someone references a symbol which is in anything g++ compiled using a newer > GCC 4.2.4 compiler. |
| - | $ more m.f | + | The moment you load libgfortran, it has a requirement for GCC_4.6 or better, and if our libgcc is already loaded things fail. |
| - | print*,'a= ',a() | + | |
| - | print*,' | + | |
| - | end | + | |
| - | $ more a.f | + | 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 |
| - | function a() | + | / |
| - | print*,' | + | 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. |
| - | a=5.0 | + | |
| - | return | + | |
| - | end | + | |
| - | $ more b.f | + | 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. |
| - | function b() | + | |
| - | print*,' | + | 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 |
| - | b=15.0 | + | I frankly think this in the long term is the cleaner solution. |
| - | return | + | |
| - | end | + | |
| - | $ flang -o m m.f a.f b.f | + | ====== Workaround we do ====== |
| - | $ ./m | + | |
| - | a= hello from a 5.000000 | + | |
| - | b= hello from b 15.00000 | + | |
| - | $ gfortran5 | + | In the ports world, we have papered over this problem by adding -Wl,-rpath=${_GCC_RUNTIME} or similar to force programs to link |
| - | $ ./m | + | against |
| - | / | + | Cmake does DTRT. |
| - | # compile with flang only a.f | + | ====== Why our workaround fails ====== |
| - | $ flang -c a.f -o a.o | + | The real problem comes when interpreters compiled with clang or gcc that do not use libgcc are run. The late binding that happens |
| - | clang-3.9: < | + | when a binary module is loaded that //does// reference a //libgcc// is what can trigger this bug //at run time// and this is independent |
| - | clang-3.9: < | + | of what our linker |
| - | clang-3.9: < | + | IFF a binary module is loaded with a libgcc reference it can pull in the //wrong// libgcc e.g. the base **/usr/lib/ |
| - | clang-3.9: < | + | |
| - | clang-3.9: < | + | |
| - | clang-3.9: < | + | |
| - | ocal/flang/lib' | + | |
| - | # compile | + | Usually it's a graphics package binary that is brought which are typically compiled |
| - | $ gfortran5 -c b.f -o b.o | + | needs libquadmath the two libraries are compatible enough. |
| - | $ flang -o m m.f a.o b.o | + | ====== 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 |
| - | %%> | + | requiring gfortran first which binds the " |
| + | 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 | ||
| + | to preload the //right// libgcc | ||
| - | / | + | ===== Final thoughts and future work ===== |
| - | %%> | + | |
| - | %%> | + | |
| - | clang-3.9: ESC[0; | + | |
| - | $ flang -o m m.f a.o b.o / | + | |
| - | $ ./m | + | |
| - | / | + | |
| - | $ gfortran -o m m.f a.o b.o / | + | N.B. at this time cmake does not realise flang is a valid fortran compiler. |
| - | a.o: In function `a_': | + | |
| - | / | + | |
| - | / | + | |
| - | /home/db/a.f:3: undefined reference to `f90io_sc_ch_ldw' | + | |
| - | /home/db/a.f:3: undefined reference to `f90io_ldw_end' | + | |
| - | collect2: error: ld returned 1 exit status | + | |
| - | $ gfortran5 -o m m.f a.o b.o / | + | Mixing gfortran and flang .obj's seem to work until I/O is involved. |
| - | %%// | + | I'll be investigating this further as time permits. |
| - | %%// | + | |
| - | collect2: error: ld returned 1 exit status | + | |
| - | + | ||
| - | # Removing | + | |
| - | + | ||
| - | $ cat a.b | + | |
| - | cat: a.b: No such file or directory | + | |
| - | $ cat a.f | + | |
| - | function a() | + | |
| - | + | ||
| - | C print*,'hello from a' | + | |
| - | a=5.0 | + | |
| - | return | + | |
| - | end | + | |
| - | $ cat b.f | + | |
| - | function b() | + | |
| - | + | ||
| - | C | + | |
| - | b=15.0 | + | |
| - | return | + | |
| - | end | + | |
| - | + | ||
| - | $ flang -c -o a.o a. | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | $ gfortran5 -c -o b.o b.f | + | |
| - | C | + | ---- |
| - | b=15.0 | + | |
| - | return | + | |
| - | end | + | |
| - | $ flang -c -o a.o a. | + | {{tag> |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | clang-3.9: ESC[0; | + | |
| - | $ gfortran5 -c -o b.o b.f | + | |
| - | $ flang -o m m.f a.o b.o | + | |
| - | $ ./m | + | |
| - | a= | + | |
| - | b= | + | |
| - | $ gfortran5 -o m m.f a.o b.o | + | |
| - | $ ./m | + | |
| - | / | + | |