Project

General

Profile

Bundle-python » History » Version 41

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