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 100% complete.

GCC のアップグレードは、一般的には Portage と通常の Gentoo ツールで首尾よく処理されるはずです。次の節を参照してください。もしユーザの介入を必要とするようなより込み入った更新があるとすれば、それに対応するニュース項目が伴うはずですので、読んでそれに従ってください。

GCC のダウングレードには望まない副作用があることがあります。よく報告される問題についてはトラブルシューティングの節を参照してください。

GCC アップグレードのクイックガイド

たいていの GCC のアップグレードは、コンパイラのバージョンを (ここでは 10.3.0 から 11.2.0 に) 変更することと、dev-build/libtool を再ビルドするだけで済みます:

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

現在のバージョン番号を確認してから、旧バージョンをアンインストールしましょう:

root #gcc --version
root #emerge --ask --depclean sys-devel/gcc:10.3.0

新しいコンパイラを楽しんでください!

GCC アップグレードの詳細なガイド

GCC のアップグレードはいつも謎めかされてきました。というのも、「ほかには何もしなくていいよ」というものから、「システム全体の再ビルドを 2 度しなければならないよ」というものまで、言われることに幅があるからです。こうした不確実さは ABI の非互換についての混乱から引き起こされていましたが、今日ではこれが問題を発生させることはめったにありません。

libtool

ではなぜ、 gcc のバージョンをアップグレードした後には libtool を再ビルドする必要があるのでしょうか? それは、libtool は、プラットフォーム特有のコードを一般化したインターフェイスに集約することで、アプリケーションソフトがプラットフォーム特有の側面を意識することなく共用ライブラリを利用可能にするものだからです。この機能を適切に実現するには、libtool のスクリプトは、様々な場所にある共用ライブラリを見つけ出して、その中にハードコーディングされた gcc のバージョン情報を得なければなりません。

bug #88596 を参照してください。

ABI の変更

GCC 5.1 より前

ABI (Application Binary Interface) は、コンパイラ、アセンブラ、リンカ、そして言語ランタイムサポート (情報源: GCC Binary Compatibility) を含む、プログラムのバイナリ表現を扱うすべてのツールによって使用される規則の集まりです。バイナリアプリケーションやライブラリに使用されている ABI が変更されると、C++ のコードを用いているすべてのライブラリをビルドしなおさない限り、リンカのエラーやプログラムの誤動作が発生する危険性があります。

GCC 4.1 や GCC 5.1 へアップグレードする場合、おそらく ABI の問題に直面することになるでしょう。これを防ぐには、GCC 3 から GCC 4.1 へのアップグレードの場合は libstdc++.so.5 に、GCC 4 から GCC 5.1 へのアップグレードの場合は libstdc++.so.6 に対して revdep-rebuild コマンドを実行する必要があります。

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

これは GCC 4.1/5.1 までにおいてのみ必要です。それらのバージョン以降、GCC はアプリケーションやライブラリの再ビルドの必要性をなくす前方互換の ABI を採用しているからです。もちろん保証は無期限に与えられるものではありえませんが、非互換が再び生じたら、私たちはそれをここへ確実に文書化し、またニュース項目をリリースします。その場合、おそらく libstdc++.so ライブラリのバージョンは増加していることでしょう。

C++11 (および C++14) 特有の事象

GCC(より具体的には、libstdc++)は、ABIの安定性を保証するために労を惜しみませんが、この保証はlibstdc++の中のC++のすべての部分に及ぶわけではありません。公式には、3.4以降のバージョンにおいて、GCC/libstdc++はC++98/C++03 ABIの安定性のみを保証し、それ以上ではありません。このことはC++11に依存するパッケージに関しては重大です。GCCはC++11 ABIの安定性の保証をバージョン5.1以降でのみ提供しています。これは、gccのバージョン(マイナーバージョンであっても)の変更(4.7.3 -> 4.7.4など)はC++11のコードからビルドされたバイナリにABI破壊をもたらす、ということを意味しています。

さらなる情報や実例は、以下を見てください:

GCC をダウングレードする

先に書いた理由により、GCC をダウングレードする、または gcc-config で古いスロットを選択する場合は、新しいシンボルを必要とする libstdc++ の利用者を見つけるために、revdep-rebuild を実行する必要があります:

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

どのパッケージで再ビルドが必要とされているか?

以下の表は、インストールされていれば再ビルドが必要なパッケージとその理由を表したものです。

パッケージ 再ビルドが必要な理由
sys-devel/libtool libtool は GCC の内部ライブラリへのパスをハードコードしています、bug #88596 を参照してください。
root #emerge --ask --oneshot --usepkg=n --verbose dev-build/libtool

いくつかのパッケージ群は同じコンパイラを用いてビルドする必要があります(たとえば、さまざまなqt-*パッケージ)。こうしたパッケージについては通常パッケージメンテナが同時にbumpを行っているため、常に同じバージョンのGCCでビルドされるようになっています。これらのパッケージからの「つまみ食い」的な再インストールはトラブルを引き起こすことがしばしばです。

すべてをリビルドする

ヒント
これは必要ではありませんが、どうしてもやりたい場合にどうすればいいのか分かるように、ここに記載しています。

「GCC の新たなバージョンを入れたときには、各パッケージのすべてを再ビルドせねばならない」と心に誓っている人もいます。もちろん、そうする意味はありません。なぜなら、ビルドやインストールに GCC を一切使わないアプリケーションソフトもたくさんあり、そうしたソフトウェアには影響がないからです。

そうはいっても、彼らが完全に間違っているかというと、そうでもありません: 新しいバージョンの GCC ではしばしば、プロセッサの命令セットのサポートが向上していることがあります。そうすると、より良い性能が得られるアプリケーションソフトもあるかもしれません。

そうした"穏健な"利点とは別に、場合によっては明確な原因がわからない問題を解決するためにすべてを1からリビルドすることが必要になることがあるかもしれません。

いくつかのソフトウェアの問題は本質的に診断が困難ですが、それでも単に1つまたは複数の適切なパッケージをリビルドすることで解決できることがあります。そのような問題がGCCのアップグレード後に起こり、前に説明したrevdep-rebuildを使ったアプローチ(と他の明らかに関係のあるパッケージのリビルド)の後にも続いている場合、システムの完全なリビルドが答えかもしれません。

これを実現する "最も安全" だが最も遅い方法は、emerge の --emptytree (-e) オプションを system 集合および world 集合のリビルドに使うことです:

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

GCC のアップグレードによって引き起こされたかもしれないバグを報告する前に、このアプローチを試してみてください。

メモ
上のコマンドでは system 集合のパッケージが 2 回リビルドされます。これは、すべてのパッケージが絶対確実に同じおそらくは "問題のない" 環境でビルドされるようにするために必要なことです。これを実行した後に残った問題はすべて、報告されるべき "正真正銘のバグ" か、あるいはまずいシステム設定によるものです。

トラブルシューティング

Boost のリビルド

以下のエラーメッセージが出た場合、dev-libs/boostをリビルドする必要があります:

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' not found

アップデートの途中、以下のようなエラーに遭遇することがあります:

コード GLIBCXX_x.y.z not found
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 が使用できる、ということを保証するに過ぎません。

libstdc++ に依存しているすべてのパッケージを再ビルドするには、上の revdep-rebuild説明を参照してください。

undefined reference to `__cxa_call_terminate@CXXABI_1.3.15'

これは通常は、現在選択されているものより新しい GCC のバージョンでビルドされたパッケージを依存として持つパッケージをコンパイルしようとした結果です。出力例としては:

コード 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'

これが意味しているのは、emerge しようとしているパッケージは例えば GCC 13 でビルドされているが、libgtest.so を提供するパッケージはより新しいバージョンの GCC、今回の場合は 14 でビルドされている、ということです。

この問題に対する解決策は比較的シンプルですが、問題のファイルを提供するパッケージが不明な場合、それを探し出すのは難しいかもしれません。Portage はファイルパスで直接 emerge するのに対応しているので、emerge -1 /path/to/file.so を実行してファイルを検出できることがあります。

この例では、/usr/lib64/libgtest.so を emerge してみてください:

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

残念ながら必要なファイルはどのパッケージにも所有されていませんでしたが、パッケージによってインストールされたファイルを見つけるためのもう一つのユーティリティ、Pfl が存在します。e-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
...

この場合は dev-cpp/gtest がビルドの問題を発生させています。以下で再 emerge することで:

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

問題を解決し、元のパッケージの emerge を続行できるはずです。

メモ
大きなパッケージでは、以前のバージョンの GCC でパッケージを再ビルド中、何度もこの問題に遭遇しやすいでしょう。上の手順に従い続けていれば、いずれパッケージを GCC 13 でコンパイルするのに成功するでしょう。

関連項目

外部資料

参照