158

多くの静的ライブラリ(a_1-a_n)に依存する小さなコードがあります。そのコードを静的ライブラリにパッケージ化して、他の人が利用できるようにしたいと思います。

私の静的ライブラリは、Xと呼びましょう。正常にコンパイルされます。

Xの関数を使用する簡単なサンプルプログラムを作成しましたが、それをXにリンクしようとすると、ライブラリa_1--a_nからシンボルが欠落しているというエラーが多数発生します。

XとXに必要なすべての機能(a_1-a_nから選択されたビット)を含む新しい静的ライブラリYを作成して、プログラムをリンクするためにYだけを配布できるようにする方法はありますか?


アップデート:

arですべてをダンプし、1つのメガライブラリを作成することを検討しましたが、不要なシンボルが多数含まれることになります(すべての.oファイルは約700 MBですが、静的にリンクされた実行可能ファイルは7です。 MB)。実際に必要なものだけを含める良い方法はありますか?


これは、複数のC / C ++ライブラリを1つに結合する方法と密接に関連しているように見えますか?。

4

6 に答える 6

91

静的ライブラリは他の静的ライブラリとリンクしません。これを行う唯一の方法は、ライブラリアン/アーカイバツール(たとえば、Linuxではar)を使用して、複数のライブラリを連結することにより、単一の新しい静的ライブラリを作成することです。

編集:あなたの更新に応じて、必要なシンボルのみを選択することを私が知っている唯一の方法は、それらを含む.oファイルのサブセットからライブラリを手動で作成することです。これは難しく、時間がかかり、エラーが発生しやすくなります。私はこれを行うのに役立つツールを知りませんが(それらが存在しないとは言えません)、それを作成することは非常に興味深いプロジェクトになります。

于 2010-01-28T20:25:34.350 に答える
50

Visual Studioを使用している場合は、はい、これを行うことができます。

Visual Studioに付属のライブラリビルダーツールを使用すると、コマンドラインでライブラリを結合できます。ただし、ビジュアルエディタでこれを行う方法はわかりません。

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib
于 2010-01-28T20:31:26.663 に答える
22

LinuxまたはMingWで、GNUツールチェーンを使用する場合:

ar -M <<EOM
    CREATE libab.a
    ADDLIB liba.a
    ADDLIB libb.a
    SAVE
    END
EOM
ranlib libab.a

liba.aとを削除しない場合はlibb.a、「薄いアーカイブ」を作成できます。

ar crsT libab.a liba.a libb.a

Windowsの場合、MSVCツールチェーンを使用します。

lib.exe /OUT:libab.lib liba.lib libb.lib
于 2014-12-28T11:33:48.857 に答える
13

静的ライブラリは、.oオブジェクトファイルの単なるアーカイブです。ar(Unixを想定して)それらを抽出し、 1つの大きなライブラリにパックし直します。

于 2010-01-28T20:28:37.997 に答える
8

残りを読む前に注意してください:ここに示されているシェルスクリプトは確かに安全に使用できず、十分にテストされています。自己責任!

そのタスクを実行するためにbashスクリプトを作成しました。ライブラリがlib1であり、いくつかのシンボルを含める必要があるのがlib2であるとします。スクリプトはループで実行され、lib1の未定義のシンボルがlib2にあるかどうかを最初にチェックします。次に、対応するオブジェクトファイルをlib2から抽出しar、名前を少し変更して、lib1に配置します。lib2からインクルードしたものには、まだ含まれていないlib2からの他のものが必要であるため、欠落しているシンボルがさらにある可能性があります。そのため、ループを再度実行する必要があります。ループを何度か通過した後、変更がなくなった場合、つまりlib2のオブジェクトファイルがlib1に追加されていない場合、ループを停止できます。

含まれているシンボルはまだによって未定義として報告されるnmため、ループを停止できるかどうかを判断するために、lib1自体に追加されたオブジェクトファイルを追跡していることに注意してください。

#! /bin/bash

lib1="$1"
lib2="$2"

if [ ! -e $lib1.backup ]; then
    echo backing up
    cp $lib1 $lib1.backup
fi

remove_later=""

new_tmp_file() {
    file=$(mktemp)
    remove_later="$remove_later $file"
    eval $1=$file
}
remove_tmp_files() {
    rm $remove_later
}
trap remove_tmp_files EXIT

find_symbols() {
    nm $1 $2 | cut -c20- | sort | uniq 
}

new_tmp_file lib2symbols
new_tmp_file currsymbols

nm $lib2 -s --defined-only > $lib2symbols

prefix="xyz_import_"
pass=0
while true; do
    ((pass++))
    echo "Starting pass #$pass"
    curr=$lib1
    find_symbols $curr "--undefined-only" > $currsymbols
    changed=0
    for sym in $(cat $currsymbols); do
        for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
            echo "  Found $sym in $obj."
            if [ -e "$prefix$obj" ]; then continue; fi
            echo "    -> Adding $obj to $lib1"
            ar x $lib2 $obj
            mv $obj "$prefix$obj"
            ar -r -s $lib1 "$prefix$obj"
            remove_later="$remove_later $prefix$obj"
            ((changed=changed+1))
        done
    done
    echo "Found $changed changes in pass #$pass"

    if [[ $changed == 0 ]]; then break; fi
done

私はそのスクリプトに名前を付けたlibcompので、たとえば次のように呼び出すことができます

./libcomp libmylib.a libwhatever.a

ここで、libwhateverは、シンボルを含める場所です。ただし、最初にすべてを別のディレクトリにコピーするのが最も安全だと思います。私は自分のスクリプトをあまり信用しませんでした(ただし、それは私にとってはうまくいきました。それを使ってlibgsl.aを数値ライブラリに含め、-lgslコンパイラスイッチを省略できます)。

于 2015-01-15T23:48:49.437 に答える
7

プロジェクトプロパティの代わりにLink Library Dependencies、VisualStudioでライブラリをリンクする別の方法があります。

  1. 他のライブラリと結合するライブラリ(X)のプロジェクトを開きます。
  2. Xと組み合わせたい他のライブラリを追加します(右クリック、Add Existing Item...)。
  3. それらのプロパティに移動しItem TypeLibrary

これには、実行したかのようにXの他のライブラリが含まれます

lib /out:X.lib X.lib other1.lib other2.lib
于 2013-08-13T04:23:43.600 に答える