Merge branch 'pyinstaller'

This commit is contained in:
Micah Lee 2017-02-21 17:16:16 -08:00
commit ab20311f6e
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
36 changed files with 143 additions and 150 deletions

View file

@ -34,35 +34,23 @@ For ArchLinux: There is a PKBUILD available [here](https://aur.archlinux.org/pac
Install Xcode from the Mac App Store. Once it's installed, run it for the first time to set it up.
If you don't already have it installed, install [Homebrew](http://brew.sh/).
Download and install Python 3.5.2 from https://www.python.org/downloads/release/python-352/ (note that a pyinstaller bug prevents you from using Python 3.6). I downloaded `python-3.5.2-macosx10.6.pkg`.
Install some dependencies using Homebrew:
Download and install Qt 5.7.1 for macOS offline installer from https://www.qt.io/download-open-source/. I downloaded `qt-opensource-mac-x64-clang-5.7.1.dmg`. (You can skip making an account in the installer.)
Now install some python dependencies with pip (note, there's issues building a .app if you install this in a virtualenv):
```sh
brew install python3 pyqt5 qt5
sudo pip3 install -r install/requirements.txt
```
Install some dependencies using pip3:
```sh
sudo pip3 install flask stem
```
After that you can try both the CLI and the GUI version of OnionShare:
You can run both the CLI and GUI versions of OnionShare without building an bundle:
```sh
./dev_scripts/onionshare
./dev_scripts/onionshare-gui
```
If you want to build a Mac OS X app bundle:
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`
To build the app bundle:
```sh
@ -83,9 +71,13 @@ Now you should have `dist/OnionShare.pkg`.
### Setting up your dev environment
Download the latest Python 3.6.x, 32-bit (x86) from https://www.python.org/downloads/. I downloaded `python-3.6.0.exe`. When installing it, make sure to check the "Add Python 3.6 to PATH" checkbox on the first page of the installer.
Download the latest Python 3.5.2, 32-bit (x86) from https://www.python.org/downloads/release/python-352/ (note that there's a pyinstaller/pywin32 bug that prevents 3.6.x from working). I downloaded `python-3.5.2.exe`. When installing it, make sure to check the "Add Python 3.5 to PATH" checkbox on the first page of the installer.
Open a command prompt and install dependencies with pip: `pip install flask stem PyQt5`
Open a command prompt, cd to the onionshare folder, and install dependencies with pip:
```cmd
pip3 install -r install\requirements-windows.txt
```
Download and install Qt5 from https://www.qt.io/download-open-source/. I downloaded `qt-unified-windows-x86-2.0.4-online.exe`. There's no need to login to a Qt account during installation. Make sure you install the latest Qt 5.x. I installed Qt 5.7.
@ -96,19 +88,17 @@ python dev_scripts\onionshare
python dev_scripts\onionshare-gui
```
If you want to build an .exe:
If you want to build a .exe:
These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH.
Download and install the [Microsoft Visual C++ 2008 Redistributable Package (x86)](http://www.microsoft.com/en-us/download/details.aspx?id=29).
Download and install the 32-bit [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-US/download/details.aspx?id=48145). I downloaded `vc_redist.x86.exe`.
Installing cx_Freeze with support for Python 3.5 is annoying. Here are the steps (thanks https://github.com/sekrause/cx_Freeze-Wheels):
Download and install the standalone [Windows 10 SDK](https://dev.windows.com/en-us/downloads/windows-10-sdk). Note that you may not need this if you already have Visual Studio. Add the following directories to the path:
* Download and install the Visual C++ Build Tools 2005 from http://go.microsoft.com/fwlink/?LinkId=691126. I downloaded `visualcppbuildtools_full.exe`.
* Install the python wheel package: `pip install wheel`
* 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: `python setup.py bdist_wheel`
* Install it with pip: `pip install dist\cx_Freeze-5.0-cp35-cp35m-win32.whl`
* `C:\Program Files (x86)\Windows Kits\10\bin\x86`
* `C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86`
* `C:\Users\user\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\PyQt5\Qt\bin`
If you want to build the installer:
@ -119,17 +109,12 @@ If you want to sign binaries with Authenticode:
* You'll need a code signing certificate. I roughly followed [this guide](http://blog.assarbad.net/20110513/startssl-code-signing-certificate/) to make one using my StartSSL account.
* Once you get a code signing key and certificate and covert it to a pfx file, import it into your certificate store.
* Windows 7:
* Go to http://msdn.microsoft.com/en-us/vstudio/aa496123 and install the latest .NET Framework. I installed `.NET Framework 4.6`.
* Go to http://www.microsoft.com/en-us/download/confirmation.aspx?id=8279 and install the Windows SDK.
* Add `C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin` to the path.
* Windows 10:
* Go to https://dev.windows.com/en-us/downloads/windows-10-sdk and install the standalone Windows 10 SDK. Note that you may not need this if you already have Visual Studio.
* Add `C:\Program Files (x86)\Windows Kits\10\bin\x86` to the path.
### To make a .exe:
* Open a command prompt, cd into the onionshare directory, and type: `python setup.py build`. `onionshare.exe`, `onionshare-gui.exe`, and all of their supporting files will get created inside the `build\exe.win32-3.5` folder.
For PyInstaller to work, you might need to edit `Scripts\pyinstaller-script.py` in your Python 3.5 folder, to work around [this bug](https://stackoverflow.com/questions/31808180/installing-pyinstaller-via-pip-leads-to-failed-to-create-process) in pip.
* Open a command prompt, cd into the onionshare directory, and type: `pyinstaller install\pyinstaller.spec`. `onionshare.exe`, `onionshare-gui.exe`, and all of their supporting files will get created inside the `build` folder.
### To build the installer:

View file

@ -3,7 +3,7 @@
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
cd $DIR
VERSION=`cat resources/version.txt`
VERSION=`cat share/version.txt`
# clean up from last build
rm -r deb_dist >/dev/null 2>&1

View file

@ -1,5 +1,5 @@
REM build onionshare.exe, onionshare-gui.exe
python setup.py build
pyinstaller install\pyinstaller.spec -y
REM sign onionshare.exe, onionshare-gui.exe
signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 build\exe.win32-3.5\onionshare.exe

View file

@ -9,7 +9,7 @@ rm -rf $ROOT/build $ROOT/dist &>/dev/null 2>&1
# build the .app
echo Building OnionShare.app
python3 setup.py bdist_mac
pyinstaller install/pyinstaller.spec
if [ "$1" = "--release" ]; then
mkdir -p dist

View file

@ -3,7 +3,7 @@
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
cd $DIR
VERSION=`cat resources/version.txt`
VERSION=`cat share/version.txt`
# clean up from last build
rm -r build dist >/dev/null 2>&1

View file

@ -7,7 +7,7 @@
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
cd $DIR
VERSION=`cat resources/version.txt`
VERSION=`cat share/version.txt`
rm -rf deb_dist >/dev/null 2>&1
python3 setup.py --command-packages=stdeb.command sdist_dsc

61
install/pyinstaller.spec Normal file
View file

@ -0,0 +1,61 @@
# -*- mode: python -*-
import platform
p = platform.system()
version = open('share/version.txt').read().strip()
a = Analysis(
['scripts/onionshare-gui'],
pathex=['.'],
binaries=None,
datas=[
('../share/license.txt', 'share'),
('../share/version.txt', 'share'),
('../share/wordlist.txt', 'share'),
('../share/images/*', 'share/images'),
('../share/locale/*', 'share/locale'),
('../share/html/*', 'share/html')
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=['jinja2.asyncsupport'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None)
pyz = PYZ(
a.pure, a.zipped_data,
cipher=None)
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 p == 'Darwin':
app = BUNDLE(
coll,
name='OnionShare.app',
icon='install/onionshare.icns',
bundle_identifier='com.micahflee.onionshare',
info_plist={
'CFBundleShortVersionString': version,
'NSHighResolutionCapable': 'True'
}
)

View file

@ -0,0 +1,13 @@
click==6.7
Flask==0.12
future==0.16.0
itsdangerous==0.24
Jinja2==2.9.5
MarkupSafe==0.23
pefile==2016.3.28
PyInstaller==3.2.1
pypiwin32==219
PyQt5==5.8
sip==4.19.1
stem==1.5.4
Werkzeug==0.11.15

10
install/requirements.txt Normal file
View file

@ -0,0 +1,10 @@
click==6.7
Flask==0.12
itsdangerous==0.24
Jinja2==2.9.5
MarkupSafe==0.23
PyInstaller==3.2.1
PyQt5==5.7.1
sip==4.19
stem==1.5.4
Werkzeug==0.11.15

View file

@ -37,16 +37,21 @@ def get_resource_path(filename):
if getattr(sys, 'onionshare_dev_mode', False):
# 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')
prefix = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))), 'share')
elif p == 'Linux' and sys.argv and sys.argv[0].startswith(sys.prefix):
# OnionShare is installed systemwide in Linux
resources_dir = os.path.join(sys.prefix, 'share/onionshare')
elif getattr(sys, 'frozen', False): # Check if app is "frozen" with cx_Freeze
# http://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files
resources_dir = os.path.join(os.path.dirname(sys.executable), 'resources')
prefix = os.path.join(sys.prefix, 'share/onionshare')
return os.path.join(resources_dir, filename)
elif getattr(sys, 'frozen', False):
# Check if app is "frozen"
# https://pythonhosted.org/PyInstaller/#run-time-information
if p == 'Darwin':
prefix = os.path.join(sys._MEIPASS, 'share')
elif p == 'Windows':
prefix = os.path.join(os.path.dirname(sys.executable), 'share')
return os.path.join(prefix, filename)
def get_version():

View file

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import os, sys, platform, tempfile
from distutils.core import setup
def file_list(path):
files = []
@ -28,7 +29,7 @@ def file_list(path):
files.append(os.path.join(path, filename))
return files
version = open('resources/version.txt').read().strip()
version = open('share/version.txt').read().strip()
description = (
"""OnionShare lets you securely and anonymously share a file of any size with someone. """
"""It works by starting a web server, making it accessible as a Tor hidden service, """
@ -45,62 +46,7 @@ url = 'https://github.com/micahflee/onionshare'
license = 'GPL v3'
keywords = 'onion, share, onionshare, tor, anonymous, web server'
p = platform.system()
# Windows and Mac
if p == 'Windows' or p == 'Darwin':
from cx_Freeze import setup, Executable
if p == '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 p == '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(
name='OnionShare', version=version,
description=description, long_description=long_description,
author=author, author_email=author_email,
url=url, license=license, keywords=keywords,
options={
'build_exe': {
'packages': ['jinja2.ext'],
'excludes': [],
'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
)
# Linux
else:
from setuptools import setup
setup(
setup(
name='onionshare', version=version,
description=description, long_description=long_description,
author=author, author_email=author_email,
@ -112,37 +58,10 @@ else:
(os.path.join(sys.prefix, 'share/applications'), ['install/onionshare.desktop']),
(os.path.join(sys.prefix, 'share/appdata'), ['install/onionshare.appdata.xml']),
(os.path.join(sys.prefix, 'share/pixmaps'), ['install/onionshare80.xpm']),
(os.path.join(sys.prefix, 'share/onionshare'), [
'resources/version.txt',
'resources/wordlist.txt'
]),
(os.path.join(sys.prefix, 'share/onionshare/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'
]),
(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']),
(os.path.join(sys.prefix, 'share/onionshare'), file_list('share')),
(os.path.join(sys.prefix, 'share/onionshare/images'), file_list('share/images')),
(os.path.join(sys.prefix, 'share/onionshare/locale'), file_list('share/locale')),
(os.path.join(sys.prefix, 'share/onionshare/html'), file_list('share/html')),
('/usr/share/nautilus-python/extensions/', ['install/scripts/onionshare-nautilus.py'])
]
)
)

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 346 B

After

Width:  |  Height:  |  Size: 346 B

View file

Before

Width:  |  Height:  |  Size: 286 B

After

Width:  |  Height:  |  Size: 286 B

View file

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

View file

@ -22,7 +22,7 @@ from onionshare import helpers, strings
# Stub get_resource_path so it finds the correct path while running tests
def get_resource_path(filename):
resources_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'resources')
resources_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'share')
path = os.path.join(resources_dir, filename)
return path
helpers.get_resource_path = get_resource_path