質問

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

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

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

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


アップデート:

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


これは密接に関連しているように見えます 複数の C/C++ ライブラリを 1 つに結合するにはどうすればよいですか?.

役に立ちましたか?

解決

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

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

他のヒント

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

のVisual Studioに付属しているライブラリビルダツールを使用すると、コマンドラインで一緒に図書館に参加することができます。でも、私はビジュアル・エディタでこれを行うにはどのような方法を知りません。

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib
GNUツールチェーンを持つLinuxまたはMinGWの上で

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

あなたが削除しないliba.alibb.aをすれば、あなたは「シンアーカイブ」を作ることができるの

ar crsT libab.a liba.a libb.a
MSVCツールチェーンを使用してWindows上で

lib.exe /OUT:libab.lib liba.lib libb.lib

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

あるいは、 Link Library Dependencies プロジェクトのプロパティでは、Visual Studio でライブラリをリンクする別の方法があります。

  1. 他のライブラリと結合したいライブラリ(X)のプロジェクトを開きます。
  2. X と組み合わせたい他のライブラリを追加します (右クリック、 Add Existing Item...).
  3. プロパティにアクセスして確認してください Item TypeLibrary

これには、次のように実行した場合と同様に、X 内の他のライブラリが含まれます。

lib /out:X.lib X.lib other1.lib other2.lib

注あなたは残りの部分を読む前に:ここに示したシェルスクリプトは確かに安全に使用でき、よくテストされていません。ご自身の責任で使用してください!

私はそのタスクを達成するためにbashスクリプトを書きました。あなたのライブラリがLIB1であると仮定し、1あなたがLIB2あるから一部の記号を含める必要があります。スクリプトはLIB1からシンボルを未定義これは、最初に確認がLIB2に見出すことができるループで実行されます。その後、arとLIB2から対応するオブジェクトファイルを抽出し、それらを少しの名前を変更し、LIB1に入れ、それらを。あなたはLIB2から付属のものは、ループを再度実行する必要があるので、我々は、まだ含まれていないLIB2、から他のものを必要とするため、今、多くの行方不明の記号があるかもしれません。ループのいくつかのパスの後に何も変更はもう存在しない場合は、LIB1に追加LIB2から、すなわち何のオブジェクトファイルは、ループが停止することはできません。

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

#! /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コンパイラスイッチことを残すことができる)そんなに私のスクリプトを信頼しないでしょう。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top