Migrate from PyInstaller to cx_Freeze for OSX

This commit is contained in:
Micah Lee 2016-09-04 19:21:09 -07:00
parent 79938e9518
commit db9d81ba90
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
6 changed files with 123 additions and 150 deletions

View File

@ -62,9 +62,15 @@ brew install python3 pyqt5 qt5
Install some dependencies using pip3: Install some dependencies using pip3:
```sh ```sh
sudo pip3 install pyinstaller flask stem sudo pip3 install flask stem
``` ```
Install the latest development version of cx_Freeze:
* Download a [snapshot](https://bitbucket.org/anthony_tuininga/cx_freeze/downloads) of the latest development version of cx_Freeze, extract it, and cd into the folder you extracted it to
* Build the package: `python3 setup.py bdist_wheel`
* Install it with pip: `sudo pip3 install dist/cx_Freeze-5.0-cp35-cp35m-macosx_10_11_x86_64.whl`
Get the source code: Get the source code:
```sh ```sh
@ -83,7 +89,7 @@ Now you should have `dist/OnionShare.app`.
To codesign and build a .pkg for distribution: To codesign and build a .pkg for distribution:
```sh ```sh
install/build_osx.sh --sign install/build_osx.sh --release
``` ```
Now you should have `dist/OnionShare.pkg`. Now you should have `dist/OnionShare.pkg`.

18
install/Info.plist Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>onionshare-gui</string>
<key>CFBundleIdentifier</key>
<string>com.micahflee.onionshare</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>CFBundleShortVersionString</key>
<string>{VERSION}</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
</dict>
</plist>

View File

@ -5,19 +5,27 @@ cd $ROOT
# deleting dist # deleting dist
echo Deleting dist folder echo Deleting dist folder
rm -rf $ROOT/dist &>/dev/null 2>&1 rm -rf $ROOT/build $ROOT/dist &>/dev/null 2>&1
# build the .app # build the .app
echo Building OnionShare.app echo Building OnionShare.app
pyinstaller install/pyinstaller.spec python3 setup.py bdist_mac
if [ "$1" = "--sign" ]; then if [ "$1" = "--release" ]; then
SIGNING_IDENTITY_APP="3rd Party Mac Developer Application: Micah Lee" mkdir -p dist
SIGNING_IDENTITY_INSTALLER="3rd Party Mac Developer Installer: Micah Lee" APP_PATH="build/OnionShare.app"
PKG_PATH="dist/OnionShare.pkg"
IDENTITY_NAME_APPLICATION="Developer ID Application: Micah Lee"
IDENTITY_NAME_INSTALLER="Developer ID Installer: Micah Lee"
# codesign the .app echo "Codesigning the app bundle"
codesign -vvvv --deep -s "$SIGNING_IDENTITY_APP" dist/OnionShare.app codesign --deep -s "$IDENTITY_NAME_APPLICATION" "$APP_PATH"
# build .pkg echo "Creating an installer"
productbuild --component dist/OnionShare.app /Applications dist/OnionShare.pkg --sign "$SIGNING_IDENTITY_INSTALLER" productbuild --sign "$IDENTITY_NAME_INSTALLER" --component "$APP_PATH" /Applications "$PKG_PATH"
echo "Cleaning up"
rm -rf "$APP_PATH"
echo "All done, your installer is in: $PKG_PATH"
fi fi

View File

@ -1,62 +0,0 @@
# -*- mode: python -*-
import platform
system = platform.system()
version = open('resources/version.txt').read().strip()
block_cipher = None
a = Analysis(
['scripts/onionshare-gui'],
pathex=['.'],
binaries=None,
datas=[
('../resources/images/*', 'images'),
('../resources/locale/*', 'locale'),
('../resources/html/*', 'html'),
('../resources/version.txt', '.'),
('../resources/wordlist.txt', '.')
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(
a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
exclude_binaries=True,
name='onionshare',
debug=False,
strip=False,
upx=True,
console=False)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='onionshare')
if system == 'Darwin':
app = BUNDLE(
coll,
name='OnionShare.app',
icon='install/onionshare.icns',
bundle_identifier='com.micahflee.onionshare',
info_plist={
'CFBundleShortVersionString': version,
'NSHighResolutionCapable': 'True'
}
)

View File

@ -37,15 +37,9 @@ def get_resource_path(filename):
if p == 'Linux' and sys.argv and sys.argv[0].startswith('/usr/bin/onionshare'): if p == 'Linux' and sys.argv and sys.argv[0].startswith('/usr/bin/onionshare'):
# OnionShare is installed systemwide in Linux # OnionShare is installed systemwide in Linux
resources_dir = os.path.join(sys.prefix, 'share/onionshare') resources_dir = os.path.join(sys.prefix, 'share/onionshare')
elif getattr(sys, 'frozen', False): # Check if app is "frozen" with pyinstaller, cx_Freeze elif getattr(sys, 'frozen', False): # Check if app is "frozen" with cx_Freeze
# https://pythonhosted.org/PyInstaller/#run-time-information
# http://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files # http://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files
if p == 'Windows': resources_dir = os.path.join(os.path.dirname(sys.executable), 'resources')
# Windows is using cx_Freeze
resources_dir = os.path.join(os.path.dirname(sys.executable), 'resources')
else:
# OS X is using PyInstaller
resources_dir = sys._MEIPASS
else: # Look for resources directory relative to python file else: # Look for resources directory relative to python file
resources_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))), 'resources') resources_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))), 'resources')

147
setup.py
View File

@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os, sys, platform import os, sys, platform, tempfile
def file_list(path): def file_list(path):
files = [] files = []
@ -42,84 +42,69 @@ long_description = description + " " + (
author = 'Micah Lee' author = 'Micah Lee'
author_email = 'micah@micahflee.com' author_email = 'micah@micahflee.com'
url = 'https://github.com/micahflee/onionshare' url = 'https://github.com/micahflee/onionshare'
license = "GPL v3" license = 'GPL v3'
keywords = 'onion, share, onionshare, tor, anonymous, web server' keywords = 'onion, share, onionshare, tor, anonymous, web server'
os = platform.system() os = platform.system()
if os == 'Windows': # Windows and Mac
if os == 'Windows' or os == 'Darwin':
from cx_Freeze import setup, Executable from cx_Freeze import setup, Executable
if os == 'Windows':
executables = [
Executable('install/scripts/onionshare',
icon='install/onionshare.ico',
base=None),
Executable('install/scripts/onionshare-gui',
icon='install/onionshare.ico',
shortcutName='OnionShare',
shortcutDir='ProgramMenuFolder',
base='Win32GUI')
]
custom_info_plist = ''
elif os == 'Darwin':
executables = [
Executable('install/scripts/onionshare-gui'),
Executable('install/scripts/onionshare')
]
# Write the correct version into Info.plist
f = tempfile.NamedTemporaryFile(mode='w')
custom_info_plist = f.name
f.write(open('install/Info.plist').read().replace('{VERSION}', str(version)))
f.flush()
setup( setup(
name="OnionShare", name='OnionShare', version=version,
version=version, description=description, long_description=long_description,
description=description, author=author, author_email=author_email,
long_description=long_description, url=url, license=license, keywords=keywords,
author=author,
author_email=author_email,
url=url,
license=license,
keywords=keywords,
options={ options={
"build_exe": { 'build_exe': {
"packages": [], 'packages': ['jinja2.ext'],
"excludes": [], 'excludes': [],
"include_files": ['resources'] 'include_files': ['resources']
},
'bdist_mac': {
'iconfile': 'install/onionshare.icns',
'bundle_name': 'OnionShare',
'qt_menu_nib': '/usr/local/Cellar/qt5/5.6.1-1/plugins/platforms',
'custom_info_plist': custom_info_plist
} }
}, },
executables=[ executables=executables
Executable("install/scripts/onionshare",
icon="install/onionshare.ico",
base=None),
Executable("install/scripts/onionshare-gui",
icon="install/onionshare.ico",
shortcutName="OnionShare",
shortcutDir="ProgramMenuFolder",
base="Win32GUI")
]
) )
# Linux
else: else:
images = [
'resources/images/logo.png',
'resources/images/drop_files.png',
'resources/images/server_stopped.png',
'resources/images/server_started.png',
'resources/images/server_working.png'
]
locale = [
'resources/locale/cs.json',
'resources/locale/de.json',
'resources/locale/en.json',
'resources/locale/eo.json',
'resources/locale/es.json',
'resources/locale/fi.json',
'resources/locale/fr.json',
'resources/locale/it.json',
'resources/locale/nl.json',
'resources/locale/no.json',
'resources/locale/pt.json',
'resources/locale/ru.json',
'resources/locale/tr.json'
]
html = [
'resources/html/index.html',
'resources/html/denied.html',
'resources/html/404.html'
]
from setuptools import setup from setuptools import setup
setup( setup(
name='onionshare', name='onionshare', version=version,
version=version, description=description, long_description=long_description,
description=description, author=author, author_email=author_email,
long_description=long_description, url=url, license=license, keywords=keywords,
author=author,
author_email=author_email,
url=url,
license=license,
keywords=keywords,
packages=['onionshare', 'onionshare_gui'], packages=['onionshare', 'onionshare_gui'],
include_package_data=True, include_package_data=True,
scripts=['install/scripts/onionshare', 'install/scripts/onionshare-gui'], scripts=['install/scripts/onionshare', 'install/scripts/onionshare-gui'],
@ -131,9 +116,33 @@ else:
'resources/version.txt', 'resources/version.txt',
'resources/wordlist.txt' 'resources/wordlist.txt'
]), ]),
(os.path.join(sys.prefix, 'share/onionshare/images'), images), (os.path.join(sys.prefix, 'share/onionshare/images'), [
(os.path.join(sys.prefix, 'share/onionshare/locale'), locale), 'resources/images/logo.png',
(os.path.join(sys.prefix, 'share/onionshare/html'), html), 'resources/images/drop_files.png',
'resources/images/server_stopped.png',
'resources/images/server_started.png',
'resources/images/server_working.png'
]),
(os.path.join(sys.prefix, 'share/onionshare/locale'), [
'resources/locale/cs.json',
'resources/locale/de.json',
'resources/locale/en.json',
'resources/locale/eo.json',
'resources/locale/es.json',
'resources/locale/fi.json',
'resources/locale/fr.json',
'resources/locale/it.json',
'resources/locale/nl.json',
'resources/locale/no.json',
'resources/locale/pt.json',
'resources/locale/ru.json',
'resources/locale/tr.json'
]),
(os.path.join(sys.prefix, 'share/onionshare/html'), [
'resources/html/index.html',
'resources/html/denied.html',
'resources/html/404.html'
]),
('/usr/share/nautilus-python/extensions/', ['install/scripts/onionshare-nautilus.py']), ('/usr/share/nautilus-python/extensions/', ['install/scripts/onionshare-nautilus.py']),
] ]
) )