1

もともと Linux OS で書かれたプログラムを MAC OSX でコンパイルしようとしています。これは、いくつかのメイクファイルを含む大きなプログラムです。私は何週間もそれに取り組んできましたが、未定義のシンボルエラーを引き起こしている理由を理解できないようです. コンパイルの順序が正しくなるように、他のメイクファイルを呼び出す包括的な Makefile が 1 つあります。

コンパイルすると、静的ライブラリと複数のアプリケーションが作成されます。この人たちは非常に巨大であるため、プログラムはこれらの静的ライブラリ (.a ファイル) を最初に作成します。次に、アプリケーション専用のソース コードをコンパイルするときに、静的ライブラリをリンクします。(あまり混乱しないことを願っています) .

静的ライブラリのビルドは問題なく完了できますが、アプリケーションがビルドされる時点に到達すると、大量の未定義シンボル エラーが表示されます。たとえば、

未定義のシンボル: "_bagUpdateOptSurface"、参照元: libdbdbv6.a(dbv_bag.o) の _dbv_bag

nm で dbv_bag.o をチェックすると、ヘッダー U で定義されていない多くの関数が表示されます。

この関数を nm でトレースバックして、それを見つけることができます...

bagUpdateOptSurface.c -->bagUpdateOptSurface.o -->libbag.a --->dbv_bag.c --->dbv_bag.o --->libdbdv6.a --->application

関数はヘッダー T を持つスタティック ライブラリ libbag.a で定義されていますが、オブジェクト ファイル dbb_bag.o では U で未定義として定義されています。どこかで情報が失われ、その理由を理解できないようです。

プログラムを Mac に移植する経験が豊富な誰かが、何が起こっているのかを明らかにするのに役立つなら、私は非常に感謝しています。正しいまたは間違っているアイデアは大歓迎です。

前もって感謝します

4

1 に答える 1

0

好奇心から、リンクにldの代わりにgccまたはg++を使用してみましたか? 多くの場合、これらの大規模なプロジェクトでは、変数が定義されたメイクファイルが使用され、 make LD=gcc targetなどと言うことができます。

「T」バージョンがある限り、多くの「U」フラグは問題になりません。

簡単な例を作成してみてください。いくつかの短い 1 行または 2 行のソース ファイルを .o にコンパイルし (-c フラグを使用)、ライブラリに入れ (ar -rv)、問題を再現できるかどうかを確認します。単純化すると、多くの場合、答えが見つけやすくなります。

リンカのフラグの問題でなければ、リンクしている行の順序付けの問題 (依存地獄) かもしれません。または、どこかでライブラリが不足している可能性があります。

使用している gcc/g++ のバージョンと、OSX のバージョンも確認する必要があると思います...

別の可能性として、誤って関数を g++ でオーバーロードしたり、実装とは異なるヘッダー シグネチャを使用したりする可能性があります。

すべての .o ファイルとライブラリ ファイルを削除して、ワールド (すべて) を再コンパイルしてみてください。.o ファイル (またはライブラリ) がソース/ヘッダー ファイルから古くなり、本当に信じられないほどの痛みと苦しみを引き起こすことがあります...



コメントへの対応:

前述のように、埋もれていますが、上記のとおりです。このような問題は、コマンドラインでの依存関係の地獄とリンクの順序付けに言及することがよくあります。少なくとも彼らはそうでした。今でもそうかどうかはわかりません。

ディレクトリをコピーし、できるだけ多くのコードを取り除き (バイナリ検索のデバッグ)、簡単な例を作成すると、通常は問題を特定しやすくなります。

gcc/g++ とのリンク: gcc -cを介してfile.cfile.oにコンパイルし、続いてldを介してfile.oを実行可能ファイルにリンクできます。または、gcc file.o -o file invoking gccを実行して、適切な引数でldを呼び出すこともできます。必要なライブラリや、 ldに渡す必要があるフラグがよくわからない場合に役立つことがあります。

Gcc 4.2.1 と OSX 10.6.8 は問題になりません。古いコンパイラには興味深い欠点/問題があったため、本当に古いものを使用しているかどうかに興味がありました。

とはいえ、今考えてみると、Linux でコンパイルするためにどのコンパイラを使用していましたか? OSXで新しい/古いgcc/g++コンパイラを使用している可能性があり、問題はコンパイラの「改善」に起因しています。

関数のオーバーロード: Gcc/g++ は、多くの場合、ファイル名のサフィックスに基づいて C と C++ のコンパイルを決定します。OSX には通常、大文字と小文字を区別しないファイルシステムがあります。したがって、ファイルの名前がfile.cfile.C かに関係なく、 gcc file.cとg++ file.Cは両方とも機能します。ただし、C 言語と C++ 言語には、噛み付く可能性のある違いがあります。たとえば、foo(signed int)を定義した場合、型情報は C++ コンパイルでコンパイルされた関数名に組み込まれます (マングルされます)。その後、C コードから呼び出すと、必ずしも機能するとは限りません (適切にリンクします)。

同様に、ヘッダー ファイルにfoo(short int)と記述されていて、ソース コードにfoo(long int)と記述されている場合、興味深い問題が発生する可能性があります。

于 2012-11-04T12:41:05.217 に答える