Project

General

Profile

Bundle-python » History » Version 40

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