Project

General

Profile

Bundle-python » History » Version 38

Adrian Georgescu, 11/08/2016 03:52 PM

1 1 Saúl Ibarra Corretgé
h1. Building a Python Framework to bundle inside Blink
2
3
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.
4
5 13 Saúl Ibarra Corretgé
The following instructions only apply for 64bit builds, 32bit builds are no longer supported.
6 7 Adrian Georgescu
7 22 Adrian Georgescu
Blink dependencies must be installed under the following directory structure:
8
9
* Distribution/Frameworks/
10
* Distribution/Resources/lib
11 1 Saúl Ibarra Corretgé
 
12 7 Adrian Georgescu
h2. Building the Python Framework itself
13 1 Saúl Ibarra Corretgé
14 18 Saúl Ibarra Corretgé
* Install it using Homebrew
15 1 Saúl Ibarra Corretgé
16
<pre>
17 18 Saúl Ibarra Corretgé
brew install python
18 1 Saúl Ibarra Corretgé
</pre>
19
20 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.
21 1 Saúl Ibarra Corretgé
22 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.
23 22 Adrian Georgescu
24
The Python framework is found in
25
26
<pre>
27 27 Adrian Georgescu
cp -a /usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework ~/work/blink/Distribution/Frameworks/
28 22 Adrian Georgescu
</pre>
29
30 2 Saúl Ibarra Corretgé
* Reduce the size of the Python Framework:
31
32 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:
33
34
<pre>
35 27 Adrian Georgescu
cd ~/work/blink/Distribution/Frameworks//Python.framework
36 26 Adrian Georgescu
find . -name *.pyc -exec rm -r "{}" \; 
37
find . -name *.pyo -exec rm -r "{}" \; 
38 24 Adrian Georgescu
rm -r Versions/Current/lib/python2.7/config/python.o
39
rm -r Versions/Current/bin
40
rm -r Versions/Current/Resources/*
41
rm -r Versions/Current/lib/python2.7/test
42
rm -r Versions/Current/lib/python2.7/plat-*
43
rm -r Versions/Current/lib/python2.7/idlelib
44
rm -r Versions/Current/lib/python2.7/curses
45
rm -r Versions/Current/lib/python2.7/lib2to3
46
rm -r Versions/Current/lib/python2.7/lib-tk
47
rm -r Versions/Current/lib/python2.7/bsddb
48
rm -r Versions/Current/lib/python2.7/lib-dynload/gdbm.so
49
rm -r Versions/Current/lib/python2.7/lib-dynload/readline.so
50 35 Adrian Georgescu
rm -r Versions/2.7/lib/python2.7/site-packages
51 1 Saúl Ibarra Corretgé
</pre>
52 3 Saúl Ibarra Corretgé
53 1 Saúl Ibarra Corretgé
Replace @Versions/Current/lib/python2.7/site.py@ with an empty file.
54 28 Adrian Georgescu
55
<pre>
56 38 Adrian Georgescu
rm ~/work/blink/Distribution/Frameworks//Python.framework/Versions/Current/lib/python2.7/site.py
57
touch ~/work/blink/Distribution/Frameworks//Python.framework/Versions/Current/lib/python2.7/site.py
58 28 Adrian Georgescu
</pre>
59 5 Saúl Ibarra Corretgé
60 34 Adrian Georgescu
Python Framework needs file a Info.plist file under Resources in order to be compatible with latest OSX bundle structure:
61
62
<pre>
63
cp build_scripts/PythonFramework.plist Distribution/Frameworks/Python.framework/Resources/Info.plist           
64
</pre>
65
66
67 5 Saúl Ibarra Corretgé
h2. Compiling PyObjC
68
69 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.
70 5 Saúl Ibarra Corretgé
71
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:
72 1 Saúl Ibarra Corretgé
73 5 Saúl Ibarra Corretgé
<pre>
74
pip install pyobjc-core
75
pip install pyobjc
76 23 Adrian Georgescu
pip install pycrypto
77 1 Saúl Ibarra Corretgé
</pre>
78
79 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:
80
81
<pre>
82
AddressBook
83
AppKit
84 1 Saúl Ibarra Corretgé
Cocoa
85 5 Saúl Ibarra Corretgé
CoreFoundation
86
Foundation
87 13 Saúl Ibarra Corretgé
JavaScriptCore
88 5 Saúl Ibarra Corretgé
LaunchServices
89 1 Saúl Ibarra Corretgé
PyObjCTools
90
Quartz
91 13 Saúl Ibarra Corretgé
ScriptingBridge
92
StoreKit
93 1 Saúl Ibarra Corretgé
WebKit
94 8 Adrian Georgescu
objc
95 6 Saúl Ibarra Corretgé
</pre>
96
97 1 Saúl Ibarra Corretgé
98 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):
99 20 Adrian Georgescu
100 1 Saúl Ibarra Corretgé
<pre>
101
AVFoundation
102
AddressBook
103
AppKit
104
Cocoa
105
CoreFoundation
106
Crypto
107
Foundation
108
LaunchServices
109
PyObjCTools
110
Quartz
111
ScriptingBridge
112
WebKit
113
_cffi_backend.so
114
_ldap.so
115
_markerlib
116
application
117
cffi
118
cjson.so
119
cryptography
120
cryptography-1.5.1.dist-info
121
dateutil
122
dns
123
dsml.py
124
enum
125
eventlib
126
formencode
127
gmpy2.so
128
gnutls
129
greenlet.so
130
idna
131
ipaddress.py
132
ldap
133
ldapurl.py
134
ldif.py
135
lxml
136
msrplib
137
objc
138
otr
139
pkg_resources
140
pyasn1
141
pycparser
142
pydispatch
143
pytz
144
service_identity
145
sipsimple
146
six.py
147
sqlobject
148
twisted
149
xcaplib
150 21 Adrian Georgescu
</pre>
151
152
153
*NOTE:* The _objc_ package is located inside a _PyObjC_ directory, just copy it from there, without the parent directory.
154
155
*NOTE:* _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:
156
157
<pre>
158
__import__('pkg_resources').declare_namespace(__name__)
159
</pre>
160
161 25 Adrian Georgescu
h2. Fix library paths
162
163
All libraries must have their relative path change to the Framework path bundled within Blink.app
164
165
<pre>
166
#!/bin/sh
167
168
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/"
169
new_path="@executable_path/../Frameworks/"
170
171
for library in $@; do
172
  install_name_tool -id $new_path$library $library
173
  dependencies=$(otool -L $library | grep $old_path | awk '{print $1}')
174
  for dependency in $dependencies; do
175
      new_basename=$(basename $dependency)
176
      new_name="$new_path$new_basename"
177
      echo $dependency $new_name $library
178
      install_name_tool -change $dependency $new_name $library
179
  done
180 1 Saúl Ibarra Corretgé
done
181
</pre>
182
183
A script is available in ./build_scripts/ directory
184
185
<pre>
186
./build_scripts/change_lib_names.sh Distribution/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/*.so
187
chmod +w Distribution/Frameworks/Python.framework/Versions/Current/Python
188
./build_scripts/change_lib_names.sh Distribution/Frameworks/Python.framework/Versions/Current/Python
189
</pre>
190
191 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
192
193
<pre>
194
sos=`find ./Resources/lib -name *.so`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
195
sos=`find ./Frameworks -name *.dylib`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
196
sos=`find ./Frameworks -name *.so`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
197
sos=`find ./Frameworks -name *.o`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
198
sos=`find ./Frameworks -name *.a`; for s in $sos; do codesign -f -s '3rd Party Mac Developer Application: AG Projects' $s; done
199
</pre>
200
201
A script is available in ./build_scripts/ directory
202
203
<pre>
204
./build_scripts/codesign.sh 
205
</pre>
206 29 Adrian Georgescu
207 21 Adrian Georgescu
h2. Module exceptions
208
209
When copying built Python modules into the distribution folder, care must be taken with the 2 following packages:
210
211
* zope: an empty @__init__.py@ file must be created in the @zope@ directory
212
* cryptography: the @*-dist.info@ must be copied too
213
214
h1. Creating a sandbox (Python virtualenv)
215
216
<pre>
217
sudo easy_install pip
218
sudo pip install virtualenv virtualenvwrapper
219
</pre>
220
221
Add to ~.bashrc
222
223
<pre>
224
# Virtualenv
225
export WORKON_HOME=$HOME/.virtualenvs
226
export PIP_VIRTUALENV_BASE=$WORKON_HOME
227
export PIP_RESPECT_VIRTUALENV=true
228
export VIRTUALENVWRAPPER_SCRIPT=/usr/local/bin/virtualenvwrapper.sh
229
[[ -f /usr/local/bin/virtualenvwrapper_lazy.sh ]] && source /usr/local/bin/virtualenvwrapper_lazy.sh
230
</pre>
231
232
Creating a sandbox:
233
234
<pre>
235
mkvirtualenv -p $(which python2.7) sandbox
236
</pre>
237
238
Exiting the sandbox:
239
240
<pre>
241
deactivate
242
</pre>
243
244
Entering the sandbox:
245
246
<pre>
247
workon sandbox
248 19 Adrian Georgescu
</pre>