Tengo un error de enlace bastante extraño en un proyecto que usa automake. Lo que hago parece bastante sencillo desde el manual, por lo que realmente preguntarse qué puedo hacer el mal ...Referencia no definida al compilar contra bibliotecas generadas por Automake
Mi proyecto tiene tres carpetas:
- src/común, en el que compila una serie de C++ archivos en un libube-common.a lib estático
- src/engine, en el que compilo una serie de archivos en un libube-engine.a lib estático
- src/client, en el cual ... lo adivinó, libue-client.a, y también un archivo ube.cpp que es mi principal
Cada una de las bibliotecas se compila con un Makefile.am así:
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)
Esto da lugar a los diversos objetos que se construyen con una línea como:
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
Y todos ellos se ponen en la biblioteca con:
ar cru libube-common.a logging.o prefix_resource_resolver.o stat_file_checker.o
ranlib libube-common.a
Todo esto parece bueno y bien, que incluso puede vinculada algunos programas de pequeñas pruebas en contra de la biblioteca (dentro de la misma makefile)
Luego, en el Makefile.am de mi programa principal, pedí a enlazar con las bibliotecas locales:
ube_LDADD=../common/libube-common.a \
../engine/libube-engine.a \
libube-client.a \
... other libs ...
y ahí es donde se producen errores como este:
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> >)'
Al principio Pensé que era debido a algunos símbolos estáticos, pero también tengo el problema con los no estáticos.
comprobado que las librerías generadas, y que parecen contener el símbolo correctamente:
~/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 única solución es vincular explícitamente en contra de mis archivos .o (añadiéndolos a la línea ube_LDADD ... pero que desafía un poco la idea de utilizar una biblioteca !!)
me parece que han estado siguiendo el manual: http://www.gnu.org/software/hello/manual/automake/Linking.html#Linking
Pero ovbiously metí la pata en algún lugar, por lo que cualquier idea es bienvenida !!
Gracias
PH
EDIT: La biblioteca en sí mismo parece funcionar, parece ser un problema de vinculación. Puedo vincular mis programas de casos de prueba contra ellos. Esto es lo que hago:
En la carpeta src/common/tests, hay una principal llamada common-tests.cpp que ejecuta pruebas unitarias; el bin de pruebas comunes está vinculado a la biblioteca libube-common.un (sólo necesita objetos que se encuentran dentro de la lib, ya que esos son pruebas unitarias)
# 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
Cuando se ejecuta make check, el programa de prueba se compila esta manera:
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
Y las cosas funcionan perfectamente. La única diferencia que puedo ver es que en este caso la biblioteca está justo al lado del ejecutable para vincular ... ¿podría esto realmente marcar la diferencia?
Además, he intentado usar opciones como -Wl, - todo el archivo, pero no sirvió de nada (además de que no sé cómo agregarlos a la línea generada por Automake ...)
¿Esas mismas bibliotecas funcionan en su plataforma? ¿Puedes vincularlos a una pequeña caja de prueba? – Potatoswatter
Normalmente, es, ver mis ediciones ... – phtrivier