2012-08-12 17 views
7

可能性の重複:
Why does the order of '-l' option in gcc matter?g ++の引数の順序を変更すると、プログラムがリンクに失敗するのはなぜですか?

私はブーストユニットテストフレームワークを学ぶために始めています。私は、最小限のテストスイートを持っています。

g++ -c src/tests.cc -o src/tests.o 

これはエラーなしで完了します。

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

BOOST_AUTO_TEST_CASE(test1) { 
    BOOST_CHECK(2 == 1); 
} 

まず私は、ソースをコンパイルします。私は次のようにリンクすることができます:

g++ -o tests src/tests.o -lboost_unit_test_framework 

これはエラーなしで完了します。生成されたバイナリは、期待される結果で実行されます。私はsrc/tests.o-lboost_unit_test_frameworkの順序を入れ替える場合は、私は、リンカエラーを取得:

g++ -o tests -lboost_unit_test_framework src/tests.o 
 
src/tests.o: In function `main': 
tests.cc:(.text+0x29): undefined reference to `boost::unit_test::unit_test_main(bool (*)(), int, char**)' 
src/tests.o: In function `test1::test_method()': 
tests.cc:(.text+0x9d): undefined reference to `boost::unit_test::unit_test_log_t::set_checkpoint(boost::unit_test::basic_cstring, unsigned int, boost::unit_test::basic_cstring)' 
tests.cc:(.text+0x146): undefined reference to `boost::test_tools::tt_detail::check_impl(boost::test_tools::predicate_result const&, boost::unit_test::lazy_ostream const&, boost::unit_test::basic_cstring, unsigned int, boost::test_tools::tt_detail::tool_level, boost::test_tools::tt_detail::check_type, unsigned int, ...)' 
src/tests.o: In function `__static_initialization_and_destruction_0(int, int)': 
tests.cc:(.text+0x24d): undefined reference to `boost::unit_test::ut_detail::auto_test_unit_registrar::auto_test_unit_registrar(boost::unit_test::test_case*, unsigned long)' 
src/tests.o: In function `boost::unit_test::unit_test_log_t::unit_test_log_t()': 
tests.cc:(.text._ZN5boost9unit_test15unit_test_log_tC2Ev[_ZN5boost9unit_test15unit_test_log_tC5Ev]+0x21): undefined reference to `vtable for boost::unit_test::unit_test_log_t' 
src/tests.o: In function `boost::unit_test::make_test_case(boost::unit_test::callback0 const&, boost::unit_test::basic_cstring)': 
tests.cc:(.text._ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[boost::unit_test::make_test_case(boost::unit_test::callback0 const&, boost::unit_test::basic_cstring)]+0x1d): undefined reference to `boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring)' 
tests.cc:(.text._ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[boost::unit_test::make_test_case(boost::unit_test::callback0 const&, boost::unit_test::basic_cstring)]+0x5d): undefined reference to `boost::unit_test::test_case::test_case(boost::unit_test::basic_cstring, boost::unit_test::callback0 const&)' 
src/tests.o: In function `boost::unit_test::unit_test_log_t::~unit_test_log_t()': 
tests.cc:(.text._ZN5boost9unit_test15unit_test_log_tD2Ev[_ZN5boost9unit_test15unit_test_log_tD5Ev]+0xb): undefined reference to `vtable for boost::unit_test::unit_test_log_t' 
collect2: ld returned 1 exit status 

はなぜ私の引数の順序は、リンカエラーを引き起こすのでしょうか?

+0

@AndreyT:検索をお寄せいただきありがとうございます。 –

答えて

11

GCCがリンクを実行すると、ライブラリが特別扱いされています:そのオブジェクトファイルから欠落しているシンボルだけをこれは、次のコマンドに示すように、短いカット-lオプションで指定したライブラリが含まれていますの前に来て、のコマンドラインリストのライブラリがライブラリから書き込まれます。 の後にさらにオブジェクトファイルがある場合、そのオブジェクトのシンボルはライブラリ内で参照されません。

簡単に言えば、オブジェクトファイルを最初にリストし、最後にライブラリをリストします。

+0

ちなみに、この変更はgccの最近のバージョンで起きた可能性があります.gcc 4.4では、コマンドラインでのライブラリの順序は重要ではありません(gccはもっと寛容でした)。 –

+3

@MatteoItaliaこの動作は、少なくともgcc 3.1.1 http://gcc.gnu.org/onlinedocs/gcc-3.1.1/gcc/Link-Options.html#Link%20Options以降に存在します。 – log0

+0

@Ugo:gcc 4.4からアップグレードした後でなければ、その理由で動作しなくなったmakefileがいくつかあったので、不思議です。 :S –

3

従来のリンカーの動作は、コマンドラインで指定されたライブラリの左から右に外部関数を検索することです。つまり、関数の定義を含むライブラリは、それを使用するソースファイルまたはオブジェクトファイルの後に現れなければなりません。

http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html

関連する問題