web-dev-qa-db-ja.com

ライブラリを作成するためのranlib、ar、ldの違いは何ですか

* .oファイルからc ++/unixでライブラリを作成するために、プロジェクト(レガシーコード)で2つの異なる方法に気づきました。

ar qc libgraphics.a *.o
ranlib libgraphics.a

そして

ld -r -o libgraphics.a *.o

2つのアプローチの違いは何ですか、そしてどちらがどの目的に使用されますか?

20
R71

ar

Linuxでは、 ar はGNU汎用アーカイバです。(他のUnix-にはarの非GNUバリアントがあります- OSのように)オプションc

ar c... archive-name file...

file...のコピーを含むアーカイブを作成します。 archive-nameには従来、拡張子.aが付いていますが、必ずしもそうではありません(for archive)。各file...は、オブジェクトファイルである必要はなく、どのような種類のファイルでもかまいません。

アーカイブされたファイルがすべてオブジェクトファイルである場合、通常はアーカイブを使用して、選択したオブジェクトファイルをプログラムまたはDSO(動的共有オブジェクト)のリンケージに配信します。この場合、archive-nameにも従来どおりプレフィックスlibが付与されます。 libfoo.a。これは、リンカーオプション-lfooを介して候補リンカー入力ファイルとして検出できるようにするためです。

リンカ入力ファイルとして使用され、libfoo.aは通常静的ライブラリと呼ばれます。アーカイブlibfoo.aは、DSO libfoo.soとほぼ同じものであり、通常はと呼ばれます。動的/共有ライブラリ、そしてこれに基づいて誤った期待を構築する。実際、「静的ライブラリ」と「動的ライブラリ」はまったく同じものではなく、まったく異なる方法で連携して使用されます。

顕著な違いは、静的ライブラリはlinkerではなくarによって生成されることです。したがって、リンケージは発生せず、シンボル解決も発生しません。アーカイブされたオブジェクトファイルは変更されていません。バッグに入れられているだけです。

isリンカによって生成された何か(プログラムやDSOなど)のリンケージにアーカイブが入力されると、リンカはバッグを調べて、定義を提供するオブジェクトファイルがあるかどうかを確認しますリンケージの早い段階で発生した未解決のシンボル参照。見つかった場合は、それらのオブジェクトファイルをバッグから抽出し、リンカコマンドラインで個別に指定した場合とまったく同じようにアーカイブに名前を付けた場合とまったく同じように、themを出力ファイルにリンクします。したがって、リンケージにおけるアーカイブの全体的な役割は、リンカがリンケージを実行するために必要なファイルを選択できるオブジェクトファイルのバッグとしての役割を果たします。

デフォルトでは、GNU arは、出力アーカイブをリンカー入力として使用できるようにします。これは、偽の「ファイル」を魔法の偽のファイル名でアーカイブに追加します。フォニーファイルは、アーカイブ内のオブジェクトファイルによって定義されたグローバルシンボルからアーカイブ内のそれらのオブジェクトファイルの名前と位置までリンカがルックアップテーブルとして読み取ることができるコンテンツを書き込みます。このルックアップテーブルにより、リンカーを使用してアーカイブを調べ、手元にある未解決のシンボル参照を定義するオブジェクトファイルを特定します。

q(= quick)オプションを使用して、このルックアップテーブルの作成または更新を抑制できます。実際には、独自のarの例で使用しています-また、(大文字)S(= no symbol table)オプションを使用します。また、arを呼び出して、何らかの理由で(最新の)シンボルテーブルを持たないアーカイブを作成または更新する場合は、sオプションを使用してアーカイブに与えることができます。

ranlib

ranlib はライブラリをまったく作成しません。 Linuxでは、ranlibはレガシープログラムであり、(最新の)シンボルテーブルがarアーカイブにない場合は、それに追加します。これはar sとまったく同じですが、GNU arです。歴史的に、arがシンボルテーブル自体を生成するように装備される前は、ranlibは、マジックフォニーファイルをアーカイブに挿入して、リンカーがオブジェクトファイルをそこから選択できるようにする陰謀でした。GNU以外のUnixライクなOSでは、ranlibが必要になる場合がありますあなたの例:

ar qc libgraphics.a *.o
ranlib libgraphics.a

言う:

  • libgraphics.aを作成します。現在のディレクトリにあるすべての*.oファイルを、シンボルテーブルなしでアーカイブに追加します。
  • 次に、libgraphics.aにシンボルテーブルを追加します

Linuxでは、これは次と同じ正味の効果があります。

ar cr libgraphics.a *.o

ar qc libgraphics.a *.o自体は、シンボルテーブルがないため、リンカーが使用できないアーカイブを作成します。

ld

あなたの例:

ld -r -o libgraphics.a *.o

実際にはまったく正統ではありません。これは、linkerldを使用してmergedオブジェクトファイルを作成し、複数の入力ファイルを単一の出力オブジェクトファイルにリンクすることで、まれに入力ファイルを指定して、どのシンボル解決が行われたか可能な限り-r(= relocatable オプションは、入力を可能な限りリンクすることにより、(プログラムまたはDSOではなく)オブジェクトファイルターゲットを生成するようにリンカーに指示します。未定義のシンボル参照が出力ファイルに残っている場合でも、リンクに失敗しない可能性があります。この使用法は部分リンクと呼ばれます。

ld -r ...の出力ファイルはオブジェクトファイルであり、ararchiveではなく、出力ファイル名を指定検索arアーカイブのように、それを作成しません。したがって、あなたの例は欺瞞を示しています。この:

ld -r -o graphics.o *.o

正直になります。 ELFオブジェクトファイルがlibgraphics.aと呼ばれ、その名前または-lgraphicsによってリンケージに入力されている場合でも、そのような詐欺の目的が何であるかは私にはわかりません。リンカは、それをarアーカイブではなくELFオブジェクトファイルとして正しく識別し、コマンドラインでオブジェクトファイルを使用するのと同じように使用します。無条件に出力ファイルにリンクしますが、入力のポイントは本物のアーカイブは、アーカイブメンバーをリンクすることです参照されている場合のみ。たぶん、あなたはここで悪質なリンクの例を持っています。

まとめ...

one通常はlibraryと呼ばれるものを生成する方法を実際に見ただけであり、それがいわゆるstatic libraryの生成です。 、いくつかのオブジェクトファイルをアーカイブし、シンボルテーブルをアーカイブに配置します。

また、従来はlibraryと呼ばれていた他の最も重要な種類のオブジェクト、つまり動的共有オブジェクト/共有ライブラリ/動的ライブラリを生成する方法はまったく見ていません。

プログラムと同様に、DSOはthe linkerによって生成されます。プログラムとDSOは、OSローダーが理解し、実行中のプロセスをアセンブルするために使用できるELFバイナリのバリアントです。通常、GCCフロントエンド(gccg++gfortranなど)の1つを介してリンカーを呼び出します。

プログラムのリンク:

gcc -o prog file.o ... -Ldir ... -lfoo ...

DSOのリンク:

gcc -shared -o libbar.so file.o ... -Ldir ... -lfoo ...

他のプログラムまたはDSOをリンクしている場合、共有ライブラリと静的ライブラリの両方を、統一された-lfooプロトコルによってリンカーに提供できます。このオプションは、指定された検索ディレクトリまたはデフォルトの検索ディレクトリをスキャンしてlibfoo.soまたはlibfoo.aを検索するようにリンカーに指示します。デフォルトでは、どちらかが見つかると、そのファイルをリンケージに入力します。同じ検索ディレクトリで両方が見つかった場合は、libfoo.soが優先されます。 libfoo.so、が選択されている場合、リンカーはそのDSOを、作成しているプログラムまたはDSOのランタイム依存関係リストに追加します。 libfoo.aが選択されている場合、リンカはアーカイブをオブジェクトファイルの選択として使用し、必要に応じて出力ファイルにリンクします。 libfoo.a自体に対する実行時の依存関係はありません。プロセスにマッピングすることはできません。 OSローダーには何の意味もありません。

29
Mike Kinghan