new branch
This commit is contained in:
parent
181b8ada21
commit
a870c43188
|
@ -0,0 +1,110 @@
|
|||
======================
|
||||
InVEST Build Framework
|
||||
======================
|
||||
|
||||
Scripts, hooks, and instructions for creating a binary build of InVEST.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
* PyInstaller (see PyInstaller project for own OS-specific dependencies)
|
||||
* InVEST3
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Currently must call pyinstaller from same directory as spec file (b/c of spec file)
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ pyinstaller invest.spec
|
||||
|
||||
Distributable build stored in top-level `dist/` folder.
|
||||
|
||||
Planning
|
||||
--------
|
||||
|
||||
* Support for Linux
|
||||
* Support for Windows
|
||||
* Support for Mac OSX
|
||||
* Scripts to install InVEST dependencies
|
||||
|
||||
Notes on PyInstaller
|
||||
--------------------
|
||||
|
||||
Repository: https://github.com/pyinstaller/pyinstaller
|
||||
|
||||
Documentation: http://pythonhosted.org/PyInstaller/
|
||||
|
||||
Definitions
|
||||
~~~~~~~~~~~
|
||||
|
||||
scripts: the python scripts named at command line
|
||||
|
||||
pure: pure python modules needed by the scripts
|
||||
|
||||
binaries: non-python modules needed by the scripts
|
||||
|
||||
Stage 1: Dependency Analysis
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
a = Analysis() # contains lists of scripts, pure, and binaries
|
||||
|
||||
hooks.hookutils functions:
|
||||
|
||||
* get_package_paths(package)
|
||||
* hiddenimports = collect_submodules(package)
|
||||
* datas = collect_data_files(package)
|
||||
|
||||
.. code:: python
|
||||
|
||||
MERGE( [ (a, 'script_name', 'exec_name'), (b, 'b', 'b'), ... ] )
|
||||
|
||||
MERGE is used in multi-package bundles.
|
||||
|
||||
|
||||
Stage 2: Python File Compression
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
pyz = PYZ(a.pure) # contains the modules listed in a.pure
|
||||
|
||||
Stage 3: Create Executable Scripts
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
# contains what will be the executable file 'myscript'
|
||||
exe = EXE(a.scripts, a.binaries, a.zipfiles, a.datas, pyz, name="myscript", exclude_binaries=1)
|
||||
|
||||
Stage 4: Collect Files into Distributable Application
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
# creates the output folder
|
||||
COLLECT(exe, a.binaries, a.zipfiles, a.datas, name="dist")
|
||||
|
||||
|
||||
Notes on Preparing InVEST Repo for PyInstaller
|
||||
----------------------------------------------
|
||||
|
||||
In Setup.py's setup() function:
|
||||
|
||||
include_package_data=True,
|
||||
|
||||
Add MANIFEST.in with following:
|
||||
|
||||
recursive-include invest_natcap/
|
||||
|
||||
Add additional elif block to iui.executor import switch statement
|
||||
|
||||
from importlib import import_module
|
||||
|
||||
elif getattr(sys, 'frozen', False) and getattr(sys, '_MEIPASS', False):
|
||||
model = import_module(module)
|
||||
model_name = os.path.splitext(os.path.basename(module))[0]
|
||||
LOGGER.debug('Loading %s in frozen environment', model)
|
|
@ -0,0 +1,2 @@
|
|||
from hookutils import collect_submodules
|
||||
hiddenimports = collect_submodules('ctypes')
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
from PyInstaller.hooks.hookutils import collect_data_files
|
||||
datas = collect_data_files('fauxgeo')
|
|
@ -0,0 +1 @@
|
|||
hiddenimports = ['_proxy', 'utils', 'defs', 'h5ac']
|
|
@ -0,0 +1,3 @@
|
|||
from PyInstaller.hooks.hookutils import collect_data_files, collect_submodules
|
||||
datas = collect_data_files('invest_natcap')
|
||||
hiddenimports = collect_submodules('invest_natcap')
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
from hookutils import collect_submodules
|
||||
hiddenimports = collect_submodules('numpy')
|
Binary file not shown.
|
@ -0,0 +1,47 @@
|
|||
from PyInstaller.compat import is_win
|
||||
from PyInstaller.hooks.hookutils import get_package_paths, collect_data_files
|
||||
# from osgeo import gdal
|
||||
# import platform
|
||||
# import os
|
||||
# import glob
|
||||
|
||||
# files = []
|
||||
# if is_win:
|
||||
# files += [
|
||||
# 'geos_c.dll',
|
||||
# ]
|
||||
# # If shapely is present, use that version of GEOS_C.dll
|
||||
# try:
|
||||
# import shapely
|
||||
# pkg_dir = os.path.dirname(shapely.__file__)
|
||||
# except (ImportError, AssertionError) as error:
|
||||
# # ImportError is raised when we can't import shapely
|
||||
# # AssertionError is raised when the package path can't be found.
|
||||
# print 'Defaulting to osgeo pkg:', error
|
||||
# pkg_base, pkg_dir = get_package_paths('osgeo')
|
||||
|
||||
# osgeo_base, osgeo_dir = get_package_paths('osgeo')
|
||||
# data_dir = os.path.join(osgeo_dir, 'data', 'gdal')
|
||||
|
||||
# datas = [(os.path.join(pkg_dir, filename), '') for filename in files]
|
||||
|
||||
# datas += [(os.path.join(data_dir, filename), '') for filename in
|
||||
# glob.glob(data_dir + '/*')]
|
||||
|
||||
# else:
|
||||
# if platform.system() == 'Darwin':
|
||||
# # Accommodate multiple gdal version installations
|
||||
# _base_data_dir = '/usr/local/Cellar/gdal/'
|
||||
# _version_glob = "%s*" % gdal.__version__
|
||||
# _gdal_version_dirname = glob.glob(_base_data_dir + _version_glob)[-1]
|
||||
# data_dir = os.path.join(_gdal_version_dirname, 'share', 'gdal')
|
||||
|
||||
# datas = [(os.path.join(pkg_dir, filename), '') for filename in files]
|
||||
|
||||
# datas += [(os.path.join(data_dir, filename), '') for filename in
|
||||
# glob.glob(data_dir + '/*')]
|
||||
|
||||
# else:
|
||||
# datas = collect_data_files('osgeo')
|
||||
|
||||
datas = collect_data_files('osgeo')
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
from PyInstaller.hooks.hookutils import collect_data_files
|
||||
|
||||
datas = collect_data_files('pygeoprocessing')
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
hiddenimports = ['scipy.special._ufuncs_cxx', 'scipy.io.matlab.streams', 'scipy.sparse.cgraph._validation']
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
import os
|
||||
from hookutils import collect_submodules, collect_data_files, get_package_paths
|
||||
hiddenimports = collect_submodules('shapely')
|
||||
|
||||
pkg_base, pkg_dir = get_package_paths('shapely')
|
||||
datas = collect_data_files('shapely')
|
||||
datas += [(os.path.join(pkg_dir, 'DLLs/geos_c.dll'), '')]
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
import sys
|
||||
import os
|
||||
import multiprocessing
|
||||
|
||||
multiprocessing.freeze_support()
|
||||
|
||||
os.environ['MATPLOTLIBDATA'] = os.path.join(sys._MEIPASS, 'mpl-data')
|
|
@ -0,0 +1,60 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
# Global Variables
|
||||
current_dir = os.path.join(os.getcwd(), os.path.dirname(sys.argv[1]))
|
||||
app_dir = os.path.join(current_dir, 'apps')
|
||||
scripts = os.listdir(app_dir)
|
||||
|
||||
# Analyze Scripts for Dependencies
|
||||
kwargs = {
|
||||
'hookspath': [os.path.join(current_dir, 'hooks')],
|
||||
'excludes': None,
|
||||
'pathex': [os.getcwd()],
|
||||
}
|
||||
analysis_object_tuples = []
|
||||
for script in scripts:
|
||||
fname, _ = os.path.splitext(script)
|
||||
fpath = os.path.join(app_dir, script)
|
||||
a = Analysis([fpath], **kwargs)
|
||||
analysis_object_tuples.append((a, fname, fname))
|
||||
MERGE(*analysis_object_tuples)
|
||||
|
||||
# Compress pyc and pyo Files into ZlibArchive Objects
|
||||
pyz_objects = []
|
||||
for t in analysis_object_tuples:
|
||||
pyz = PYZ(t[0].pure)
|
||||
pyz_objects.append(pyz)
|
||||
|
||||
# Create Executable Files
|
||||
exe_objects = []
|
||||
for i in range(len(scripts)):
|
||||
fname, _ = os.path.splitext(scripts[i])
|
||||
exe = EXE(
|
||||
pyz_objects[i],
|
||||
analysis_object_tuples[i][0].scripts,
|
||||
name=fname,
|
||||
exclude_binaries=1,
|
||||
debug=False,
|
||||
strip=None,
|
||||
upx=False,
|
||||
console=False)
|
||||
exe_objects.append(exe)
|
||||
|
||||
# Collect Files into Distributable Folder/File
|
||||
binaries = []
|
||||
zipfiles = []
|
||||
datas = []
|
||||
|
||||
for i in range(len(scripts)):
|
||||
binaries.append(analysis_object_tuples[i][0].binaries)
|
||||
zipfiles.append(analysis_object_tuples[i][0].zipfiles)
|
||||
datas.append(analysis_object_tuples[i][0].datas)
|
||||
|
||||
args = exe_objects + binaries + zipfiles + datas
|
||||
|
||||
dist = COLLECT(
|
||||
*args,
|
||||
name="invest_dist",
|
||||
strip=None,
|
||||
upx=True)
|
Loading…
Reference in New Issue