解决MacOS上的动态链接库问题(dyld相关)

0 阅读2分钟

遇到的问题

  1. git报错:

    dyld[86362]: Symbol not found: _iconv
      Referenced from: <0B17F88E-81CD-3265-A735-F54385122F74> /opt/homebrew/Cellar/git/2.46.0/bin/git
      Expected in:     <5E3C6B42-48F0-3444-ABA3-D9F7C90E124C> /opt/homebrew/Cellar/libiconv/1.18/lib/libiconv.2.dylib
    zsh: abort      git remote -v
    

    需要的文件明明是存在的,然后尝试修复:

    brew update
    brew upgrade
    brew reinstall git
    brew reinstall libiconv
    

    仍然错误,继续排查

    echo $DYLD_LIBRARY_PATH
    

    发现之前有过设置,于是执行

    unset $DYLD_LIBRARY_PATH
    

    之后就好了(unset仅对当前终端有效,永久修复需要删除~/.zshrc中的配置)

    原因:DYLD_LIBRARY_PATH 设置后,macOS 会优先加载路径中的 libiconv 版本,而不是 Git 编译时预期的 Homebrew libiconv 版本

  2. 但是unset了之后,操作psql又报错了(之前临时设置的DYLD_LIBRARY_PATH就是为了解决这个问题的):

    dyld[6824]: Library not loaded: @rpath/libpq.5.dylib
      Referenced from: <29FDBA1B-B4AA-3198-B7F6-CD3558E65EE1> ~/.cargo/bin/cli
      Reason: no LC_RPATH's found
    

    解释:

    1. 可执行文件里写的是 @rpath/libpq.5.dylib
    2. 但是这个可执行文件 并没有 在它的 Mach-O 头部声明任何 RPATH 路径
    3. 之前用 DYLD_LIBRARY_PATH 来告诉系统临时去找这些库,一旦 unset 后,就失去了线索

    类比:写了@/pages/index.tsx但是没有配置'@': path.resolve(__dirname, 'src')

    解决:

    install_name_tool -add_rpath /opt/homebrew/opt/libpq/lib ~/.cargo/bin/cli
    install_name_tool -add_rpath /opt/homebrew/opt/libiconv/lib ~/.cargo/bin/cli
    

    解释:将需要的目录添加进可执行文件的LC_RPATH

进行一些学习

  1. MacOS上的动态库文件.dylib属于Mach-O格式(具体为MH_DYLIB),Mach-O是Mach object的缩写,是iOS、macOS上用于存储程序、库的标准格式,比如任何应用程序.app/Content/MacOS中的可执行文件就属于这个格式(使用命令file file_name查看,举例输出:Mach-O 64-bit executable arm64)

  2. 一个Mach-O文件包含三个主要区域:

    • Header:包含文件类型、目标架构类型等
    • Load commands:描述文件在虚拟内存中的逻辑结构、布局,指定segment的虚拟内存地址,以及其它权限等
    • Raw segment data:在load commands中定义的segment的原始数据,每个segment包含一个或多个section。不同类型code、data,存储到不同section
  3. LC_RPATH 是什么:

    在 macOS 的 Mach-O 二进制格式中,LC代表Load Command,R代表Run-time,整体表示的是一个 "运行时搜索路径",是Mach-O Load Command 部分的一种

  4. otool工具用来查看Mach-O特定部分和段的内容,比如-h输出mach头部信息,-L输出该文件使用的共享库

  5. install_name_tool 是 macOS 系统下专门用于编辑Mach-O 格式可执行文件和动态库 的命令行工具

tips:MacOS系统(xcode)本身会有一些库,HomwBrew又会自己管理一些库,所以建议不要手动控制的DYLD_LIBRARY_PATH之类的东西,避免混乱