Help getting package to find dynamic library

209 views
Skip to first unread message

Joshua Robbins

unread,
Feb 5, 2021, 4:48:28 AM2/5/21
to pyins...@googlegroups.com
Hello! I've been using PyInstaller gainfully for a while now, but a recent addition of a new package to my installer is causing me some troubles, and I'm stumped as to how one normally solves this issue.

The problem library is Capstone (https://pypi.org/project/capstone/), to be specific. Upon trying to load capstone in single-file Linux executable, it immediately crashes with this error:

     File "capstone/__init__.py", line 315, in <module>
    ImportError: ERROR: fail to load the dynamic library.

I can confirm that the dynamic library that it searches for, libcapstone.so, is present in the installer. I include libcapstone.so by passing it in the​ "binaries" argument to "Analysis" in my .spec file. The relevant code in Capstone that tries to load the library and fails is as such:

    _lib = "libcapstone.so"
    _found = False

    def _load_lib(path):
        lib_file = join(path, _lib)
        if os.path.exists(lib_file):
            return ctypes.cdll.LoadLibrary(lib_file)
        return None
    
    _cs = None
    
    _path_list = [os.getenv('LIBCAPSTONE_PATH', None),
                pkg_resources.resource_filename(__name__, 'lib'),
                join(split(__file__)[0], 'lib'),
                '',
                distutils.sysconfig.get_python_lib(),
                '/usr/lib64']
    
    for _path in _path_list:
        if _path is None: continue
        _cs = _load_lib(_path)
        if _cs is not None: break
    else:
        raise ImportError("ERROR: fail to load the dynamic library.")

What is the standard operating procedure for getting libraries linked to packages that look them up in pkg_resources? If there isn't a way, is there a method of ensuring the "LIBCAPSTONE_PATH" environment variable is set to "_MEIPASS" before any other code runs?

The information contained in this e-mail and any attachments from GrammaTech, Inc may contain confidential and/or proprietary information, and is intended only for the named recipient to whom it was originally addressed. If you are not the intended recipient, any disclosure, distribution, or copying of this e-mail or its attachments is strictly prohibited. If you have received this e-mail in error, please notify the sender immediately by return e-mail and permanently delete the e-mail and any attachments.

bwoodsend

unread,
Feb 6, 2021, 7:35:49 AM2/6/21
to PyInstaller

This is a pretty standard recipe for any missing DLL problems. Edit your spec file putting:

from PyInstaller.utils.hooks import collect_dynamic_libs

at the top then set the binaries argument to collect_dynamic_libs("capstone"):

a = Analysis(...,
             binaries=collect_dynamic_libs("capstone"),
             ...

Then rebuild using:

pyinstaller project-name.spec

Joshua Robbins

unread,
Feb 8, 2021, 11:06:19 AM2/8/21
to PyInstaller
Ah, so that's the trick. I tried it and I can confirm it works. Thanks a million for your help!
Reply all
Reply to author
Forward
0 new messages