Mpfr4-update-guide
dev-libs/mpfr version 4 introduced an ABI and soname change that has the potential of breaking the compiler toolchain. In order to minimize potential problems it is strongly recommended to rebuild dev-libs/mpc and sys-devel/gcc immediately after mpfr.
The problem
libmpfr.so is used by libmpc.so (provided by dev-libs/mpc), as well as internal executables (e.g. cc1, cc1plus) of sys-devel/gcc. Appropriate subslots in mpfr and slot-operators in dependencies in mpc and gcc will cause a rebuild of mpc and gcc after an upgrade of mpfr.
However, after dev-libs/mpfr version 4 is installed and dev-libs/mpc rebuilt, but before sys-devel/gcc is rebuilt, the gcc compiler will be in an inconsistent state wherein symbols from incorrect library versions of mpfr might get used. This can result in segmentation faults and internal compiler errors. It is therefore important to rebuild gcc immmediately after mpc.
Preparatory steps
Make sure that you have enabled the "preserved libs" feature:
user $
emerge --info | grep preserve-libs
FEATURES="... preserve-libs ..."
Detailed upgrade steps
Update and rebuild all affected packages as atomically as possible:
root #
emerge --ask --oneshot ">=dev-libs/mpfr-4" dev-libs/mpc sys-devel/gcc
Check that cc1 is dynamically linked against the new mpfr version. First identify the absolute path of the cc1 executable by running
user $
qlist gcc | grep -P "cc1$"
/usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1
Then, use ldd to list all dynamically linked libraries:
user $
ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr
libmpfr.so.6 => /usr/lib64/libmpfr.so.6 (0x00007fe37e9df000)
You might want to use this ldd invocation to list all dynamically linked libraries for any installed gcc compilers:
user $
for i in /usr/libexec/gcc/*-pc-linux-gnu/*/cc1; do echo $i; ldd $i | grep mpfr ; done;
/usr/libexec/gcc/i686-pc-linux-gnu/6.4.0/cc1 libmpfr.so.6 => /usr/lib/libmpfr.so.6 (0xf7747000) /usr/libexec/gcc/i686-pc-linux-gnu/7.3.0/cc1 libmpfr.so.6 => /usr/lib/libmpfr.so.6 (0xf7b70000) /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 libmpfr.so.6 => /usr/lib/libmpfr.so.6 (0xf7797000)
You should only see libmpfr.so.6 and not the old libmpfr.so.4 in the output of ldd.
Troubleshooting
Mixed linkage
If the ldd command in the previous step returns two library versions,
user $
ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr
libmpfr.so.4 => /usr/lib64/libmpfr.so.4 (0x00007fe37fa02000) libmpfr.so.6 => /usr/lib64/libmpfr.so.6 (0x00007fe37e9df000)
You have rebuilt sys-libs/mpc against the new mpfr version, but not sys-devel/gcc (or vice versa). Rebuild the mpc library and the gcc executable immediately:
root #
emerge --ask --oneshot dev-libs/mpc sys-devel/gcc
Warning about preserved libraries
If you get the following warning you had the preserve-libs feature disabled:
* Messages for package dev-libs/mpfr-4.0.1:
* Old versions of installed libraries were detected on your system.
* In order to avoid breaking packages that depend on these old libs,
* the libraries are not being removed. You need to run revdep-rebuild
* in order to remove these old dependencies. If you do not have this
* helper program, simply emerge the 'gentoolkit' package.
*
* # revdep-rebuild --library '/usr/lib64/libmpfr.so.4' && rm '/usr/lib64/libmpfr.so.4
Follow above instructions immediately and check that the link interface is consistent before you remove the libmpfr.so.4 library. ldd must return exactly one mpfr library:
user $
ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr
libmpfr.so.6 => /usr/lib64/libmpfr.so.6 (0x00007fe37e9df000)
Missing mpfr-4 library
If you encounter internal compiler errors of the form
/usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1plus: error while loading shared libraries: libmpfr.so.4: cannot open shared object file: No such file or directory
The libmpfr.so.4 library got removed before mpc and gcc had been both rebuilt. The preserve-libs feature and the manual check mentioned above should have prevented this.
There is a workaround to bring the system back into working order:
This is a very fragile workaround and only meant as last resort. Under normal circumstances, you should refrain from changing sonames in such manner.
root #
ln -s /usr/lib64/libmpfr.so.6 /usr/lib64/libmpfr.so.4
root #
emerge --ask --oneshot dev-libs/mpc sys-devel/gcc
root #
rm /usr/lib64/libmpfr.so.4
root #
revdep-rebuild
Make sure that the link interface is consistent after above steps:
user $
ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr
libmpfr.so.6 => /usr/lib64/libmpfr.so.6 (0x00007fe37e9df000)