32 ビット組み込みプロセッサ用に記述された大規模なコードベースをコンパイルして、シミュレーション/単体テスト用に 64 ビット デスクトップ プロセッサで実行しようとしています。結果のオブジェクトを共有ライブラリにする必要があります。これは Windows の問題ではありません。このような dll (/DWIN32) をビルドでき、問題なく動作します。
Linux では、gcc とリンカーの両方に -m32 オプションを指定してコンパイルおよびリンクし、共有ライブラリを取得できます。問題は、このライブラリが (-m32 で指定したように) 32 ビット ライブラリであり、私の 64 ビット アーキテクチャでは動作しないことです。Python で、ライブラリをロードしようとします (ctypes.cdll.LoadLibrary() を使用)
OSError: out.so: wrong ELF class: ELFCLASS32
-mx32 オプションを発見しました。ドキュメントによると、これはまさに私が望むものです:
-mx32 オプションは、int、long、およびポインター型を 32 ビットに設定し、x86-64 アーキテクチャー用のコードを生成します。
そのため、-mx32 をコンパイラとリンカーに渡し (-m32 オプションを置き換えます)、次の結果を取得します (出力を切り取りました)。
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/32/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/32/libstdc++.a when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a when searching for -lstdc++
/usr/bin/ld: cannot find -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm
gcc 4.7 と gcc 4.8 で同じ結果が得られます。上記の出力は gcc 4.8 からのものです。
gcc-4.8-multilib と g++-4.8-multilib がインストールされています。
私のライブラリパスは次のとおりです。
LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu/4.8/32:/usr/lib/gcc/x86_64-linux-gnu/4.8/
.bashrc から、リンカーが機能するライブラリにのみバインドすることを読んだ後、絶望的に /4.8/ および /4.8/32/ を追加して、このように指定しました (以下)。
export LIBRARY_PATH=/usr/lib/$(gcc -print-multiarch):/usr/lib/gcc/x86_64-linux-gnu/4.8/32:/usr/lib/gcc/x86_64-linux-gnu/4.8/
私が言及したように、これはWindows上でdllとしてすでに非常にうまく機能しています。何かが欠けているだけだと信じなければなりません。ポインターは 32 ビット、long は 32 ビットである必要があり、すべてが x86_64 で実行される必要があります。-mx32 は、まさにそれを行うと言っています (そうですか?)。
-m32 でコンパイルした後、オブジェクトの 1 つを確認します。
$:~/project$ file foo.o
foo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
-mx32 でコンパイルした後、同じオブジェクトをチェックします。
$:~/project$ file foo.o
foo.o: ELF 32-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
私はこれについて間違った方法で進んでいますか?32 ビットの共有ライブラリを何らかの互換性レイヤーで引き続き使用できますか?
これらのリンク エラーに関する gcc 4.7 に対するバグ レポートを見ましたが、結論はあまり出ていませんでした。 このページには、gcc 4.8 が x32 の推奨される最小値であると記載されているため、インストールしました。それでも -- リンクできません。-m32 リンクは問題ありません。