[英]Using a shared library linked with other shared libs
我已经在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
标志和可执行文件的库,并且后者起作用了。 能否请任何人告诉我为什么? 可能是我已经用这些标志编译过的boost库吗?
再次感谢!
您遇到的最重要的问题是,您没有将应用程序与提供使用的符号的库链接起来。
您的错误消息指出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
,并确保每个组件都链接到其使用的符号所必需的库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.