web-dev-qa-db-ja.com

共有ライブラリの複数のバージョンをインストールできないのはなぜですか?

特定のプログラムがライブラリバージョンx.yと別のプログラムがx.zに依存する場合がよくありますが、私が知る限り、x.yとx.zの両方をインストールできるパッケージマネージャーはありません。場合によっては、両方のメジャーバージョン(同時にインストールできるqt4とqt5など)が許可されますが、(一見)マイナーバージョンは許可されません。

どうしてこれなの?のように、それを妨げる制限要因は何ですか?私は、この一見有用な機能を許可しない正当な理由があるに違いないと思います。たとえば、共有オブジェクトをロードするときにロードするバージョンを示すフィールドがないため、Linuxがロードするものを決定する方法を知る方法はありませんか?それとも理由は本当にないのですか?とにかく、すべてのマイナーバージョンは互換性があると思われますか?

10
Tyler

実際、正しく実行されていれば、共有ライブラリの複数のバージョンをインストールできます。

共有ライブラリは通常、次のように命名されます。

lib<name>.so.<api-version>.<minor>

次に、次の名前でライブラリへのシンボリックリンクがあります。

lib<name>.so
lib<name>.so.<api-version>

開発者がライブラリをリンクしてバイナリを生成する場合、リンカーが検出するのは.soで終わるファイル名です。実際、特定の<name>に同時にインストールできるのは1つだけですが、これは、開発者が複数の異なるバージョンのライブラリを同時にターゲットにできないことを意味します。パッケージマネージャーでは、この.soシンボリックリンクは、開発者のみがインストールする必要がある別の-devパッケージの一部です。

リンカが.soで終わる名前のファイルを見つけて使用すると、そのライブラリ内でsonameというフィールドを探します。 sonameは、生成されるバイナリに埋め込むファイル名をリンカーに通知するため、実行時にどのファイル名が検索されるかを通知します。 sonameはlib<name>.so.<api-version>に設定されることになっています。

したがって、実行時に、動的リンカーはlib<name>.so.<api-version>を探してそれを使用します。

意図は次のとおりです。

  • <minor>のアップグレードによってライブラリのAPIが変更されることはありません。<minor>が上位バージョンに移行した場合、すべてのバイナリを新しいバージョンにアップグレードしても安全です。バイナリはすべて、lib<name>.so.<api-version>という名前でライブラリを探しています。これは、最新のインストール済みlib<name>.so.<api-version>.<minor>へのシンボリックリンクであるため、アップグレードされます。
  • <api-version>アップグレードはライブラリのAPIを変更するため、既存のバイナリアプリケーションに新しいバージョンを使用させるのは安全ではありません。 <api-version>が変更された場合、これらのアプリケーションはlib<name>.so.<api-version>という名前を探していますが、<api-version>の値が異なるため、新しいバージョンは取得されません。

ライブラリを使用するすべてのバイナリを含むディストリビューション全体は通常、配布前にすべてのライブラリの一貫したバージョンを使用するようにコンパイルされるため、パッケージマネージャは、同じライブラリの複数のバージョンを同じ配布バージョンにパッケージ化しないことがよくあります。リリースされました。すべてに一貫性があり、ディストリビューションのすべてが他のすべてと互換性があることを確認することは、ディストリビューターのワークロードの大きな部分です。

ただし、システムをディストリビューションのあるバージョンから別のバージョンにアップグレードしても、古いライブラリバージョンを必要とする古いパッケージがいくつかある場合は、簡単にライブラリの複数のバージョンになる可能性があります。例:

  • libmysqlclient16 古いDebianから、libmysqlclient.so.16.0.0およびsymlink libmysqlclient.so.16が含まれています。
  • libmysqlclient18 現在のDebianから、libmysqlclient.so.18.0.0およびsymlink libmysqlclient.so.18が含まれています。
13
Celada

この機能は禁止されていません。ほとんどのライブラリの番号付けが機能する方法と、パッケージ名の変更の不便さのため、これはあまり一般的ではありません。

ドット付きバージョン番号スキームX.Y.Zを使用する場合。 「マイクロ」バージョンZはバグ修正で頻繁に変更され、「マイナー」番号Yは後方互換性変更で変更され、「メジャー」バージョン番号XはAPI変更で変更する必要があります(時にはメジャー追加で変更します)機能性)。

最新のバグを修正したくない理由は決してないはずです。また、下位互換性のある変更によってソフトウェアが壊れることもないはずです。

ライブラリがそのように開発されている場合、常にX.Y.ZをX.(Y + m)。(Z + n)で置き換えることができるはずです。任意の与えられたmとnに対して。つまりライブラリを同じメジャー番号シリーズの最新のものといつでも置き換えることができるはずです。また、ライブラリ開発者が注意深く、次のメジャー番号に互換性がある場合(たとえば、廃止予定であるが、まだ削除していないことによる)、次のメジャー番号を使用することもできます。

パッケージ開発者にとって、これは、名前を1つだけ、または番号なしの名前で使用して、パッケージを更新するだけで最新バージョンを提供できることを意味します。ライブラリをパッケージabc2で出荷する場合、abc2依存する独自のソフトウェアを移動するためにフープを通過する必要があり、abc3を使用するようにアップグレードします。時々移行パッケージで。依存しているほとんどのパッケージで機能する場合は、ライブラリからメジャーバージョン番号を除外する方が便利です。したがって、abc2abc3の両方をディストリビューションで利用できるようにする必要がある場合でも、abc3はしばしばabcと呼ばれます(abc2が呼び出されたのと同じように) abc3がまだなかった場合)、ディストリビューション内でabc2に依存するパッケージがなくなるとすぐに、abc2を完全に削除することが可能になります。

番号付けスキームは一律ではありませんが、そのようなスキームの使用方法に関する情報をインターネットで広めることと、ライブラリーのユーザー(ディストリビューション開発者を含む)から後方互換性などの重要なことを明確にせずに圧力をかけるようになったことでしか想像できません。ライブラリに含まれているCHANGESファイルを読む必要があることは、これがより一般的になっていることに貢献しています。

ライブラリではない反例の1つに、python intpreterがあります。これは、共有オブジェクトとマイナー番号の変更時のピクル化形式では互換性がありません。したがって、python(2.7シリーズの最新)とpython3(現在のpython3.4シリーズの最新)のパッケージと、python 2.6の明示的なパッケージが表示されます(あまり一般的ではありません)およびpython 3.3。

4
Anthon