cloudmatrix / esky

an auto-update framework for frozen python apps
BSD 3-Clause "New" or "Revised" License
362 stars 74 forks source link

OSX fcntl not bundled? #66

Closed MagnusKnutas closed 6 years ago

MagnusKnutas commented 10 years ago

When i run my setup everything works except that esky do not include fcntl to my .app (in the OSX version) code:

import sys
from esky.bdist_esky import Executable
from distutils.core import setup
from glob import glob

subversion = 1
version = "1.0.%s"
data_files = ["myapp.ico"]

if sys.platform in ['win32', 'cygwin', 'win64']:
    data_files = [("images", glob(r'.\images\*.*'))]

    # We can customuse the executable's creation by passing an instance
    #  of Executable() instead of just the script name.
    example = Executable("main.py",
                         #  give our app the standard Python icon
                         icon="myapp.ico",
                         #  we could make the app gui-only by setting this to True
                         gui_only=False,
                         #  any other keyword args would be passed on to py2exe
    )

    setup(
        data_files=data_files,
        name="myapp",
        version=version % subversion,
        scripts=[example],
        options={"bdist_esky": {
            #  forcibly include some other modules
            "includes": [],
            #  forcibly exclude some other modules
            "excludes": ["pydoc"],
            #  force esky to freeze the app using py2exe
            "freezer_module": "py2exe",
            #  tweak the options used by py2exe
            "freezer_options": {
                "dll_excludes": ['MSVCP90.dll', 'w9xpopen.exe'],
                'bundle_files': 1,
                'compressed': True
            },
        }}
    )

if sys.platform == 'darwin':
    app = ['main.py']

    example = Executable("main.py",
                         icon="myapp.ico",
    )

    options = {
        "bdist_esky": {
            # forcibly include some other modules
            "includes": ['fcntl'],
            #  forcibly exclude some other modules
            "excludes": ["pydoc"],
            #  force esky to freeze the app using py2app
            "freezer_module": "py2app",
            #  tweak the options used by py2app
            "freezer_options": {
                "plist": {
                    'argv_emulation': True,
                    'packages': [],
                }
            },
        }
    }

    setup(
        app=app,
        name="myapp",
        version=version % subversion,
        data_files=data_files,
        options=options,
        scripts=[example],
    )

When i run program

    File "dist/myapp.app/Contents/Resources/__boot__.py", line 68, in <module>
    ImportError: No module named fcntl
loopingz commented 10 years ago

I've had the same issue, and it was because i used the default python from MacOS X ( /usr/bin/python ) if i use the one from ( /usr/local/bin/python ) it works

djoproject commented 8 years ago

The solution from loopingz didn't work in my case, there is no /usr/local/bin/python on my operating system.

But I found a workaround. I already had the same kind of issue with py2app alone and it seems to be the same issue with esky when using py2app.

For an unknown reason, py2app does not look for python modules on the host computer, it only looks in the ####.app directories. And guess what ? Because fcntl is a standard python package, it is not packaged with in the ####.app.

The solution consists to indicate to py2app to look after python modules in the host directories. Here is the solution:

In the setup.py file

    setup_kwargs['options'] = {
        'py2app': {
            'plist': {
                'PyResourcePackages': [
                    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/'
                    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/'
                ]
            }
        },
        'bdist_esky': {
            'freezer_module': 'py2app',
            'freezer_options': {
                'plist': {
                    'PyResourcePackages': [
                         '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/'
                         '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/'
                    ]
                }
            }
        }
    }

This solution is verbose on purpose and can be easily improved/simplified. Notice the fact that the plist informations are duplicated in py2app and in freezer_options. Esky does not retrieve information from py2app field and py2app does not retrieve information from bdist_esky field... So if you want to have a generic setup.py able to build app with py2app or with esky+py2app, the information needs to be duplicated.

For a basic application, only these two directories need to be added in PyResourcePackages, but if you use advanced application, for example with a graphical interface, maybe more directories need to be added. In my case, the app uses wxPython, and the following directory was needed: /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/

rfk commented 6 years ago

Thanks for reaching out. Unfortunately this project is no longer actively maintained, so I'm going to move it into archive mode:

https://rfk.id.au/blog/entry/archiving-open-source-projects/