automake を使用するプロジェクトで、奇妙なリンク エラーが発生します。私がやっていることはマニュアルから見るとかなり単純に思えるので、何が間違っているのだろうか...
私のプロジェクトには 3 つのフォルダーがあります。
- src/common では、いくつかの C++ ファイルを libube-common.a 静的ライブラリにコンパイルします。
- src/engine で、いくつかのファイルを libube-engine.a 静的ライブラリにコンパイルします。
- src/client には ... ご想像のとおり、 libue-client.a と、私のメインである ube.cpp という 1 つのファイルがあります。
各ライブラリは、次のような Makefile.am でコンパイルされます。
noinst_LIBRARIES=libube-common.a
libube_common_a_SOURCES=gettext.h lua_helper.hpp \
silent_ostream.hpp \
logging.hpp logging.cpp \
logger_interface.hpp \
... etc ...
AM_CPPFLAGS=-DSRCDIR=\"${srcdir}\" \
-DLUADIR=\"${luadir}\" \
-Wall -Werror \
-I$(srcdir)/../../include \
$(LUA_INCLUDE) \
$(BOOST_CPPFLAGS)
これにより、さまざまなオブジェクトが次のような行で構築されます。
g++ -DHAVE_CONFIG_H -I. -I../../../../../src/common -I../.. -DSRCDIR=\"../../../../../src/common\" -DLUADIR=\"\" -Wall -Werror -I../../../../../src/common/../../include -I/usr/include/lua5.1 -I/usr/include -g -O2 -MT logging.o -MD -MP -MF .deps/logging.Tpo -c -o logging.o ../../../../../src/common/logging.cpp
そして、それらはすべてライブラリに入れられます:
ar cru libube-common.a logging.o prefix_resource_resolver.o stat_file_checker.o
ranlib libube-common.a
これはすべてうまくいっているように思えます。ライブラリに対していくつかの小さなテスト プログラムをリンクすることもできます (同じメイクファイル内)。
次に、メイン プログラムの Makefile.am で、ローカル ライブラリへのリンクを要求しました。
ube_LDADD=../common/libube-common.a \
../engine/libube-engine.a \
libube-client.a \
... other libs ...
そして、それが私がこのようなエラーを得る場所です:
g++ -g -O2 -o ube ube.o ../common/libube-common.a ../engine/libube-engine.a libube- client.a -L/usr/include/lua5.1/lib -llua5.1 -lm -ldl -L/usr/lib -lSDL -lSDL_image -lpng -ltiff -ljpeg -lz -lSDL_ttf -lfreetype -lSDL_mixer -lSDL_mixer -lSDL_ttf -lSDL_image
libube-client.a(game_loop.o): In function `Logging::debug_ostream(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
(...) logging.hpp:54: undefined reference to `Logging::get_ostream(LogLevel::Level, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
(...)logging.hpp:54: undefined reference to `Logging::get_ostream(LogLevel::Level, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
最初は、いくつかの静的シンボルが原因だと思っていましたが、非静的シンボルでも問題が発生します。
生成されたライブラリを確認したところ、シンボルが適切に含まれているようです:
~/prj/ube/builds/linux/current/src/common$ nm -C libube-common.a | grep logging.o -C 20
logging.o:
00000010 t global constructors keyed to _ZN7Logging15disable_loggingEv
00000000 V guard variable for Logging::get_instance()::s_local_instance
000000b0 T Logging::get_ostream(LogLevel::Level, std::string)
00000000 T Logging::disable_logging()
00000040 T Logging::is_category_enabled(LogLevel::Level, std::string&)
U std::ios_base::Init::Init()
U std::ios_base::Init::~Init()
00000000 b std::__ioinit
U __cxa_atexit
U __dso_handle
U __gxx_personality_v0
唯一の修正は、.o ファイルに対して明示的にリンクすることです (それらを ube_LDADD 行に追加することによって...しかし、それはライブラリを使用するという考えにちょっと反抗します!!)
私はマニュアルに従っているようです:http://www.gnu.org/software/hello/manual/automake/Linking.html#Linking
しかし、明らかに私はどこかを台無しにしたので、どんなアイデアでも大歓迎です!!
ありがとう
PH
編集:ライブラリ自体は機能しているようですが、リンクの問題のようです。テストケースプログラムをそれらに対してリンクできます。これが私がすることです:
フォルダー src/common/tests には、単体テストを実行する common-tests.cpp というメインがあります。common-tests ビンは、ライブラリ libube-common.a に対してリンクされています (これらは単体テストであるため、ライブラリ内にあるオブジェクトのみが必要です)。
# There is one program that aggreatates all tests cases
check_PROGRAMS = common-tests
common_tests_SOURCES= tests/common_tests.cpp \
tests/prefix_resource_resolver_test.cpp \
tests/mock_file_checker.hpp \
tests/stat_file_checker_test.cpp
# The program needs to be compiled against the local lib
common_tests_LDADD=libube-common.a -L$(top_srcdir)/lib -lgtest -lgmock -llua -ldl
# This means common-tests is run when using 'make check'.
TESTS = common-tests
make check を実行すると、テスト プログラムは次のようにコンパイルされます。
g++ -g -O2 -o common-tests common_tests.o prefix_resource_resolver_test.o stat_file_checker_test.o libube-common.a -L../../../../../lib -lgtest -lgmock -llua -ldl -lSDL_mixer -lSDL_ttf -lSDL_image
そして、物事は完璧に機能します。私が見ることができる唯一の違いは、この場合、ライブラリがリンクする実行可能ファイルのすぐ隣にあるということです...これは本当に違いを生むでしょうか?
また、-Wl,--whole-archive などのオプションを使用してみましたが、役に立ちませんでした (さらに、それらを Automake によって生成された行に追加する方法がわかりません ...)