Ошибки компоновщика C++, неопределенные ссылки на элементы, на которые следует ссылаться из общего объекта.

Я создаю библиотеку под названием physgameengine, чтобы помочь в создании игр. Эта игровая библиотека связана с несколькими библиотеками, в том числе: Ogre3d, Bullet Physics и SDL, которые находятся в файлах библиотек libOgreMain-1.6.5.so, libBulletCollision.a, libBulletDynamics.a, libBulletSoftBody.a, libSDL-1.2.so.0. . Этот объект Library/Shared, по-видимому, прекрасно строится в Ubuntu 9.10 с использованием GCC и Code::blocks. Он отлично работает на Windows с mingw и Code::blocks.

В Windows я могу создавать игры, которые компилируются/связываются с использованием созданной мной библиотеки, эти программы работают и делают именно то, что я от них ожидаю. В Ubuntu, когда я пытаюсь скомпилировать/связать игру, использующую эту библиотеку, я получаю множество ошибок неопределенных ссылок. Но не к функциям или объектам в библиотеке, которую я создал, а скорее к элементам, которые вызывает моя библиотека. Вот пример ошибок, которые я получаю.

> ||warning: libOgreMain-1.6.5.so, needed by ../physgameengine/bin/ubuntudebug/libphysgame.so, not found (try using -rpath or -rpath-link)|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::Root(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::StringUtil::BLANK'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::updateAabbs()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::createRenderWindow(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, unsigned int, bool, std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const*)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Timer::getMilliseconds()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::createSceneManager(unsigned short, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::~Root()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::~btCollisionWorld()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::renderOneFrame()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionObject::btCollisionObject()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Timer::getMillisecondsCPU()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btSimulationIslandManager::buildAndProcessIslands(btDispatcher*, btCollisionWorld*, btSimulationIslandManager::IslandCallback*)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Viewport::getActualWidth() const'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::initialise(bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Camera::lookAt(Ogre::Vector3 const&)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::removeCollisionObject(btCollisionObject*)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Viewport::getActualHeight() const'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Timer::reset()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::restoreConfig()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Timer::~Timer()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::NedAllocImpl::deallocBytes(void*)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::convexSweepTest(btConvexShape const*, btTransform const&, btTransform const&, btCollisionWorld::ConvexResultCallback&, float) const'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::NedAllocImpl::allocBytes(unsigned int, char const*, int, char const*)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `typeinfo for btCollisionWorld'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionObject::~btCollisionObject()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btSimulationIslandManager::btSimulationIslandManager()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Root::showConfigDialog()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionObject::setActivationState(int)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::LogManager::getSingleton()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::performDiscreteCollisionDetection()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::LogManager::logMessage(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Ogre::LogMessageLevel, bool)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Timer::Timer()'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::btCollisionWorld(btDispatcher*, btBroadphaseInterface*, btCollisionConfiguration*)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `typeinfo for btCollisionObject'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `Ogre::Camera::setPosition(Ogre::Vector3 const&)'|
../physgameengine/bin/ubuntudebug/libphysgame.so||undefined reference to `btCollisionWorld::addCollisionObject(btCollisionObject*, short, short)'|
||=== Build finished: 36 errors, 1 warnings ===|

Основная часть кода идентична для Windows и Linux, они, кажется, имеют эквивалентные настройки компиляции/компоновки. Но игра для Linux, похоже, линкуется с оригинальными библиотеками, с которыми должна линковаться моя библиотека. Что здесь происходит? Любые идеи о том, как это исправить?


person Sqeaky    schedule 15.01.2010    source источник


Ответы (4)


В отличие от Windows, в системах Linux недостаточно поместить файл общей библиотеки в ту же папку, что и исполняемый файл.

Вы должны либо указать переменную LD_LIBRARY_PATH, либо последовать совету компоновщика и использовать -rpath (проверьте этот вопрос)

person P Shved    schedule 15.01.2010
comment
Я отмечаю этот ответ как ответ, потому что предоставленная ссылка заставила меня понять, что я смотрел на это совершенно неправильно. - person Sqeaky; 15.01.2010
comment
То же самое здесь. Не совсем тот ответ, который решил мою проблему, но заставил меня понять, что это был за ответ. - person robhasacamera; 09.04.2013

Самая первая строка вашей ошибки говорит вам о проблеме:

libOgreMain-1.6.5.so, needed by libphysgame.so, not found (try using -rpath or -rpath-link)|

Вам нужно указать каталог, в котором установлен libOgreMain. Поскольку вам нужно использовать опцию компоновщика, вам нужно использовать функцию -Wl gcc. Предполагая, что файлы находятся в /opt/lib, вы должны добавить:

gcc -Wl,-rpath-link,/opt/lib ...rest of linker line...
person R Samuel Klatchko    schedule 15.01.2010
comment
Добавлю ли я это в игру или в библиотеку. Если я добавлю это в игру, это удалит ключевое преимущество создания отдельной библиотеки? - person Sqeaky; 15.01.2010
comment
Я неправильно понял. Я думал, что это сделало что-то еще сначала. Это определяет, где этот исполняемый файл будет искать свои общие библиотеки, поэтому мне это действительно нужно в обоих, чтобы библиотека знала, где искать Ogre/bullet/что угодно, если только это не может быть определено обычными средствами во время компиляции, и мне это нужно в игра, чтобы найти мою библиотеку. - person Sqeaky; 15.01.2010

Просто на основе первой строки:

> ||warning: libOgreMain-1.6.5.so, needed by ../physgameengine/bin/ubuntudebug/libphysgame.so, not found (try using -rpath or -rpath-link)|

Похоже, ваш компоновщик не может найти ваш общий объект. Убедитесь, что пути включения вашего компоновщика настроены правильно.

person Adam Maras    schedule 15.01.2010
comment
Это предупреждение выдается при компиляции игры. Во-первых, он никогда не должен искать этот общий объект. - person Sqeaky; 15.01.2010

Это хорошая ссылка по теме http://sysprogs.com/w/fixing-rpath-link-issues-with-cross-compilers/

По сути, если у вас нет -lmylib для всех ваших библиотек, на которые вы ссылаетесь, вы не можете рассчитывать на -Lpath для их поиска. Таким образом, если /opt/infoa/lib/liba.so зависит от /opt/infod/lib/libd.so и вы указываете только -la, то вам нужно что-то вроде этого:

gcc -Wl,-rpath-ссылка,/opt/infod/lib -L/opt/infoa/lib -la *.c -o myexec

person edW    schedule 24.03.2015