升级GCC

From Gentoo Wiki
Jump to:navigation Jump to:search
This page is a translated version of the page Upgrading GCC and the translation is 23% complete.
Outdated translations are marked like this.
Other languages:

GCC upgrades should generally be handled gracefully with Portage and the usual Gentoo tools, see next section. If ever there are more involved updates that require user intervention, they should be accompanied by a corresponding news item, that should be read and followed.

请注意,降级GCC可能会产生不必要的副作用。有关一些常见问题,请参阅故障排除部分。

大多数GCC升级都像切换编译器版本一样简单(这里从5.4.0到6.4.0),并重建libtool

root #emerge --ask --oneshot sys-devel/gcc
root #gcc-config --list-profiles
[1] x86_64-pc-linux-gnu-5.4.0 *
[2] x86_64-pc-linux-gnu-6.4.0
root #gcc-config 2
root #source /etc/profile
root #emerge --ask --oneshot --usepkg=n sys-devel/libtool

检查当前版本号,然后卸载旧版本:

root #gcc --version
root #emerge --ask --depclean =sys-devel/gcc-5.4.0

享受新的编译器吧!

GCC 升级详解

GCC升级向来一直都被神秘化了,从“用户不需要再做任何事情”到“用户需要重新编译整个系统两次”。这些恐惧、疑惑、怀疑大多数都源自用户对ABI不兼容性的不够了解,这种困惑如今很少发生(一旦发生,它将被宣布)。首先先关注下 libtool

libtool

在升级 gcc 版本之后我们需要重新编译 libtool 的原因在于它的主要目的:“libtool” 是一个工具集,通过一个通用的接口聚合了特定平台的代码,允许应用程序使用共享库进行构建,无需应对平台相关的共享库。为能正确实现这一功能,libtool 脚本使用的各种库的定位都包含了 gcc 版本硬编码信息。

See bug #88596.

ABI changes

ABI 变化

ABI,或“应用程序二进制接口”是一个所有处理二进制的程序(包括编译器、汇编器、链接器和语言运行库支持)都会使用的接口(来源:GCC 二进制兼容性)。当二进制程序和库使用的 ABI 改变了之后,你将面临 链接错误或者程序错误的风险,除非你重新编译了所有的使用 C++ 代码的库。

When upgrading to GCC 4.1, or GCC 5.1, it is likely to encounter ABI issues. To prevent this, the revdep-rebuild command should be run against the libstdc++.so.5 library when moving from GCC 3 to GCC 4.1, or libstdc++.so.6 when moving from GCC 4 to GCC 5.1.

root #revdep-rebuild --library 'libstdc\+\+.so.6' -- --exclude gcc

那么为什么只有升级到GCC 3.4.0/4.1/5.1版本才需要这么做?这是因为在这之前的版本,GCC采用向下兼容的ABI,这使得你不需要重新编译软件和系统库。当然,我们不能永远保证这种兼容性。如果发生不兼容的情况,libstdc++.so 库将很可能也会升级到更高的版本。

The special case C++11 (and C++14)

While GCC (or more specifically, libstdc++) goes to great lengths to guarantee stability of the ABI, this guarantee does not extend to all parts of C++ within libstdc++. Formally, with versions starting from 3.4, GCC/libstdc++ only guarantees C++98/C++03 ABI stability and not more. This is crucial for packages that depend on C++11. GCC only makes C++11 ABI stability guarantees beginning with version 5.1. This means that switching (even minor) versions of gcc (say from 4.7.3 -> 4.7.4) might cause ABI breakage for binaries built from C++11 code.

For more information and some examples, see:

Downgrading GCC

For the aforementioned reasons, if downgrading GCC or choosing an older slot with gcc-config, it is necessary to run revdep-rebuild to catch libstdc++ consumers requiring newer symbols:

root #revdep-rebuild --library 'libstdc++.so.6' -- --exclude gcc

那些包是已知的要重新构建的?

下面表格给出的包都是需要重新安装的,如果的系统安装过这些包的话,那么请重新构建它们.

Package Rebuild needed because ...
dev-build/libtool libtool has hardcoded paths towards GCC internal libraries, see bug #88596.
root #emerge --ask --oneshot --usepkg=n --verbose sys-devel/libtool sys-devel/llvm sys-devel/clang

Some collections of packages need to be built with the same compiler (for example, the various qt-* packages). Such packages are usually bumped by package maintainers simultaneously, so they will always be built with the same GCC version. Cherry-picking re-installs on these packages might prove to be troublesome.

一些人认为当新版本的GCC安装好之后,他们需要重新编译他们系统上的已经安装过的应用,当然,这被认为是没有意义的,因为这里有很多应用在编译和构建的时候并没有用到GCC,所以更新不会影响到它们.

提示
This isn't necessary but is described here so people know how to do it thoroughly if they desire.

Some people swear that they need to rebuild every single package on their system when a new GCC version is made available. Of course, that doesn't make sense, since there are many applications that are not using GCC for their build and install process anyhow, so they would never be affected by such changes.

然而并不能说安装好新的GCC并更新应用这种做法是错误的,因为新的GCC版本往往会对进程提供更好的指令集支持,这些支持可能会在某些方面提高一些程序的性能,当然这些影响可能都是轻微的,甚至在某些方面(尤其是特别消耗CPU的应用)并不会提高性能.

Apart from such "benign" benefits, rebuilding everything from scratch may be necessary in some cases to fix problems that don't seem to have any obvious cause.

Some software problems are inherently difficult to diagnose and yet could be solved by simply rebuilding one or more appropriate packages. If such a problem has arisen following a GCC upgrade and persists after using the revdep-rebuild approach described above (and after rebuilding any other obviously relevant packages), a complete system rebuild may be the answer.

The "safest" but slowest way to accomplish this is to use the --emptytree (-e) option of emerge to rebuild the system set and then the world set:

root #emerge --ask --emptytree --usepkg=n @system
root #emerge --ask --emptytree --usepkg=n @world

Try this approach before reporting bugs that might have been caused by a GCC upgrade.

附注
The commands above will cause the packages in the system set to be rebuilt twice, which is necessary to be absolutely certain that every package gets built in the same presumably "problem-free" environment. Any problems that remain after doing this are due to either "genuine bugs" that should be reported or poor system configuration.

故障排除

重建 boost

If dev-libs/boost needs to be rebuilt, one will get the following error message:

root #emerge ...
 
checking for the Boost _____ library... no
configure: error: cannot find the flags to link with Boost _____

可以通过以下方式重建:

root #emerge --ask --oneshot --usepkg=n --verbose dev-libs/boost

libstdc++.so.6: version `GLIBCXX_3.4.15' 未找到

在升级过程中,你或许会遇到以下面这些错误:

代码 GLIBCXX_x.y.z 未找到
cmake_bootstrap_28021_test: /usr/lib/gcc/i486-pc-linux-gnu/4.1.2/libstdc++.so.6:
version `GLIBCXX_3.4.11' not found

这意味着你正在用一个"较老版本"(新版本指的是那些已经构建好这些依赖库的版本)的GCC来构建这些包.请记住所谓的C++ABI 向前兼容指的是:假设你可以用某个版本的GCC成功构建程序和连接库文件,那么你可以用比这个版本更高版本GCC去构建这些程序,而不是用更低版本GCC来构建这些程序.

要重新构建所有以来 libstdc++的包,你可以执行下面的脚本

undefined reference to `__cxa_call_terminate@CXXABI_1.3.15'

This is usually a result of compiling a package that had its dependencies built with a newer GCC version than with the current one selected. An example output might be:

代码 undefined reference to __cxa_call_terminate@CXXABI_1.3.15
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: /usr/lib64/libgtest.so: undefined reference to `__cxa_call_terminate@CXXABI_1.3.15'

What this means is the package that is emerging is building with, for example, GCC 13 but the package that provides libgtest.so was built with a newer version of GCC, 14 in this case.

The solution to this problem is rather simple but can be hard to figure out if the package providing the file is unknown. Portage supports emerging file paths directly so running emerge -1 /path/to/file.so might detect the file.

In the example, try emerging /usr/lib64/libgtest.so

root #emerge -1a /usr/lib64/libgtest.so
Calculating dependencies -
 
!!! '/usr/lib/libgtest.so' is not claimed by any package.
... done!

Unfortunately the file needed was not claimed, but another utility exists to find files installed by packages, Pfl. Using e-file, it is possible to find the package that installs the needed file.

user $e-file libgtest.so
...
[I] dev-cpp/gtest
        Seen Versions:          1.13.0 1.14.0
        Portage Versions:       1.13.0 1.14.0 9999
        Installed Versions:     1.14.0(Fri Nov 24 04:35:00 2023)
        Homepage:               https://github.com/google/googletest
        Description:            Google C++ Testing Framework
        Matched Files:          /usr/lib/libgtest.so; /usr/lib64/libgtest.so
...

In this case, dev-cpp/gtest is causing the build issue, re-merging it with:

root #emerge --ask --oneshot dev-cpp/gtest

should fix the issue and allow the continuation of emerging the original package.

附注
For larger packages, it is likely to encounter this more than once while rebuilding a package with a lower version of GCC, keep following the above steps to eventually succeed in recompiling the package with GCC 13

另请参阅

External resources

参考