9

私は2つの簡単なファイルを持っています:

runner.cpp:

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>

およびtest1.cpp:

#define BOOST_TEST_DYN_LINK
#ifdef STAND_ALONE
#   define BOOST_TEST_MODULE Main
#endif
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE( Foo)

BOOST_AUTO_TEST_CASE( TestSomething )
{
    BOOST_CHECK( true );
}

BOOST_AUTO_TEST_SUITE_END()

コンパイルするために、私は使用しています:

$ g++ -I/e/code/boost_1_52_0 -o runner -lboost_unit_test_framework runner.cpp test1.cpp

次のエラーが発生します。

C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0x8c): multiple definition of `main'
c:/pdev/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.2/../../../libboost_unit_test_framework.a(unit_test_main.o):unit_test_main.cpp:(.text.startup+0x0): first defined here
c:/pdev/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.2/../../../libboost_unit_test_framework.a(unit_test_main.o):unit_test_main.cpp:(.text.startup+0x14): undefined reference to `init_unit_test_suite(int, char**)'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0x52): undefined reference to `_imp___ZN5boost9unit_test9framework17master_test_suiteEv'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0xb0): undefined reference to `_imp___ZN5boost9unit_test14unit_test_mainEPFbvEiPPc'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerD2Ev[__ZN5boost9unit_test13test_observerD2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerC2Ev[__ZN5boost9unit_test13test_observerC2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test15unit_test_log_tC1Ev[__ZN5boost9unit_test15unit_test_log_tC1Ev]+0x22): undefined reference to `_imp___ZTVN5boost9unit_test15unit_test_log_tE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x88): undefined reference to `_imp___ZN5boost9unit_test15unit_test_log_t14set_checkpointENS0_13basic_cstringIKcEEjS4_'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x136): undefined reference to `_imp___ZN5boost10test_tools9tt_detail10check_implERKNS0_16predicate_resultERKNS_9unit_test12lazy_ostreamENS5_13basic_cstringIKcEEjNS1_10tool_levelENS1_10check_typeEjz'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x21d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1ENS0_13basic_cstringIKcEE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x284): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1EPNS0_9test_caseEm'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x2a4): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1Ei'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x1d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x5b): undefined reference to `_imp___ZN5boost9unit_test9test_caseC1ENS0_13basic_cstringIKcEERKNS0_9callback0INS0_9ut_detail6unusedEEE'
collect2.exe: error: ld returned 1 exit status

MinGWでg++4.7.2を使用しており、ブーストは1.52.0です。

test1.cpp「複数のメイン定義」のものを除いて、コンパイルしようとすると同じエラーが発生します。

私はかなり長い間公式ドキュメントを熟読しましたが、リンクオプションに関する詳細についてはほとんどありません。ブーストライブラリをコンパイルしたとき、さらに、 ;unit_test_frameworkも取得prg_exec_monitorしました。test_exec_monitorたぶん私はこれらをどうにかしてリンクする必要がありますか?多くの組み合わせを試しましたが、いずれも何らかの未定義の参照リンカーエラーが発生しました。

ブーストで生成されたライブラリの完全なリスト-私はそれらすべてをプロジェクトルートに持っています:

libboost_prg_exec_monitor-mgw47-mt-1_52.a
libboost_prg_exec_monitor-mgw47-mt-1_52.dll
libboost_prg_exec_monitor-mgw47-mt-1_52.dll.a
libboost_prg_exec_monitor-mgw47-mt-d-1_52.a
libboost_prg_exec_monitor-mgw47-mt-d-1_52.dll
libboost_prg_exec_monitor-mgw47-mt-d-1_52.dll.a
libboost_test_exec_monitor-mgw47-mt-1_52.a
libboost_test_exec_monitor-mgw47-mt-d-1_52.a
libboost_unit_test_framework-mgw47-mt-1_52.a
libboost_unit_test_framework-mgw47-mt-1_52.dll
libboost_unit_test_framework-mgw47-mt-1_52.dll.a
libboost_unit_test_framework-mgw47-mt-d-1_52.a
libboost_unit_test_framework-mgw47-mt-d-1_52.dll
libboost_unit_test_framework-mgw47-mt-d-1_52.dll.a
4

1 に答える 1

23

@llonesmizの助けを借りて、いくつかの問題が特定されました。

1.ライブラリは、それらを使用するオブジェクトとソースのに指定する必要があります。

ここで説明されているように:

リンカの従来の動作は、コマンドラインで指定されたライブラリで左から右に外部関数を検索することです。つまり、関数の定義を含むライブラリは、それを使用するソースファイルまたはオブジェクトファイルの後に表示される必要があります。これには、次のコマンドに示すように、ショートカット-lオプションで指定されたライブラリが含まれます。

$ gcc -Wall calc.c -lm -o calc (correct order)

一部のリンカでは、逆の順序(-lmオプションをそれを使用するファイルの前に配置)でエラーが発生し、エラーが発生します。

$ cc -Wall -lm calc.c -o calc (incorrect order)
main.o: In function 'main':
main.o(.text+0xf): undefined reference to 'sqrt'

'calc.c'の後にsqrtを含むライブラリまたはオブジェクトファイルがないためです。オプション-lmは、ファイル'calc.c'の後に表示されます</p>

2.ライブラリパスは明示的に指定する必要があります。

libパスが指定されていない場合、リンカは一連のデフォルトフォルダでlibを検索し、意図したものとは異なるライブラリをロードする可能性があります。これが私の場合に起こったことです-リンクしたかったboost_unit_test_frameworkのですが、リンカーが現在のフォルダーを検索すると想定したため、パスを指定しませんでした。結局のところ、これが実行時に発生します。dllがと同じフォルダにある場合はexe、それが検出されます。

名前が付けられているので、リンカーがlibを見つけるのは少し奇妙だと思いましたibboost_unit_test_framework-mgw47-mt-1_52.dll。存在しないlibにリンクしようとすると、リンカーが文句を言ったので、これは問題ではないと思い、MinGWのリンカーはそれらのサフィックスを無視します。

さらに調査した結果、MinGWライブラリパスに関するこの記事を見つけました。MinGWがlibsを検索するフォルダーは、の出力にありgcc -print-search-dirsます。bashこの記事には、その出力を理解するための魔法も含まれています。

gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012 | grep -v '^ */'

これにより、これらのフォルダの適切なリストが印刷されます。デフォルトでは、現在のディレクトリでlibsを検索しgccません。私はそれらのそれぞれを調べて、ロードされていたlib- libboost_unit_test_framework.a、静的libを見つけました。

これにより、言及する価値のある別の問題が明らかになります。

3.静的リンクと動的リンク

boost_unit_test_framework静的にリンクするか動的にリンクするかを指定しませんでした。この場合、gcc動的リンクを優先します:

これらの利点があるため、gccはプログラムをコンパイルして、ほとんどのシステムでデフォルトで共有ライブラリを使用できるようにします(使用可能な場合)。オプション-lNAMEを使用してリンクするために静的ライブラリ'libNAME.a'が使用される場合は常に、コンパイラは最初に同じ名前で拡張子が'.so'の代替共有ライブラリをチェックします。

soUnixのダイナミックライブラリの拡張機能です。Windowsの場合、同等のものはdllです。)

つまり、何が起こったのかというと、デフォルトのフォルダgcclibboost_unit_test_framework.dll すべて検索しましたが、見つかりませんでした。次に、を探し libboost_unit_test_framework.a、静的にリンクしました。#define BOOST_TEST_DYN_LINKソースにはがあり、したがってlibが動的にリンクされていると予想されるため、これによりリンクエラーが発生しました。

静的または動的リンクを適用するために、ここ-Wl,-Bstaticで説明するリンカーオプションと-Wl,-Bdynamic リンカーオプションが機能します。

動的リンクが必要であることをリンカーに伝えると、次のようになります。

$ g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework

リンカがを見つけることができないため、これは失敗しますdll

4.まとめ

問題は次のとおりです。

  1. それらを使用したソースの前に指定されたライブラリ
  2. libパスが指定されていません
  3. リンクの種類が指定されていません
  4. ライブラリの名前が正しくありませんでした

最終的な作業コマンド:

$ g++ -I/e/code/boost_1_52_0 -o runner runner.cpp test1.cpp -L. -Wl,-Bdynamic -lboost_unit_test_framework-mgw47-mt-1_52
于 2012-12-08T12:59:01.860 に答える