Search code examples
macospython-2.7homebrewcx-freeze

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


We use cx_Freeze to produce standalone binary build of our python application under Mac OS. The build runs well under the build machine (which has Homebrew-and-Python installed), but failed in client machine with following error messages.

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

By browsing stackoverflow answers about "__PySlice_AdjustIndices" and "flat namespace", we suspect this error was caused by the python conflict between system-default version and homebrew version.

Then we use "brew install python@2" in client machine, and the ctypes error disappeared. We run "brew uninstall python@2", this error returned back.

The question is : how can we embed necessary part of homebrew-python to bypass this ctype error?

We used "otool -L lib/_ctypes.so" to know the depenency of dynamic-linked file, it only showed out one file "/usr/lib/libSystem.B.dylib". This file seems to have no relation with python.

Any advice to move forward?


Dev Machine Info: Mac High Sierra, python 2.7.15 64bit. Use homebrew-python to build.

setup.py for 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)

Solution

  • I found the solution by myself.

    This issue is caused by wrongly linked dylib files. We use "otool -L" to find the dependency and re-link them with "install_name_tool -change" one by one. Finally the program works.