مرجع غير محدد عند تجميع المكتبات التي تم إنشاؤها بواسطة Automake

StackOverflow https://stackoverflow.com/questions/2037538

  •  19-09-2019
  •  | 
  •  

سؤال

أحصل على خطأ ربط غريب جدا في المشروع الذي يستخدم Automake. ما أبدوه يبدو بسيطا جدا من الدليل، لذلك أتساءل حقا ما يمكنني فعله خطأ ...

يحتوي مشروعي على ثلاثة مجلدات:

  • SRC / شائع، حيث أرخص عددا من ملفات C ++ في libube-common.a ثابت
  • SRC / المحرك، حيث أرخص عدد من الملفات في محرك Libube.
  • SRC / العميل، الذي ... لقد خمنت ذلك، عميل Libue، وكذلك ملف واحد 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.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.

ولكن بشكل مباشر أنا افسدت في مكان ما، لذلك أي فكرة هو موضع ترحيب!

شكرا

دكتوراه


تحرير: يبدو أن المكتبة في حد ذاتها تعمل، ويبدو أنها مشكلة ربط. يمكنني ربط برامج حالات الاختبار الخاصة بي أجراها. إليك ما أقوم به:

في مجلد SRC / الشائع / الاختبارات، هناك رئيسي يسمى Test.cpp الذي يدير اختبارات الوحدة؛ يتم ربط صندوق الاختبارات الشائعة بالضغط على المكتبة 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

عند تشغيل الشيكات، يتم تجميع برنامج الاختبار بهذه الطريقة:

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، - أرشيف كامل، لكنه لم يساعد (بالإضافة إلى أنني لا أعرف كيفية إضافتها إلى الخط الذي تم إنشاؤه بأتمتة ...)

هل كانت مفيدة؟

المحلول

من المرجح أن تكون هناك مشكلات ترتيب مكتبة - كلما زادت مكتبة "المشتركة"، في وقت لاحق يجب أن تحدث في خط الارتباط النهائي. على وجه التحديد، يقرأ جنو LD المكتبات للرموز بالضبط بمجرد, ثم يتجاهل جميع الرموز الأخرى من المكتبة، قبل الانتقال إلى تعليمات المكتبة التالية. هناك حلول مختلفة (انظر صفحة الرجل ل "LD") ولكن أسهل واحد هو إعادة طلب الأسطر في makefile.am لوضع libube-common.a بعد العميل والحركة LIBS.

لاحظ أن داروين LD لا ليس لدينا هذا السلوك، فإنه يحافظ على جميع رموز المكتبة افتراضيا (والتي قد تستخدم ذاكرة أكثر بكثير أثناء الارتباط).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top