Project

General

Profile

Bundle-python » History » Version 35

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