PyInstaller
There was a question on dabo-users today regarding a spec file for PyInstaller. Lack of time prevents me from rewriting this at the moment. Here are the dependent files which you'll need to go through line-by-line to fix to your specifications. A lot of the complication in my code is due to:
- Working with multiple platforms using multiple freezing products (py2exe, PyInstaller, cx_freeze, py2app)
- Having different deployment targets for different modes (multiuser, single-user, and test)
- Using text-substitution (lots of the strings come from my App object)
Anyway, here are the files I use. I hope it helps!
* buildwin.bat (type 'buildwin' at the command line)
rmdir /s /q dist python -O setup.py %1 move dist\main*.exe dist\shutter_studio.exe del dist\tcl85.dll dist\tk85.dll dist\_tkinter.pyd del dist\*wx*richtext* del .\shutter_studio.exe deltree /s dist\support iscc setup.iss
* setup.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys from setup_util import locales, iconSubDirs, iconDir, getVersionTuple make_test_package = ("__TEST__" in sys.argv) if make_test_package: del sys.argv[sys.argv.index("__TEST__")] make_mu_package = ("__MU__" in sys.argv) if make_mu_package: del sys.argv[sys.argv.index("__MU__")] import os import glob if sys.platform.startswith("darwin"): from setuptools import setup import py2app elif sys.platform.startswith("linux"): from cx_Freeze import setup, Executable from App import App # The applications App object contains all the meta info: app = App(MainFormClass=None, test_version=make_test_package, mu_version=make_mu_package) _appName = app.getAppInfo("appName") _appShortName = app.getAppInfo("appShortName") _appFileStem = _appShortName.lower().replace(" ", "_") _appVersion = app.getAppInfo("appVersion") _appDescription = app.getAppInfo("appDescription") _copyright = app.getAppInfo("copyright") _authorName = app.getAppInfo("authorName") _authorEmail = app.getAppInfo("authorEmail") _authorURL = app.getAppInfo("authorURL") _authorPhone = app.getAppInfo("authorPhone") _appComments = ("This is custom software by %s.\r\n" "\r\n" "%s\r\n" "%s\r\n" "%s\r\n") % (_authorName, _authorEmail, _authorURL, _authorPhone) _appIcon = "./resources/icon_green.ico" if make_test_package: _script = "main_TEST.py" elif make_mu_package: _script = "main_MU.py" else: _script = "main.py" class Target: def __init__(self, **kw): self.__dict__.update(kw) # for the versioninfo resources self.version = _appVersion self.company_name = _authorName self.copyright = _copyright self.name = _appName self.description = _appDescription self.comments = _appComments self.script = _script self.other_resources = [(24, 1, manifest)] if _appIcon is not None: self.icon_resources = [(4, _appIcon)] if sys.platform.startswith("win"): _versionTupleStr = str(getVersionTuple(_appVersion)) vinfo = open("vinfo.txt.spec").read() % locals() open("vinfo.txt", "w").write(vinfo) spec = open("sbs_studio.spec.txt").read() % locals() open("sbs_studio.spec", "w").write(spec) os.system("python -O c:\python26\lib\site-packages\pyinstaller\Build.py sbs_studio.spec") if not make_mu_package: os.system("del dist\*mysql*") # Write out the setup.iss file for inno: iss = open("setup.iss.txt").read() % locals() open("setup.iss", "w").write(iss) sys.exit() data_files=[("db/sqlite", glob.glob("db/sqlite/*.sql")), ("resources", glob.glob(os.path.join(iconDir, "*.ico"))), ("resources", glob.glob("resources/*")), ("reports", glob.glob("reports/*")), ("messages", [i for i in glob.glob("messages/*") if ("messages%sold" % os.sep) not in i]), ("db/updates", glob.glob("db/updates/*"))] data_files.extend(iconSubDirs) data_files.extend(locales) if sys.platform.startswith("darwin"): options = {"py2app": {"includes": ["App", "__version__", "constants", "db.updates", "ui", "biz", "ss_common.lib.floatcanvas", "encodings", "wx", "wx.lib.calendar", "wx.gizmos"], "optimize": 2, "excludes": ["matplotlib", "Tkconstants","Tkinter","tcl", "_imagingtk", "PIL._imagingtk", "ImageTk", "PIL.ImageTk", "FixTk", "wxPython", ], "argv_emulation": True, "resources": data_files, "plist": dict(CFBundleGetInfoString=_appVersion, CFBundleIdentifier="com.sanbenitoshutter.sbs_studio", LSPrefersPPC=False, NSHumanReadableCopyright=_copyright ), "iconfile": "resources/logo_green.icns", } } setup(name="SBS Studio", app=[_script], version=_appVersion, description=_appDescription, author=_authorName, author_email=_authorEmail, url=_authorURL, options=options, #data_files=data_files, setup_requires=["py2app"] ) elif sys.platform.startswith("linux"): include_files = [(i[1], i[0]) for i in data_files] ### need to unpack the globbed files for cx_Freeze unpacked = [] for source, destination in include_files: for source_item in source: destination_item = os.path.join(destination, os.path.split(source_item)[-1]) unpacked.append((source_item, destination_item)) include_files = unpacked options = {"build_exe": {"include_files": include_files, "includes": ["wx.gizmos", "wx.lib.calendar", "numpy.core._internal", "numpy.distutils.unixccompiler", "distutils.unixccompiler"], "optimize": 2, "create_shared_zip": False }} setup(name="SBS Studio", version=_appVersion, description=_appDescription, executables=[Executable("sbs_studio.py", compress=True, appendScriptToExe=True, icon=_appIcon)], options=options)
- sbs_studio.spec.txt
# -*- mode: python -*- import sys sys.path.insert(0, r"c:\ss") from setup_util import localeDir, iconDir daboIconTree = Tree(iconDir, "resources", [".svn", "cards"]) daboLocaleTree = Tree(localeDir, "dabo.locale", [".svn"]) ssResourceTree = Tree(r"c:\ss\resources", "resources", [".svn"]) ssReportsTree = Tree(r"c:\ss\reports", "reports", [".svn", "*.py", "*.pyc", "*.pyo"]) ssDbTree = Tree(r"c:\ss\db\sqlite", "db\sqlite", [".svn"]) ssDbUpdatesTree = Tree(r"c:\ss\db\updates", "db\updates", [".svn", "*.pyc", "*.pyo", "readme"]) ssMessagesTree = Tree(r"c:\ss\messages", "messages", [".svn"]) a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), '%(_script)s'], pathex=['C:\\Python26\\Lib\\site-packages\\pyinstaller']) pyz = PYZ(a.pure) exe = EXE(pyz, a.scripts + [('O','','OPTION')], exclude_binaries=1, name="shutter_studio.exe", debug=False, strip=False, upx=True, console=False, icon='%(_appIcon)s', version='./vinfo.txt') coll = COLLECT( exe, a.binaries, a.zipfiles, a.datas, daboIconTree, daboLocaleTree, ssResourceTree, ssReportsTree, ssDbTree, ssDbUpdatesTree, ssMessagesTree, strip=False, upx=True, name='dist') app = BUNDLE(coll, name=os.path.join('dist', 'sbs_studio.app'))
- vinfo.txt.spec
VSVersionInfo( ffi=FixedFileInfo( filevers=%(_versionTupleStr)s, prodvers=%(_versionTupleStr)s, mask=0x3f, flags=0x0, OS=0x4, fileType=0x1, subtype=0x0, date=(0, 0) ), kids=[ StringFileInfo( [ StringTable( '000004b0', [StringStruct('Comments', 'Custom software by Paul McNett (p@ulmcnett.com)'), StringStruct('CompanyName', '%(_authorName)s'), StringStruct('FileDescription', '%(_appDescription)s'), StringStruct('FileVersion', '%(_appVersion)s'), StringStruct('LegalCopyright', '%(_copyright)s'), StringStruct('ProductName', '%(_appName)s'), StringStruct('ProductVersion', '%(_appVersion)s')]) ]), VarFileInfo([VarStruct('Translation', [0, 1200])]) ] )
- setup_util.py
import os import glob import dabo import dabo.icons daboDir = os.path.split(dabo.__file__)[0] # Find the location of the dabo icons: iconDir = os.path.split(dabo.icons.__file__)[0] iconSubDirs = [] def getIconSubDir(arg, dirname, fnames): if ".svn" not in dirname and "cards" not in dirname.lower() and dirname[-1] != "\\": icons = glob.glob(os.path.join(dirname, "*.png")) if icons: subdir = (os.path.join("resources", dirname[len(arg)+1:]), icons) iconSubDirs.append(subdir) os.path.walk(iconDir, getIconSubDir, iconDir) # locales: localeDir = "%s%slocale" % (daboDir, os.sep) #locales = [("dabo.locale", (os.path.join(daboDir, "locale", "dabo.pot"),))] locales = [] def getLocales(arg, dirname, fnames): if ".svn" not in dirname and dirname[-1] != "\\": #po_files = tuple(glob.glob(os.path.join(dirname, "*.po"))) mo_files = tuple(glob.glob(os.path.join(dirname, "*.mo"))) if mo_files: subdir = os.path.join("dabo.locale", dirname[len(arg)+1:]) locales.append((subdir, mo_files)) os.path.walk(localeDir, getLocales, localeDir) def getVersionTuple(ss_version): l = [int(i) for i in ss_version.split(".")] + [0] return tuple(l)
