回答:
gcc -lsome_dynamic_lib code.c some_static_lib.a
code.c
ファイルの前に静的ライブラリをリストすると、そこにあるシンボルが無視されることが保証されますmain()
ライブラリオブジェクトファイルのいずれかで機能。
ld
オプションを使用することもできます-Bdynamic
gcc <objectfiles> -static -lstatic1 -lstatic2 -Wl,-Bdynamic -ldynamic1 -ldynamic2
それ以降のすべてのライブラリ(gccによって自動的にリンクされるシステムライブラリを含む)は動的にリンクされます。
gcc objectfiles -o program -Wl,-Bstatic -ls1 -ls2 -Wl,-Bdynamic -ld1 -ld2
次も使用できます:-static-libgcc -static-libstdc++
gccライブラリのフラグ
場合があることに注意してくださいlibs1.so
とlibs1.a
の両方が存在し、リンカが選択されますlibs1.so
、それは前にかどう-Wl,-Bstatic
か後-Wl,-Bdynamic
。を-L/libs1-library-location/
呼び出す前にパスすることを忘れないでください-ls1
。
-static
ますが、コマンドのどこかを使用すると失敗します(必要なライブラリだけではなく、より多くのものを静的にリンクしようとしていると思います)。
-Wl,-Bstatic
とは-Wl,-Bdynamic
重要です。
ld
(これはgccでは機能しません)のマンページから、--static
オプションを参照してください:
このオプションは、コマンドラインで複数回使用できます。これは、それに続く-lオプションのライブラリ検索に影響します。
1つの解決策は--static
、コマンドラインのオプションの前に動的依存関係を置くことです。
別の可能性は、を使用せず--static
に、静的オブジェクトファイルの完全なファイル名/パスを提供する(つまり、-lオプションを使用しない)ことで、特定のライブラリに静的にリンクすることです。例:
# echo "int main() {}" > test.cpp
# c++ test.cpp /usr/lib/libX11.a
# ldd a.out
linux-vdso.so.1 => (0x00007fff385cc000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f9a5b233000)
libm.so.6 => /lib/libm.so.6 (0x00007f9a5afb0000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f9a5ad99000)
libc.so.6 => /lib/libc.so.6 (0x00007f9a5aa46000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9a5b53f000)
例からわかるように、libX11
は静的にリンクされていたため、動的にリンクされたライブラリのリストにはありません。
注意:.so
完全なファイル名/パスで指定されている場合でも、ファイルは常に動的にリンクされます。
ldd a.out
か?
ldd
必要な共有ライブラリを出力し、libX11はそのリストに表示されません。
私が理解している問題は次のとおりです。いくつかのライブラリがあり、一部は静的、一部は動的、一部は静的と動的の両方です。 gccのデフォルトの動作は、「ほぼ動的」にリンクすることです。つまり、gccは可能な場合は動的ライブラリにリンクしますが、そうでない場合は静的ライブラリにフォールバックします。-staticオプションを使用してgccを実行すると、適切な動的ライブラリがある場合でも、静的ライブラリのみをリンクし、静的ライブラリが見つからない場合はエラーで終了します。
いくつかの場合にgccに期待したい別のオプションは、私が-most-staticと呼んでいるもので、基本的に-dynamic(デフォルト)の反対です。 -mostly-staticは、存在する場合、静的ライブラリに対してリンクすることを好みますが、動的ライブラリにフォールバックします。
このオプションは存在しませんが、次のアルゴリズムでエミュレートできます。
-staticを含めずにリンクコマンドラインを作成します。
ダイナミックリンクオプションを反復処理します。
ライブラリパス、つまり-L <lib_dir>形式のオプションを変数<lib_path>に累積します。
各ダイナミックリンクオプション、つまり-l <lib_name>形式のオプションについて、コマンドgcc <lib_path> -print-file-name = lib <lib_name> .aを実行し、出力をキャプチャします。
コマンドが渡したもの以外のものを出力する場合、それは静的ライブラリへのフルパスになります。ダイナミックライブラリオプションをスタティックライブラリへのフルパスに置き換えます。
リンクコマンドライン全体を処理するまで、すすぎ、繰り返します。オプションで、スクリプトはライブラリ名のリストを取得して、静的リンクから除外することもできます。
次のbashスクリプトは、トリックを行うようです:
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Usage: $0 [--exclude <lib_name>]. . . <link_command>"
fi
exclude=()
lib_path=()
while [ $# -ne 0 ]; do
case "$1" in
-L*)
if [ "$1" == -L ]; then
shift
LPATH="-L$1"
else
LPATH="$1"
fi
lib_path+=("$LPATH")
echo -n "\"$LPATH\" "
;;
-l*)
NAME="$(echo $1 | sed 's/-l\(.*\)/\1/')"
if echo "${exclude[@]}" | grep " $NAME " >/dev/null; then
echo -n "$1 "
else
LIB="$(gcc $lib_path -print-file-name=lib"$NAME".a)"
if [ "$LIB" == lib"$NAME".a ]; then
echo -n "$1 "
else
echo -n "\"$LIB\" "
fi
fi
;;
--exclude)
shift
exclude+=(" $1 ")
;;
*) echo -n "$1 "
esac
shift
done
echo
例えば:
mostlyStatic gcc -o test test.c -ldl -lpthread
私のシステムでは:
gcc -o test test.c "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libdl.a" "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
または除外あり:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
私はそれから得ます:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
-l:libstatic1.a
静的ライブラリをリンクするために使用できるgccの-lオプションの(マイナスlコロン)バリアントもあります(https://stackoverflow.com/a/20728782に感謝)。文書化されていますか?gccの公式ドキュメントにはありません(これは共有ライブラリにも当てはまりません):https : //gcc.gnu.org/onlinedocs/gcc/Link-Options.html
-llibrary -l library
リンク時にlibraryという名前のライブラリを検索します。(ライブラリを個別の引数として使用する2番目の選択肢はPOSIX準拠のためだけであり、推奨されません。)... -lオプションを使用することとファイル名を指定することの間の唯一の違いは、-lが 'lib'でライブラリを囲み、 '.a'といくつかのディレクトリを検索します。
binutils ld docで説明しています。-lname
オプションでは、検索を行いますlibname.so
ため、その後libname.a
のlib接頭辞を追加し、.so
(現時点では有効になっている場合)または.a
接尾辞。ただし、-l:name
オプションは指定された名前を正確に検索するだけです:https :
//sourceware.org/binutils/docs/ld/Options.html
-l namespec --library=namespec
によって指定されたアーカイブまたはオブジェクトファイル
namespec
をリンクするファイルのリストに追加します。このオプションは何度でも使用できます。namespec
の形式の場合:filename
、ldはライブラリパスでというファイルfilename
を検索しますlibnamespec.a
。それ以外の場合は、ライブラリパスでというファイルを検索します。共有ライブラリをサポートするシステムでは、ldは以外のファイルも検索する場合があります
libnamespec.a
。具体的には、ELFおよびSunOSシステムでは、ldはと呼ばれるライブラリを検索するlibnamespec.so
前に、呼び出されるライブラリをディレクトリで 検索しlibnamespec.a
ます。(慣例により、.so
拡張子は共有ライブラリを示します。)この動作は:filename
、常にと呼ばれるファイルを指定するには適用されないことに注意してくださいfilename
。リンカは、コマンドラインで指定された場所で、アーカイブを1回だけ検索します。アーカイブが、コマンドラインでアーカイブの前に表示された一部のオブジェクトで未定義のシンボルを定義している場合、リンカーはアーカイブから適切なファイルを含めます。ただし、後でコマンドラインに表示されるオブジェクトに未定義のシンボルがあっても、リンカーはアーカイブを再度検索しません。
-(
リンカーにアーカイブを複数回検索させる方法については、オプションを参照してください。コマンドラインで同じアーカイブを複数回リストすることができます。
このタイプのアーカイブ検索は、Unixリンカーの標準です。ただし、AIXでldを使用している場合は、AIXリンカーの動作とは異なることに注意してください。
バリアント-l:namespec
は、binutils(2007)の2.18バージョン以降でドキュメント化されています:https : //sourceware.org/binutils/docs-2.18/ld/Options.html
一部のローダー(リンカー)は、動的ロードをオンまたはオフにするスイッチを提供します。GCCがそのようなシステム(Solaris-および場合によっては他のシステム)で実行されている場合は、関連するオプションを使用できます。
静的にリンクするライブラリがわかっている場合は、リンク行に静的ライブラリファイルをフルパスで指定するだけです。