cx_Freeze Mac-构建停止在 _ctypes 用于 Homebrew-and-Python

cx_Freeze Mac-build stopped at _ctypes for Homebrew-and-Python

我们使用 cx_Freeze 在 Mac OS 下生成 python 应用程序的独立二进制构建。构建 运行 在构建机器(安装了 Homebrew-and-Python)下运行良好,但在客户端机器上失败并出现以下错误消息。

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/cx_Freeze/initscripts/__startup__.py", line 14, in run
      module.run()
  File "/usr/local/lib/python2.7/site-packages/cx_Freeze/initscripts/Console.py", line 26, in run
      exec(code, m.__dict__)
  File "./utest2.py", line 15, in <module>
      from ttLib import *
  File "ttLib.py", line 848, in init ttLib
      import ctypes
  File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 7, in <module>
      from _ctypes import Union, Structure, Array


ImportError: dlopen(/Users/gff/src/TextSeek_test/build/test_build/lib/_ctypes.so, 2): Symbol not found: __PySlice_AdjustIndices
  Referenced from: /Users/gff/src/TextSeek_test/build/test_build/lib/_ctypes.so
  Expected in: flat namespace
 in /Users/gff/src/TextSeek_test/build/test_build/lib/_ctypes.so

通过浏览关于“__PySlice_AdjustIndices”和"flat namespace"的Whosebug答案,我们怀疑这个错误是由系统默认版本和自制版本之间的python冲突引起的。

然后我们在客户机上使用“brew install python@2”,ctypes 错误消失了。我们运行“brew uninstall python@2”,返回了这个错误。

问题是:我们如何嵌入 homebrew-python 的必要部分来绕过这个 ctype 错误?

我们使用“otool -L lib/_ctypes.so”来了解动态链接文件的依赖性,它只显示了一个文件“/usr/lib/libSystem.B.dylib”。此文件似乎与 python.

无关

有什么前进的建议吗?


Dev Machine 信息:Mac High Sierra,python 2.7.15 64 位。使用 homebrew-python 构建。

setup.py 对于 cx_Freeze :

build_exe_options = {
    "packages":  ["wcwidth", "watchdog", "xlrd", "jinja2", "subprocess"],
    "excludes": [ "AppKit", "Carbon", "CoreFoundation", "Finder", "Foundation", "FSEvents", "objc"],
    "include_msvcr": True,
    "zip_include_packages":["winshell", "wcwidth", "watchdog", "pyhk", "xlrd", "jinja2",\
        "argh", "ctypes",  "email", "encodings" ]
    }
exeList = [Executable( "utest2.py", base = None, targetName= "utest")  ]

setup(  name = "XXX",
        description = u"XXX desc",
        options = {
            "build_exe": build_exe_options,
            'bdist_mac': {
                'bundle_name': "XXX",
            }

        },
        executables = exeList)
  1. 在客户端机器上,安装冻结的应用程序后,尝试手动复制所有动态库(.so.dylib,...?)将构建目录的 lib 子目录放入构建目录本身。还将构建目录中的所有动态库复制到其 lib 子目录中。这能解决问题吗?在构建机器上,您当然应该使用与 运行 未冻结应用程序相同的 python 版本来生成冻结的应用程序。

  2. 如果 1. 解决了问题,请找出需要复制哪些动态库才能使应用程序运行(即找出您所做的哪些手动复制操作是真正必要的) .在安装脚本中使用 build_exe optionsinclude_files 列表,让 cx_Freeze 在构建步骤中自动包含动态库。您可以使用元组 (source, destination) 作为 include_files 列表中的项目,让 cx_Freeze 将文件从 source 复制到特定的 destination 到构建目录中。

解释:我不知道Mac/OS。但我相信您描述的问题可能与 Windows 下 Microsoft Visual C++ Redistributable DLLs 的类似 issue 有关: cx_Freeze 5.1.1 includes packages in a lib subdirectory of build 目录,在以前的 cx_Freeze 版本中,它们曾经位于 build 目录本身。某些动态库需要在构建目录中找到,但被 cx_Freeze 错误地包含在 lib 子目录中,反之亦然。在构建机器上这通常不是问题,因为库的副本通常在系统路径中找到,但在客户端机器上通常在系统路径上找不到库的副本,或者是不兼容的副本。

顺便说一下,build_exe 选项 "include_msvcr": True 似乎在 cx_Freeze5.1.1 中不起作用,参见 this issue

我自己找到了解决方案。

此问题是由错误地 linked dylib 文件引起的。我们使用“otool -L”找到依赖关系并使用“install_name_tool -change”重新link它们逐个。程序终于运行了。