Bundle-python

Version 44 (Adrian Georgescu, 03/04/2018 03:48 pm)

1 1 Saúl Ibarra Corretgé
h1. Building a Python Framework to bundle inside Blink
2 1 Saúl Ibarra Corretgé
3 44 Adrian Georgescu
*These have moved inside blink project _build_scripts folder*
4 44 Adrian Georgescu
5 44 Adrian Georgescu
6 1 Saúl Ibarra Corretgé
In order to avoid using the system Python a custom Framework build is needed. Using a bundled Python version will make the package bigger in size, but all package versions are controlled and not up to the environment. Also, we can use the latest Python version, with latest bugfixes and features, since Apple only updates the system Python version on every major OS release.
7 1 Saúl Ibarra Corretgé
8 13 Saúl Ibarra Corretgé
The following instructions only apply for 64bit builds, 32bit builds are no longer supported.
9 7 Adrian Georgescu
10 22 Adrian Georgescu
Blink dependencies must be installed under the following directory structure:
11 22 Adrian Georgescu
12 22 Adrian Georgescu
* Distribution/Frameworks/
13 22 Adrian Georgescu
* Distribution/Resources/lib
14 1 Saúl Ibarra Corretgé
 
15 7 Adrian Georgescu
h2. Building the Python Framework itself
16 1 Saúl Ibarra Corretgé
17 18 Saúl Ibarra Corretgé
* Install it using Homebrew
18 1 Saúl Ibarra Corretgé
19 1 Saúl Ibarra Corretgé
<pre>
20 40 Adrian Georgescu
brew install python (this may install python 3)
21 40 Adrian Georgescu
22 40 Adrian Georgescu
To install 2.7:
23 40 Adrian Georgescu
24 41 Adrian Georgescu
brew install python2
25 41 Adrian Georgescu
26 41 Adrian Georgescu
or
27 40 Adrian Georgescu
https://stackoverflow.com/questions/18671253/how-can-i-use-homebrew-to-install-both-python-2-and-3-on-mac
28 40 Adrian Georgescu
29 40 Adrian Georgescu
brew install pyenv
30 40 Adrian Georgescu
pyenv install 2.7
31 1 Saúl Ibarra Corretgé
</pre>
32 1 Saúl Ibarra Corretgé
33 18 Saúl Ibarra Corretgé
The framework will be installed and linked with Homebrew supplied OpenSSL and SQLite versions. Those libraries will need to be copied too.
34 1 Saúl Ibarra Corretgé
35 18 Saúl Ibarra Corretgé
*NOTE*: Be careful when copying the framework around, it contains symlinks and if @cp -r@ is used the size will we doubled, use @cp -a@ instead.
36 22 Adrian Georgescu
37 22 Adrian Georgescu
The Python framework is found in
38 22 Adrian Georgescu
39 22 Adrian Georgescu
<pre>
40 27 Adrian Georgescu
cp -a /usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework ~/work/blink/Distribution/Frameworks/
41 22 Adrian Georgescu
</pre>
42 22 Adrian Georgescu
43 2 Saúl Ibarra Corretgé
* Reduce the size of the Python Framework:
44 2 Saúl Ibarra Corretgé
45 1 Saúl Ibarra Corretgé
There are a number of things that can (and must when submitting a sandbox app to Mac App Store) be removed from the framework directory to make it smaller in size:
46 1 Saúl Ibarra Corretgé
47 1 Saúl Ibarra Corretgé
<pre>
48 43 Adrian Georgescu
cd ~/work/blink/Distribution/Frameworks/Python.framework
49 42 Adrian Georgescu
cd Versions/2.7
50 42 Adrian Georgescu
ln -sf Current 2.7
51 43 Adrian Georgescu
cd ~/work/blink/Distribution/Frameworks/Python.framework
52 42 Adrian Georgescu
ln -sf Versions/Current/Headers .
53 42 Adrian Georgescu
ln -sf Versions/Current/Python .
54 42 Adrian Georgescu
ln -sf Versions/Current/Resources .
55 26 Adrian Georgescu
find . -name *.pyc -exec rm -r "{}" \; 
56 26 Adrian Georgescu
find . -name *.pyo -exec rm -r "{}" \; 
57 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/config/python.o
58 24 Adrian Georgescu
rm -r Versions/Current/bin
59 24 Adrian Georgescu
rm -r Versions/Current/Resources/*
60 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/test
61 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/plat-*
62 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/idlelib
63 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/curses
64 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/lib2to3
65 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/lib-tk
66 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/bsddb
67 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/lib-dynload/gdbm.so
68 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/lib-dynload/readline.so
69 35 Adrian Georgescu
rm -r Versions/2.7/lib/python2.7/site-packages
70 1 Saúl Ibarra Corretgé
</pre>
71 3 Saúl Ibarra Corretgé
72 1 Saúl Ibarra Corretgé
Replace @Versions/Current/lib/python2.7/site.py@ with an empty file.
73 28 Adrian Georgescu
74 28 Adrian Georgescu
<pre>
75 38 Adrian Georgescu
rm ~/work/blink/Distribution/Frameworks//Python.framework/Versions/Current/lib/python2.7/site.py
76 38 Adrian Georgescu
touch ~/work/blink/Distribution/Frameworks//Python.framework/Versions/Current/lib/python2.7/site.py
77 28 Adrian Georgescu
</pre>
78 5 Saúl Ibarra Corretgé
79 34 Adrian Georgescu
Python Framework needs file a Info.plist file under Resources in order to be compatible with latest OSX bundle structure:
80 34 Adrian Georgescu
81 34 Adrian Georgescu
<pre>
82 34 Adrian Georgescu
cp build_scripts/PythonFramework.plist Distribution/Frameworks/Python.framework/Resources/Info.plist           
83 34 Adrian Georgescu
</pre>
84 34 Adrian Georgescu
85 34 Adrian Georgescu
86 5 Saúl Ibarra Corretgé
h2. Compiling PyObjC
87 5 Saúl Ibarra Corretgé
88 13 Saúl Ibarra Corretgé
In order to get a PyObjC version that will work with the framework created above (Python 2.7, 64bits) an equivalent Python must be used to compile it. That is, if has to be a Python 2.7 version (it doesn't have to be the exact version) and it has to be a 64bit version. The MACOSX_DEPLOYMENT_TARGET must also be set to the appropriate value.
89 5 Saúl Ibarra Corretgé
90 5 Saúl Ibarra Corretgé
PyObjcC can be installed with easy_install or pip. We install it in 2 steps to save some compilation time due to a bug in the build system:
91 1 Saúl Ibarra Corretgé
92 5 Saúl Ibarra Corretgé
<pre>
93 5 Saúl Ibarra Corretgé
pip install pyobjc-core
94 5 Saúl Ibarra Corretgé
pip install pyobjc
95 23 Adrian Georgescu
pip install pycrypto
96 1 Saúl Ibarra Corretgé
</pre>
97 1 Saúl Ibarra Corretgé
98 5 Saúl Ibarra Corretgé
When compiling PyObjC a Python package will be created for every system framework, but not all of them are needed (at the moment), so just pick the ones we use:
99 5 Saúl Ibarra Corretgé
100 5 Saúl Ibarra Corretgé
<pre>
101 5 Saúl Ibarra Corretgé
AddressBook
102 5 Saúl Ibarra Corretgé
AppKit
103 1 Saúl Ibarra Corretgé
Cocoa
104 5 Saúl Ibarra Corretgé
CoreFoundation
105 5 Saúl Ibarra Corretgé
Foundation
106 13 Saúl Ibarra Corretgé
JavaScriptCore
107 5 Saúl Ibarra Corretgé
LaunchServices
108 1 Saúl Ibarra Corretgé
PyObjCTools
109 1 Saúl Ibarra Corretgé
Quartz
110 13 Saúl Ibarra Corretgé
ScriptingBridge
111 13 Saúl Ibarra Corretgé
StoreKit
112 1 Saúl Ibarra Corretgé
WebKit
113 8 Adrian Georgescu
objc
114 6 Saúl Ibarra Corretgé
</pre>
115 6 Saúl Ibarra Corretgé
116 1 Saúl Ibarra Corretgé
117 21 Adrian Georgescu
For example this is the content of a Resources/lib bundled with Blink Cocoa as of November 3rd, 2016 (including sipsimple dependencies & all):
118 20 Adrian Georgescu
119 1 Saúl Ibarra Corretgé
<pre>
120 1 Saúl Ibarra Corretgé
AVFoundation
121 1 Saúl Ibarra Corretgé
AddressBook
122 1 Saúl Ibarra Corretgé
AppKit
123 1 Saúl Ibarra Corretgé
Cocoa
124 1 Saúl Ibarra Corretgé
CoreFoundation
125 1 Saúl Ibarra Corretgé
Crypto
126 1 Saúl Ibarra Corretgé
Foundation
127 1 Saúl Ibarra Corretgé
LaunchServices
128 1 Saúl Ibarra Corretgé
PyObjCTools
129 1 Saúl Ibarra Corretgé
Quartz
130 1 Saúl Ibarra Corretgé
ScriptingBridge
131 1 Saúl Ibarra Corretgé
WebKit
132 1 Saúl Ibarra Corretgé
_cffi_backend.so
133 1 Saúl Ibarra Corretgé
_ldap.so
134 1 Saúl Ibarra Corretgé
_markerlib
135 1 Saúl Ibarra Corretgé
application
136 1 Saúl Ibarra Corretgé
cffi
137 1 Saúl Ibarra Corretgé
cjson.so
138 1 Saúl Ibarra Corretgé
cryptography
139 1 Saúl Ibarra Corretgé
cryptography-1.5.1.dist-info
140 1 Saúl Ibarra Corretgé
dateutil
141 1 Saúl Ibarra Corretgé
dns
142 1 Saúl Ibarra Corretgé
dsml.py
143 1 Saúl Ibarra Corretgé
enum
144 1 Saúl Ibarra Corretgé
eventlib
145 1 Saúl Ibarra Corretgé
formencode
146 1 Saúl Ibarra Corretgé
gmpy2.so
147 1 Saúl Ibarra Corretgé
gnutls
148 1 Saúl Ibarra Corretgé
greenlet.so
149 1 Saúl Ibarra Corretgé
idna
150 1 Saúl Ibarra Corretgé
ipaddress.py
151 1 Saúl Ibarra Corretgé
ldap
152 1 Saúl Ibarra Corretgé
ldapurl.py
153 1 Saúl Ibarra Corretgé
ldif.py
154 1 Saúl Ibarra Corretgé
lxml
155 1 Saúl Ibarra Corretgé
msrplib
156 1 Saúl Ibarra Corretgé
objc
157 1 Saúl Ibarra Corretgé
otr
158 1 Saúl Ibarra Corretgé
pkg_resources
159 1 Saúl Ibarra Corretgé
pyasn1
160 1 Saúl Ibarra Corretgé
pycparser
161 1 Saúl Ibarra Corretgé
pydispatch
162 1 Saúl Ibarra Corretgé
pytz
163 1 Saúl Ibarra Corretgé
service_identity
164 1 Saúl Ibarra Corretgé
sipsimple
165 1 Saúl Ibarra Corretgé
six.py
166 1 Saúl Ibarra Corretgé
sqlobject
167 1 Saúl Ibarra Corretgé
twisted
168 1 Saúl Ibarra Corretgé
xcaplib
169 21 Adrian Georgescu
</pre>
170 21 Adrian Georgescu
171 21 Adrian Georgescu
172 21 Adrian Georgescu
*NOTE:* The _objc_ package is located inside a _PyObjC_ directory, just copy it from there, without the parent directory.
173 21 Adrian Georgescu
174 21 Adrian Georgescu
<pre>
175 21 Adrian Georgescu
__import__('pkg_resources').declare_namespace(__name__)
176 21 Adrian Georgescu
</pre>
177 21 Adrian Georgescu
178 25 Adrian Georgescu
h2. Fix library paths
179 25 Adrian Georgescu
180 25 Adrian Georgescu
All libraries must have their relative path change to the Framework path bundled within Blink.app
181 25 Adrian Georgescu
182 25 Adrian Georgescu
<pre>
183 25 Adrian Georgescu
#!/bin/sh
184 25 Adrian Georgescu
185 25 Adrian Georgescu
old_path="local/lib/\|local/Cellar/\|/usr/local/opt/libmpc/lib/\|/usr/local/opt/mpfr/lib/\|Frameworks/Frameworks/\|/Users/adigeo/work/ag-projects/video/local/lib/"
186 25 Adrian Georgescu
new_path="@executable_path/../Frameworks/"
187 25 Adrian Georgescu
188 25 Adrian Georgescu
for library in $@; do
189 25 Adrian Georgescu
  install_name_tool -id $new_path$library $library
190 25 Adrian Georgescu
  dependencies=$(otool -L $library | grep $old_path | awk '{print $1}')
191 25 Adrian Georgescu
  for dependency in $dependencies; do
192 25 Adrian Georgescu
      new_basename=$(basename $dependency)
193 25 Adrian Georgescu
      new_name="$new_path$new_basename"
194 25 Adrian Georgescu
      echo $dependency $new_name $library
195 25 Adrian Georgescu
      install_name_tool -change $dependency $new_name $library
196 25 Adrian Georgescu
  done
197 1 Saúl Ibarra Corretgé
done
198 1 Saúl Ibarra Corretgé
</pre>
199 1 Saúl Ibarra Corretgé
200 1 Saúl Ibarra Corretgé
A script is available in ./build_scripts/ directory
201 1 Saúl Ibarra Corretgé
202 1 Saúl Ibarra Corretgé
<pre>
203 1 Saúl Ibarra Corretgé
./build_scripts/change_lib_names.sh Distribution/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/*.so
204 1 Saúl Ibarra Corretgé
chmod +w Distribution/Frameworks/Python.framework/Versions/Current/Python
205 1 Saúl Ibarra Corretgé
./build_scripts/change_lib_names.sh Distribution/Frameworks/Python.framework/Versions/Current/Python
206 1 Saúl Ibarra Corretgé
</pre>
207 1 Saúl Ibarra Corretgé
208 33 Adrian Georgescu
*NOTE*: Python.framework as well as all other libraries must be signed using command line tools. Make sure when building Blink that "Code sign on copy" option is disabled for Python.framework. This script can be used to sign all libraries and frameworks
209 33 Adrian Georgescu
210 33 Adrian Georgescu
<pre>
211 33 Adrian Georgescu
sos=`find ./Resources/lib -name *.so`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
212 33 Adrian Georgescu
sos=`find ./Frameworks -name *.dylib`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
213 33 Adrian Georgescu
sos=`find ./Frameworks -name *.so`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
214 33 Adrian Georgescu
sos=`find ./Frameworks -name *.o`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
215 33 Adrian Georgescu
sos=`find ./Frameworks -name *.a`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
216 33 Adrian Georgescu
</pre>
217 33 Adrian Georgescu
218 33 Adrian Georgescu
A script is available in ./build_scripts/ directory
219 33 Adrian Georgescu
220 33 Adrian Georgescu
<pre>
221 33 Adrian Georgescu
./build_scripts/codesign.sh 
222 33 Adrian Georgescu
</pre>
223 29 Adrian Georgescu
224 21 Adrian Georgescu
h2. Module exceptions
225 21 Adrian Georgescu
226 21 Adrian Georgescu
When copying built Python modules into the distribution folder, care must be taken with the 2 following packages:
227 21 Adrian Georgescu
228 1 Saúl Ibarra Corretgé
* zope: an empty @__init__.py@ file must be created in the @zope@ directory
229 1 Saúl Ibarra Corretgé
* cryptography: the @*-dist.info@ must be copied too
230 39 Adrian Georgescu
* _PyObjCTools_ is not a valid Python package, as it lacks a @__init__.py@ file, an empty one needs to be manually created with this content:
231 39 Adrian Georgescu
232 21 Adrian Georgescu
233 21 Adrian Georgescu
h1. Creating a sandbox (Python virtualenv)
234 21 Adrian Georgescu
235 21 Adrian Georgescu
<pre>
236 21 Adrian Georgescu
sudo easy_install pip
237 21 Adrian Georgescu
sudo pip install virtualenv virtualenvwrapper
238 21 Adrian Georgescu
</pre>
239 21 Adrian Georgescu
240 21 Adrian Georgescu
Add to ~.bashrc
241 21 Adrian Georgescu
242 21 Adrian Georgescu
<pre>
243 21 Adrian Georgescu
# Virtualenv
244 21 Adrian Georgescu
export WORKON_HOME=$HOME/.virtualenvs
245 21 Adrian Georgescu
export PIP_VIRTUALENV_BASE=$WORKON_HOME
246 21 Adrian Georgescu
export PIP_RESPECT_VIRTUALENV=true
247 21 Adrian Georgescu
export VIRTUALENVWRAPPER_SCRIPT=/usr/local/bin/virtualenvwrapper.sh
248 21 Adrian Georgescu
[[ -f /usr/local/bin/virtualenvwrapper_lazy.sh ]] && source /usr/local/bin/virtualenvwrapper_lazy.sh
249 21 Adrian Georgescu
</pre>
250 21 Adrian Georgescu
251 21 Adrian Georgescu
Creating a sandbox:
252 21 Adrian Georgescu
253 21 Adrian Georgescu
<pre>
254 21 Adrian Georgescu
mkvirtualenv -p $(which python2.7) sandbox
255 21 Adrian Georgescu
</pre>
256 21 Adrian Georgescu
257 21 Adrian Georgescu
Exiting the sandbox:
258 21 Adrian Georgescu
259 21 Adrian Georgescu
<pre>
260 21 Adrian Georgescu
deactivate
261 21 Adrian Georgescu
</pre>
262 21 Adrian Georgescu
263 21 Adrian Georgescu
Entering the sandbox:
264 21 Adrian Georgescu
265 21 Adrian Georgescu
<pre>
266 21 Adrian Georgescu
workon sandbox
267 19 Adrian Georgescu
</pre>