Использование общей библиотеки, связанной с другими общими библиотеками

Я скомпилировал на OSX разделяемую библиотеку с некоторыми внешними зависимостями (boost, OpenGL):

g++ -dynamiclib -undefined suppress -flat_namespace -o "libMY_LIB.dylib" ./windowbase.o -lGL -lGLU -lGLUT -lboost_system -lboost_thread

Нет ошибок, file libMY_LIB.dylib результаты в Mach-O 64-bit dynamically linked shared library x86_64, а также otool -L libMY_LIB.dylib выходы:

libPixelsGL.dylib (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/GLUT.framework/Versions/A/GLUT (compatibility version 1.0.0, current version 1.0.0)
libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
libboost_thread.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

Теперь я пытаюсь связать исполняемый файл с libMY_LIB.dylib, используя только функции в MY_LIB.h (и скомпилировано в lib):

g++ -L"/path/to/MY_LIB" -o "Program" ./main.o -lMY_LIB

но это не удается, печать:

Undefined symbols for architecture x86_64:
"boost::system::system_category()", referenced from:
    __static_initialization_and_destruction_0(int, int)in main.o
    boost::mutex::mutex()in main.o
    boost::mutex::lock()    in main.o
    boost::mutex::unlock()    in main.o
"boost::system::generic_category()", referenced from:
    __static_initialization_and_destruction_0(int, int)in main.o
"boost::thread::detach()", referenced from:
    boost::thread::~thread()in main.o
ld: symbol(s) not found for architecture x86_64

Некоторое объяснение и / или помощь?

Спасибо!

РЕДАКТИРОВАТЬ

Я пытался связать библиотеку без -undefined suppress -flat_namespace флаги и исполняемый файл с ними, и последний работал. Может ли кто-нибудь сказать мне, почему? Может быть, это были улучшенные библиотеки, которые я скомпилировал с этими флагами?

Обновленное спасибо!

1 ответ

Решение

Наиболее существенная проблема, с которой вы столкнулись, заключается в том, что вы не связываете свое приложение с библиотеками, которые предоставляют символы, которые оно использует.

Ваше сообщение об ошибке вызывает main.o содержит ссылки на boost::system::system_category(), boost::system::generic_category(), а также boost::thread::detach(), Поэтому при связывании main.o в исполняемом двоичном файле вам нужно связать библиотеку, которая предоставляет эти символы, в этом случае, передав -lboost_system -lboost_thread,


Что касается -undefined suppress -flat_namespace: эти параметры влияют на обнаружение пропущенных символов во время сборки. В общем, вы должны избегать использования этих флагов, если у вас нет особых потребностей. Причина, по которой ваш главный исполняемый файл с этими флагами "работает", заключается в том, что вы попросили компоновщика не генерировать ошибки для пропущенных символов. Поскольку они не знают этих символов, они ничего не делают для того, чтобы библиотека, предоставляющая их, загружалась в адресное пространство вашего приложения во время выполнения. Вам повезло, так как символы предоставлены библиотеками, которые libMY_LIB.dylib также ссылки на.

Для иллюстрации рассмотрим простую тестовую библиотеку, liba.dylib, который экспортирует функцию a:

$ cat a.c
int a(void)
{
    return 1;
}
$ cc -dynamiclib -o liba.dylib a.c
$

И простое приложение, которое использует эту функцию:

$ cat main.c
#include <stdio.h>

extern int a(void);

int main(int argc, char **argv)
{
    fprintf(stderr, "a: %d\n", a());
    return 0;
}

Теперь давайте рассмотрим три подхода к привязке этой библиотеки к нашему приложению.

1) без указания библиотеки вообще

$ cc -o main main.c 
Undefined symbols for architecture x86_64:
  "_a", referenced from:
      _main in main-JmKbTd.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Это тот случай, о котором вы изначально сообщали в своем вопросе.

2) Указание -undefined suppress -flat_namespace

$ cc -undefined suppress -flat_namespace -o main main.c 
$

Это успешно создало исполняемый файл, но когда мы запускаем двоичный файл:

$ ./main 
dyld: lazy symbol binding failed: Symbol not found: _a
  Referenced from: /tmp/./main
  Expected in: flat namespace

dyld: Symbol not found: _a
  Referenced from: /tmp/./main
  Expected in: flat namespace

Trace/BPT trap: 5

В этом случае загрузчик во время выполнения не знает, что ему нужно загрузить liba.dylib найти функцию a:

$ otool -L main 
main:
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.0.0)
$ nm -m main | grep _a
                 (undefined) external _a
$ 

3) Правильно указать библиотеку

$ cc -L. -la -o main main.c 
$ ./main 
a: 1
$ 

И вы можете видеть, что двоичный main знает как загрузить liba.dylib и что это liba.dylib которая обеспечивает функцию a тот main использует:

$ otool -L main
main:
    liba.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.0.0)
$ nm -m main | grep _a
                 (undefined) external _a (from liba)
$ 

Таким образом, я рекомендую прекратить прохождение -undefined suppress -flat_namespace вообще при создании ваших библиотек и двоичных файлов, а также чтобы каждый компонент связывался с необходимыми библиотеками для символов, которые он использует.

Другие вопросы по тегам