Reputation: 154
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)
Upvotes: 1
Views: 551
Reputation: 154
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.
Upvotes: 1
Reputation: 2461
On the client machine, after installation of the frozen application, try to manually copy all dynamic libraries (.so
, .dylib
, ...?) which are in the lib
subdirectory of the build directory into the build directory itself. Copy also all dynamic libraries which are in the build directory into its lib
subdirectory. Does this solve the problem? On the build machine, you should of course use the same python version to produce the frozen application than you use to run the unfrozen application.
If 1. solves the problem, find out which dynamic libraries need to be copied in order that the application works (i.e. find out which of the manual copy actions you've done are really necessary). Use the include_files
list of the build_exe
options in your setup script to let cx_Freeze
include the dynamic library automatically at the build step. You can use a tuple (source, destination)
as item in the include_files
list to let cx_Freeze
copy a file from source
to a specific destination
into the build directory.
Explanation: I don't know Mac/OS. But I believe the issue you describe could be related to a similar issue with Microsoft Visual C++ Redistributable DLLs
under Windows: cx_Freeze
5.1.1 includes packages in a lib
subdirectory of the build directory, in the previous versions of cx_Freeze
they used to be in the build directory itself. Some dynamic libraries need to be found in the build directory but are erroneously included in the lib
subdirectory by cx_Freeze
or vice versa. On the build machine it is usually not a problem, because a copy of the library is usually found in the system path, but on the client machine often no copy of the library can be found on the system path, or an incompatible one.
By the way the build_exe
option "include_msvcr": True
does not seem to work in cx_Freeze
5.1.1, see this issue.
Upvotes: 0