Я скомпилировал на OSX общую библиотеку с некоторыми внешними зависимостями (увеличение, 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
флаги и исполняемый файл с ними, и последний работал. Может ли кто-нибудь сказать мне, почему? Может быть увеличение libs у меня были собраны с этими флагами?
Обновленное спасибо!
Наиболее существенная проблема, с которой вы столкнулись, заключается в том, что вы не связываете свое приложение с библиотеками, которые предоставляют символы, которые оно использует.
Ваше сообщение об ошибке вызывает 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
вообще при создании ваших библиотек и двоичных файлов, а также чтобы каждый компонент связывался с необходимыми библиотеками для символов, которые он использует.
Других решений пока нет …