编译Automake生成的库时未定义的引用

时间:2010-01-10 16:03:37

标签: c++ automake

我在使用automake的项目中遇到了一个非常奇怪的链接错误。从手册中我所做的看起来非常简单,所以我真的很想知道我做错了什么......

我的项目有三个文件夹:

  • src / common,其中我将一些C ++文件编译成一个libube-common.a static lib
  • src / engine,我将一些文件编译成libube-engine.a static lib
  • src / client,其中......你猜对了,libue-client.a,还有一个文件ube.cpp是我的主要

每个库都使用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中)

然后,在我的主程序的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> >)'

起初我虽然是因为一些静态符号,但我也遇到了非静态符号的问题。

我检查了生成的libs,它似乎正确地包含了符号:

~/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


编辑:图书馆本身似乎有用,似乎是一个链接问题。我可以链接我的测试用例程序agaist他们。这是我的工作:

在文件夹src / common / tests中,有一个名为common-tests.cpp的main运行单元测试; common-tests bin链接到库libube-common.a(它只需要lib中的对象,因为它们是单元测试)

# 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这样的选项, - 整个存档但它没有帮助(加上我不知道如何将它们添加到Automake生成的行......)

1 个答案:

答案 0 :(得分:4)

这很可能是一个库排序问题 - 库越“普遍”,它应该在最后的链接行中发生。具体来说,GNU ld完全一次读取符号库,然后丢弃库中的所有其他符号,然后再转到下一个库指令。有各种解决方案(参见'ld'的手册页),但最简单的方法是重新排序Makefile.am中的行,以便在客户端和引擎库之后放置libube-common.a

请注意,Darwin ld 具有此行为,默认情况下会保留所有库符号(在链接期间可能会占用更多内存)。