在macOS Big Sur上,使用Python加载dylib失败:`Symbol not found: ___addtf3`。

3

我在 Mac OS X Big Sur 11.1 上使用 python3.7 时,加载自定义的 mylib.dylib 出现了问题:

OSError                                   Traceback (most recent call last)
<ipython-input-7-21ad9f6d803b> in <module>
     12 try:
---> 13     mylib = ctypes.CDLL(mylib_path)
     14 except OSError:

~/opt/anaconda3/lib/python3.7/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error)
    363         if handle is None:
--> 364             self._handle = _dlopen(self._name, mode)
    365         else:

OSError: dlopen(mylib.dylib, 6): Symbol not found: ___addtf3
  Referenced from: /usr/local/opt/gcc/lib/gcc/10/libquadmath.0.dylib
  Expected in: flat namespace
 in /usr/local/opt/gcc/lib/gcc/10/libquadmath.0.dylib

然而,在Mac OS X Big Sur 11.1上,使用完全相同的python代码成功加载了mylib.dylib此外,当将mylib编译为可执行文件而不是共享库时,在我的Big Sur 11.1上运行完全相同的mylib二进制文件也是成功的。

详细的步骤描述如下:

  1. 我使用bazel在Mac OS X Big Sur 11.1上构建了一个C++代码的共享库:
bazel build :mylib.dylib

BUILD文件:

cc_binary(
    name = "mylib.dylib",
    srcs = ["mylib.cc", "mylib.h", "mylib_external.cc", "mylib_external.h"],
    deps = [
        ...some dependencies...
    ],
    linkshared = 1,
)

.bazelrc 文件内容如下:

# Basic build settings
build --jobs 128
build --define='absl=1'
build --enable_platform_specific_config

# macOS
build:macos --cxxopt=-std=c++17
build:macos --host_cxxopt=-std=c++17
build:macos --copt=-w

# Sets the default Apple platform to macOS.
build --apple_platform_type=macos

# Allow debugging with XCODE
build --apple_generate_dsym

build:darwin_x86_64 --apple_platform_type=macos
build:darwin_x86_64 --macos_minimum_os=10.12
build:darwin_x86_64 --cpu=darwin_x86_64
  1. 然后我尝试在Python3.7中加载它:
import sys, platform
import ctypes, ctypes.util

mylib_path = ctypes.util.find_library("mylib")
if not mylib_path:
    print("Unable to find the specified library.")
    sys.exit()

try:
    mylib = ctypes.CDLL(mylib_path)
except OSError:
    print("Unable to load the specified library.")
    sys.exit()

它给我:

OSError                                   Traceback (most recent call last)
<ipython-input-7-21ad9f6d803b> in <module>
     12 try:
---> 13     mylib = ctypes.CDLL(mylib_path)
     14 except OSError:

~/opt/anaconda3/lib/python3.7/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error)
    363         if handle is None:
--> 364             self._handle = _dlopen(self._name, mode)
    365         else:

OSError: dlopen(mylib.dylib, 6): Symbol not found: ___addtf3
  Referenced from: /usr/local/opt/gcc/lib/gcc/10/libquadmath.0.dylib
  Expected in: flat namespace
 in /usr/local/opt/gcc/lib/gcc/10/libquadmath.0.dylib

关于同样问题的一个可能解决方案已经在这个GitHub问题中讨论过,但对我来说,更改DYLD_LIBRARY_PATH无效。

  1. 我尝试将路径设置为libquadmath.0.dylib中的libgcc_ext.10.4.dylib
install_name_tool -change /usr/lib/libSystem.B.dylib /usr/local/opt/gcc/lib/gcc/10/libgcc_ext.10.4.dylib /usr/local/opt/gcc/lib/gcc/10/libquadmath.0.dylib

这可能有所帮助,因为在Big Sur 11.1上没有/usr/lib/libSystem.B.dylib文件(所以我想这个文件没有被使用),但是代之以新的错误:

OSError                                   Traceback (most recent call last)
<ipython-input-7-21ad9f6d803b> in <module>
     12 try:
---> 13     mylib = ctypes.CDLL(mylib_path)
     14 except OSError:

~/opt/anaconda3/lib/python3.7/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error)
    363         if handle is None:
--> 364             self._handle = _dlopen(self._name, mode)
    365         else:

OSError: dlopen(mylib.dylib, 6): Library not loaded: /usr/local/opt/gcc/lib/gcc/10/libgcc_ext.10.4.dylib
  Referenced from: /usr/local/opt/gcc/lib/gcc/10/libquadmath.0.dylib
  Reason: no suitable image found.  Did find:
    /usr/local/opt/gcc/lib/gcc/10/libgcc_ext.10.4.dylib: mach-o, but wrong filetype
    /usr/local/Cellar/gcc/10.2.0/lib/gcc/10/libgcc_ext.10.4.dylib: mach-o, but wrong filetype
  1. 我也尝试了brew reinstall gcc,在执行此操作之前,实际问题中的/usr/local/libSystem.B.dylib代替了flat namespace

  2. 还有一些相关问题:scipyscipy.specialscipy._fblasgdal2。它们的解决方法并没有帮助,因为通常都是重新安装软件包,但这里我要使用自己的软件包。

  3. 最后,我尝试在使用bazel构建时设置CC=clang/g++/g++-10。不幸的是,这并没有起作用。

欢迎提出任何建议和想法。提前感谢您的帮助。


1
___addtf3是gcc运行时函数,通常在libgcc_s共享库中定义。您的自定义dylib是否引用了此库? - n. m.
谢谢! 您的建议帮助我找到了解决方案,我将在“答案”中详细描述它。 - Ilya Zakharkin
1个回答

1

根据评论中@n. 'pronouns' m.的建议,我尝试链接libgcc_s而不是libSystem:

install_name_tool -change "/usr/lib/libSystem.B.dylib" "/usr/local/opt/gcc/lib/gcc/10/libgcc_s.1.dylib" mylib.dylib

它给了我另一个错误:Symbol not found: ___emutls_get_address 来自于 libopenblas。我谷歌搜索并找到了 this SO answer,然后执行了以下操作:
brew link --overwrite gcc

然后我所做的唯一一件事情就是使用bazel按照之前完全相同的规则重新构建了mylib.dylib,结果它成功了!现在该库可以在Python中加载而不会出现任何错误。非常感谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接