我有一个名为myBinary
的胖(32位和64位)Intel二进制文件无法在运行Mac OS X 10.8.2的另一个工作站上运行:
$ myBinary
dyld: lazy symbol binding failed: Symbol not found: __ZNSt8__detail15_List_node_base7_M_hookEPS0_
Referenced from: /usr/local/bin/myBinary
Expected in: /usr/lib/libstdc++.6.dylib
dyld: Symbol not found: __ZNSt8__detail15_List_node_base7_M_hookEPS0_
Referenced from: /usr/local/bin/myBinary
Expected in: /usr/lib/libstdc++.6.dylib
Trace/BPT trap: 5
我是从运行GCC 4.7.2的Mac OS X 10.8.2工作站编译的:
$ gcc --version
gcc (MacPorts gcc47 4.7.2_2+universal) 4.7.2
我跑了nm
,符号未定义:
$ nm /usr/local/bin/myBinary | grep __ZNSt8__detail15_List_node_base7_M_hookEPS0_
U __ZNSt8__detail15_List_node_base7_M_hookEPS0_
编译myBinary
时我错过了什么或做错了什么?我不知道我能在/usr/lib/libstdc++.6.dylib
中对丢失的符号做些什么 - 我是否应该将C ++库静态编译为myBinary
?
答案 0 :(得分:2)
是的,你有两个选择,要么不使用客户不会拥有的库......(你可以将它们作为dyld或框架提供。)
或者只是静态地链接库...如果你的包只是一个进程,这实际上最终会减少内存和磁盘空间,因为你可以删除你不使用的符号。
答案 1 :(得分:1)
每个C ++编译器都有自己的标准C ++库实现。由于您使用的是外部编译器(GCC 4.7),因此在Mac OS X的标准安装中无法使用其库。
您唯一的选择是在您的应用中捆绑图书馆或静态链接。
使用应用程序捆绑库:
使用install_name_tool
确保您的应用在需要时找到它
E.g。您可以将dylib放入.app / Contents / Frameworks,将其安装名称设置为@rpath
并使用-rpath @executable_path/../Frameworks
编译应用程序。
答案 2 :(得分:0)
我在使用MacPorts GCC 4.8编译10.6时遇到了同样的问题,然后尝试在没有MacPorts的情况下在新的10.9安装上运行我的应用程序。幸运的是我找到了你的问题,肯佐的回答引导我朝着正确的方向指导为什么问题发生了......但它并没有真正提供我正在寻找的解决方案。
首先,我将解释为什么它在您的系统上正确运行:MacPorts为您的系统提供了libstdc ++的版本,GCC 4.7为/ opt / local / lib而不是/ usr / lib提供符号。这就是我的样子(GCC 4.8通用):
$ find /opt/local/lib -name 'libstdc++.*'
/opt/local/lib/gcc48/i386/libstdc++.6.dylib
/opt/local/lib/gcc48/i386/libstdc++.a
/opt/local/lib/gcc48/i386/libstdc++.a-gdb.py
/opt/local/lib/gcc48/i386/libstdc++.dylib
/opt/local/lib/gcc48/i386/libstdc++.la
/opt/local/lib/gcc48/libstdc++.6.dylib
/opt/local/lib/gcc48/libstdc++.a
/opt/local/lib/gcc48/libstdc++.a-gdb.py
/opt/local/lib/gcc48/libstdc++.dylib
/opt/local/lib/gcc48/libstdc++.la
/opt/local/lib/libgcc/libstdc++.6.dylib
/opt/local/lib/libstdc++.6.dylib
您可以看到您的应用与otool -L
链接的内容:
$ otool -L myBinary
myBinary:
/opt/local/lib/libgcc/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.18.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 832.0.0)
/opt/local/lib/libgcc/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
在最终的gcc构建步骤(调用链接器的步骤)中,提高可移植性的最简单方法是-static-libstdc++ -static-libgcc
。您需要两者,因为动态libgcc将带来动态libstdc ++绑定,因此仅仅请求静态libstdc ++是不够的。对于一个简单的应用程序,这是你的gcc行可能是什么样的:
g++ -static-libstdc++ -static-libgcc myBinary.cpp -o myBinary
但是,根据gcc man page about linker options,静态链接libgcc在处理跨库的异常时会导致问题。我没有遇到过它的问题,但你可能会这样。
所以,要做到Kentzo的方式,首先你应该从MacPorts获得最新的install_name_tool,这样就不会被未知的加载命令搞糊涂了:
sudo port install cctools +universal
现在,让我们改变路径,以便搜索可执行文件的目录:
/opt/local/bin/install_name_tool -change /opt/local/lib/libgcc/libstdc++.6.dylib '@executable_path/libstdc++.6.dylib'
/opt/local/bin/install_name_tool -change /opt/local/lib/libgcc/libgcc_s.1.dylib '@executable_path/libgcc_s.1.dylib'
现在您只需要将这些dylib与应用程序一起分发。如果您正在制作.app,请将dylib复制到myBinary.app/Contents/MacOS /。
最后一点说明:如果您在创建一个好的通用二进制文件时遇到问题,可以单独构建架构(使用不同的编译器和选项),然后将它们与lipo合并:
/usr/bin/g++ -arch i686 -mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk myBinary.cpp -o myBinary_32
/opt/local/bin/g++ -arch x86_64 -static-libstdc++ -static-libgcc myBinary.cpp -o myBinary_64
lipo myBinary_32 myBinary_64 -create -output myBinary