Handling “dyld: lazy symbol binding failed: Symbol not found” error when nm does not find symbol

谁说胖子不能爱 提交于 2019-11-29 10:16:47

yeah you have 2 options, either not use libraries that the customer won't have... (you can provide them as a dyld or framework.)

or just statically link the library... this will actually end up being smaller in memory and disk space if your package is only one process, because you can strip symbols that you don't use.

Each C++ compiler has its own implementation of Standard C++ Library. Since you're using external compiler (GCC 4.7) its library is not available among standard installations of Mac OS X.

Your only options is to either bundle the library within your app or statically link it.

To bundle the library with the app:

  1. Update install name of the library using install_name_tool

  2. Ensure your app will find it when needed

E.g. you can put the dylib into .app/Contents/Frameworks, set its install name to @rpath and compile you app with the -rpath @executable_path/../Frameworks.

I ran into this same issue when compiling on 10.6 with MacPorts GCC 4.8, and then trying to run my application on a fresh 10.9 install without MacPorts. Luckily I found your question, and Kentzo's answer steered me in the right direction as to why the problem occurred... but it didn't really provide the solution I was looking for.

First, I'll explain why it runs on your system correctly: MacPorts has provided your system with the version of libstdc++ that GCC 4.7 is providing symbols for, under /opt/local/lib rather than /usr/lib. Here's what it looks like for me (with GCC 4.8 universal):

$ 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

And you can see what your application is linking to with 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)

The easiest way to improve portability is -static-libstdc++ -static-libgcc in your final gcc build step (the one that calls the linker). You need both because dynamic libgcc will bring dynamic libstdc++ binding with it, so it's not enough to simply request static libstdc++. For a simple application, here's what your gcc line might look like:

g++ -static-libstdc++ -static-libgcc myBinary.cpp -o myBinary

However, according to the gcc man page about linker options, statically linking libgcc can cause problems when handling exceptions across libraries. I haven't run into issues with it, but you might.

So, to do it Kentzo's way, first you should get the newest install_name_tool from MacPorts so it won't be confused by unknown load commands:

sudo port install cctools +universal

Now, let's change the path so it searches the executable's directory:

/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'

Now you just need to distribute these dylibs with the application. If you're making a .app, copy the dylibs to myBinary.app/Contents/MacOS/.

One final note: If you're having trouble making a good universal binary, it is possible to build the architectures separately (with different compilers and options) and then merge them with 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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!