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

后端 未结 3 423
旧时难觅i
旧时难觅i 2020-12-19 03:10

I have a fat (32- and 64-bit) Intel binary called myBinary that fails to run on another workstation running Mac OS X 10.8.2:

$ myBinary
dyld: la         


        
3条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-19 03:33

    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
    

提交回复
热议问题