現在のubuntu(12.04)でプログラムをコンパイルする必要があります。このプログラムは、古いカーネル(2.6.18)でCentOSを使用するクラスターで実行する必要があります。残念ながら、クラスターで直接コンパイルすることはできません。変更せずにプログラムをコンパイルしてコピーするだけで、「カーネルが古すぎます」というエラーメッセージが表示されます。
私が理解したように、この理由はカーネルのバージョンではなく、コンパイルに使用されたlibcのバージョンです。そこで、プログラムをコンパイルして、クラスターからlibcを動的にリンクし、他のすべてを静的にリンクしようとしました。
研究
このことについては、SOで既に多くの質問がありますが、答えはどれも私にとってはうまくいきませんでした。
-rpath
を使用して異なるlibcバージョン用にコンパイルできますが、これは私には機能しませんでした(下記参照)現在の状態
次のファイルをクラスターからディレクトリ/path/to/copied/libs
にコピーしました
オプション-nodefaultlibs -Xlinker -rpath=/path/to/copied/libs -Wl,-Bstatic,-lrt,-lboost_system,-lboost_filesystem -Wl,-Bdynamic,-lc,-lstdc++,-lgcc_s
でコンパイルしています
コンパイルされたバイナリでのlddの出力は次のとおりです。
mybin: /path/to/copied/libs/libc.so.6: version `GLIBC_2.14' not found (required by mybin)
mybin: /path/to/copied/libs/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by mybin)
linux-vdso.so.1 => (0x00007ffff36bb000)
libc.so.6 => /path/to/copied/libs/libc.so.6 (0x00007fbe3789a000)
libstdc++.so.6 => /path/to/copied/libs/libstdc++.so.6 (0x00007fbe37599000)
libgcc_s.so.1 => /path/to/copied/libs/libgcc_s.so.1 (0x00007fbe3738b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbe37bf3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbe37071000)
正しいパス(つまり、クラスターからのlibc)を使用しているため、エラーに多少混乱していますが、glibcバージョンが見つからないことを訴えています。クラスタでlddを実行すると、not a dynamic executable
が返され、バイナリを実行すると、上記と同じ2つのエラーが発生します。また、他のライブラリが含まれているようです(linux-vdso.so.1、ld-linux-x86-64.so.2、およびlibm.so.6)。それらにも古いバージョンを使用する必要がありますか?
だから今、私は2つの主な質問があります:
this answerを参照してください。
これは正しいアプローチですか?
いいえ:リンクコマンドのように、glibcのmismatchedバージョンを使用することはできません。使いました crt0.o
およびld-linux.so
fromnew(システムインストール済み)libc、ただしlibc.so.6
古い(クラスターからコピーされた)libcから。それはうまくいきません。
-rpath
はDT_RPATHタグを設定しますが、リンカにライブラリを探すように指示しません。そのために-L
が必要です。