3

CppUTestを使用して、fornol.cソースファイルで定義されたCコードをテストしています。そのファイルは、主要な生産main()関数を定義します。

関数もあるAllTests.cppファイルもありますが、単体テストを実行する場合にのみ使用することになっています。main()main()

AllTests.cpp.oファイルにコンパイルされますが、アーカイブfornol.cにコンパイルされます。libfornol.a

次に、CppUTestはすべてをリンクしようとしますが、代わりに次のようになります。

Linking fornol_tests
cc    -o fornol_tests objs/tests/AllTests.o objs/tests/FornolTests.o lib/libfornol.a ../../CppUTest/lib/libCppUTest.a ../../CppUTest/lib/libCppUTestExt.a -lstdc++ -lgcov
lib/libfornol.a(fornol.o): In function `main':
/home/dlindelof/Work/endor/nol/fornol/fornol.c:453: multiple definition of `main'
objs/tests/AllTests.o:/home/dlindelof/Work/endor/nol/fornol/tests/AllTests.cpp:4: first defined here
collect2: ld returned 1 exit status

で定義され、アーカイブに存在するmain()関数がで定義されたものと競合しているように見えます。しかし、私の理解では、アーカイブ/ライブラリファイルは、特定のシンボルがまだ参照されていない場合にのみ検索されます。したがって、すべての定義がアーカイブ/ライブラリファイルにある場合は、同じシンボルを複数回定義しても問題はありません。fornol.clibfornol.amain()AllTests.cpp

私はここで何が間違っているのですか?

4

2 に答える 2

4

main()を削除しAllTests.cppて、独自のソース ファイルに配置する必要があります。

リンカーがライブラリ内でリンクする場合、ライブラリ内のオブジェクト ファイルを分割することはできません。ライブラリ内の各オブジェクト ファイルを 1 つの単位としてリンクするか、または省略する必要があります。(LLVM が異なることは知っていますが、それは別のトピックです。) これが、glibc のようなライブラリのソースを見ると、各関数が独自のソース ファイルを取得する理由です。

つまり、リンカーは依存関係を満たすためfornol.oにライブラリ ( ) からオブジェクト ファイル ( ) をプルする必要がありlibfornol.aますが、そのオブジェクト ファイルには重複したシンボルが含まれています ( main)。

テスト コードをライブラリに入れることはまったく問題ありません (私が働いている場所では日常的に行っています) が、それを独自のソース ファイルに保持します (私たちは伝統的に を使用しますmain.cc)。static(テスト コードは-declared シンボルにアクセスできないため、これはより良いテストです。)

于 2012-02-03T13:15:48.693 に答える
0

ライブラリはライブラリであるため、 main() 関数を持たないことになっています

その main() を fornol.c から削除して、再度コンパイルする必要があります。

main() は実行可能ファイルのソース コードのエントリ ポイントです。ライブラリ (特に静的な ".a" ライブラリ) はコンパイル済みのソース コードにすぎないため、そこで main を使用することはできません。

ライブラリの主要なプロダクション エントリ ポイントが必要な場合は、fornol.c の main() の名前を、たとえば "fornolMain()" など、より明示的であまり予約されていない名前に変更できます。

静的ライブラリはバイナリ実行可能ファイルにコンパイルされるため、シンボルがロードされている場合にのみ検索されません。fornol.c をコンパイルし、fornol.o と他の .o をリンクするのとまったく同じです。

于 2012-02-03T13:09:07.983 に答える