J'ai une erreur de liaison assez étrange dans un projet qui utilise automake. Ce que je semble assez simple du manuel, donc je me demande vraiment ce que je peux faire mal ...Référence non définie lors de la compilation des bibliothèques générées par Automake
Mon projet a trois dossiers:
- src/commune, où je compile un certain nombre de C++ fichiers dans un libube-common.a static lib
- src/engine, dans lequel je compiler un certain nombre de fichiers dans un libube-engine.a static lib
- src/client, dans lequel ... vous l'avez deviné, libue-client.a, et aussi un fichier ube.cpp qui est mon principal
Chacune des bibliothèques est compilé avec un Makefile.am comme ceci:
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)
Il en résulte les divers objets en cours de construction avec une ligne comme:
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
Et tous sont mis en la bibliothèque:
ar cru libube-common.a logging.o prefix_resource_resolver.o stat_file_checker.o
ranlib libube-common.a
Tout cela semble bon et bien, je peux même lié quelques petits programmes de tests contre la bibliothèque (dans le même makefile)
Puis, dans le Makefile.am de mon programme principal, j'ai demandé de lier avec les bibliothèques locales:
ube_LDADD=../common/libube-common.a \
../engine/libube-engine.a \
libube-client.a \
... other libs ...
Et c'est là que je reçois des erreurs comme ceci:
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> >)'
Dans un premier temps Je pensais que c'était à cause de certains symboles statiques, mais j'ai aussi le problème avec ceux qui ne sont pas statiques.
J'ai vérifié les libs générés, et il semble contenir le symbole correctement:
~/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
La seule solution est de lier mes fichiers contre explicitement .o (en les ajoutant à la ligne ... mais ube_LDADD qui défie un peu l'idée d'utiliser une bibliothèque !!)
Il me semble avoir suivi le manuel: http://www.gnu.org/software/hello/manual/automake/Linking.html#Linking
Mais je ovbiously foiré quelque part, de sorte que toute idée est la bienvenue !!
Merci
PH
EDIT: La bibliothèque en elle-même semble fonctionner, il semble être un problème de liaison. Je peux lier mes programmes de cas de test à leur taille. Voici ce que je fais:
Dans le dossier src/common/tests, il y a un principal appelé common-tests.cpp qui exécute des tests unitaires; la poubelle de tests communs est liée à la bibliothèque libube-common.un (dont il a besoin que les objets qui sont à l'intérieur du lib, puisque ce sont des tests unitaires)
# 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
Lors de l'exécution faire vérifier, le programme de test est compilé de cette façon:
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
Et les choses fonctionnent parfaitement. La seule différence que je peux voir est que dans ce cas, la bibliothèque est juste à côté de l'exécutable à relier ... cela pourrait-il vraiment faire une différence?
Aussi, j'ai essayé d'utiliser des options comme -Wl, - l'archive complète, mais il n'a pas aidé (plus je ne sais pas comment les ajouter à la ligne générée par Automake ...)
Ces mêmes bibliothèques fonctionnent sur votre plate-forme? Vous pouvez les lier à un petit testcase? – Potatoswatter
Normalement, es, voir mes modifications ... – phtrivier