|
1 |
| -from pythonforandroid.recipe import TargetPythonRecipe, Recipe |
2 |
| -from pythonforandroid.toolchain import shprint, current_directory, info |
3 |
| -from pythonforandroid.patching import (is_darwin, is_api_gt, |
4 |
| - check_all, is_api_lt, is_ndk) |
5 |
| -from os.path import exists, join, realpath |
6 |
| -from os import walk |
7 |
| -import glob |
8 |
| -import sh |
9 |
| - |
10 |
| -EXCLUDE_EXTS = (".py", ".pyc", ".so.o", ".so.a", ".so.libs", ".pyx") |
| 1 | +from pythonforandroid.recipe import TargetPythonRecipe |
| 2 | +from pythonforandroid.patching import ( |
| 3 | + is_darwin, is_api_gt, check_all, is_api_lt, is_ndk) |
11 | 4 |
|
12 | 5 |
|
13 | 6 | class Python2Recipe(TargetPythonRecipe):
|
14 |
| - version = "2.7.2" |
15 |
| - url = 'https://python.org/ftp/python/{version}/Python-{version}.tar.bz2' |
| 7 | + ''' |
| 8 | + The python2's recipe. |
| 9 | +
|
| 10 | + .. versionchanged:: 0.6.0 |
| 11 | + Updated to version 2.7.15 and the build process has been changed in |
| 12 | + favour of the recently changed class |
| 13 | + :class:`~pythonforandroid.recipe.TargetPythonRecipe` |
| 14 | + ''' |
| 15 | + version = "2.7.15" |
| 16 | + url = 'https://www.python.org/ftp/python/{version}/Python-{version}.tgz' |
16 | 17 | name = 'python2'
|
17 | 18 |
|
18 | 19 | depends = ['hostpython2']
|
19 |
| - conflicts = ['python3crystax', 'python3'] |
20 |
| - opt_depends = ['openssl', 'sqlite3'] |
21 |
| - |
22 |
| - patches = ['patches/Python-{version}-xcompile.patch', |
23 |
| - 'patches/Python-{version}-ctypes-disable-wchar.patch', |
24 |
| - 'patches/disable-modules.patch', |
25 |
| - 'patches/fix-locale.patch', |
| 20 | + conflicts = ['python3crystax', 'python3', 'python2legacy'] |
| 21 | + # opt_depends = ['openssl', 'sqlite3'] |
| 22 | + |
| 23 | + patches = [ |
| 24 | + # new 2.7.15 patches |
| 25 | + # ('patches/Python-2.7.15-fix-api-minor-than-21.patch', |
| 26 | + # is_api_lt(21)), # todo: this should be tested |
| 27 | + 'patches/Python_{version}-ctypes-libffi-fix-configure.patch', |
| 28 | + 'patches/ffi-config.sub-{version}.patch', |
| 29 | + 'patches/fix-locale-{version}.patch', |
| 30 | + 'patches/modules-locales-{version}.patch', |
| 31 | + 'patches/fix-platform-{version}.patch', |
| 32 | + # migrated patches from 2.7.2 |
26 | 33 | 'patches/fix-gethostbyaddr.patch',
|
27 |
| - 'patches/fix-setup-flags.patch', |
28 | 34 | 'patches/fix-filesystemdefaultencoding.patch',
|
29 | 35 | 'patches/fix-termios.patch',
|
30 | 36 | 'patches/custom-loader.patch',
|
31 |
| - 'patches/verbose-compilation.patch', |
32 | 37 | 'patches/fix-remove-corefoundation.patch',
|
33 | 38 | 'patches/fix-dynamic-lookup.patch',
|
34 | 39 | 'patches/fix-dlfcn.patch',
|
35 |
| - 'patches/parsetuple.patch', |
36 |
| - 'patches/ctypes-find-library-updated.patch', |
| 40 | + 'patches/ctypes-find-library.patch', |
| 41 | + 'patches/Python-{version}-ctypes-disable-wchar.patch', |
| 42 | + 'patches/disable-modules.patch', |
| 43 | + 'patches/verbose-compilation.patch', |
| 44 | + # migrated special patches from 2.7.2 |
37 | 45 | ('patches/fix-configure-darwin.patch', is_darwin),
|
38 | 46 | ('patches/fix-distutils-darwin.patch', is_darwin),
|
39 | 47 | ('patches/fix-ftime-removal.patch', is_api_gt(19)),
|
40 |
| - ('patches/disable-openpty.patch', check_all(is_api_lt(21), is_ndk('crystax')))] |
41 |
| - |
42 |
| - from_crystax = False |
43 |
| - |
44 |
| - def build_arch(self, arch): |
45 |
| - |
46 |
| - if not exists(join(self.get_build_dir(arch.arch), 'libpython2.7.so')): |
47 |
| - self.do_python_build(arch) |
48 |
| - |
49 |
| - if not exists(self.ctx.get_python_install_dir()): |
50 |
| - shprint(sh.cp, '-a', join(self.get_build_dir(arch.arch), 'python-install'), |
51 |
| - self.ctx.get_python_install_dir()) |
52 |
| - |
53 |
| - # This should be safe to run every time |
54 |
| - info('Copying hostpython binary to targetpython folder') |
55 |
| - shprint(sh.cp, self.ctx.hostpython, |
56 |
| - join(self.ctx.get_python_install_dir(), 'bin', 'python.host')) |
57 |
| - self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host') |
58 |
| - |
59 |
| - if not exists(join(self.ctx.get_libs_dir(arch.arch), 'libpython2.7.so')): |
60 |
| - shprint(sh.cp, join(self.get_build_dir(arch.arch), 'libpython2.7.so'), self.ctx.get_libs_dir(arch.arch)) |
61 |
| - |
62 |
| - # # if exists(join(self.get_build_dir(arch.arch), 'libpython2.7.so')): |
63 |
| - # if exists(join(self.ctx.libs_dir, 'libpython2.7.so')): |
64 |
| - # info('libpython2.7.so already exists, skipping python build.') |
65 |
| - # if not exists(join(self.ctx.get_python_install_dir(), 'libpython2.7.so')): |
66 |
| - # info('Copying python-install to dist-dependent location') |
67 |
| - # shprint(sh.cp, '-a', 'python-install', self.ctx.get_python_install_dir()) |
68 |
| - # self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host') |
69 |
| - |
70 |
| - # return |
71 |
| - |
72 |
| - def do_python_build(self, arch): |
73 |
| - |
74 |
| - hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx) |
75 |
| - shprint(sh.cp, self.ctx.hostpython, self.get_build_dir(arch.arch)) |
76 |
| - shprint(sh.cp, self.ctx.hostpgen, self.get_build_dir(arch.arch)) |
77 |
| - hostpython = join(self.get_build_dir(arch.arch), 'hostpython') |
78 |
| - hostpgen = join(self.get_build_dir(arch.arch), 'hostpython') |
79 |
| - |
80 |
| - with current_directory(self.get_build_dir(arch.arch)): |
81 |
| - |
82 |
| - hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx) |
83 |
| - shprint(sh.cp, join(hostpython_recipe.get_recipe_dir(), 'Setup'), 'Modules') |
84 |
| - |
85 |
| - env = arch.get_env() |
86 |
| - |
87 |
| - env['HOSTARCH'] = 'arm-eabi' |
88 |
| - env['BUILDARCH'] = shprint(sh.gcc, '-dumpmachine').stdout.decode('utf-8').split('\n')[0] |
89 |
| - env['CFLAGS'] = ' '.join([env['CFLAGS'], '-DNO_MALLINFO']) |
90 |
| - |
91 |
| - # TODO need to add a should_build that checks if optional |
92 |
| - # dependencies have changed (possibly in a generic way) |
93 |
| - if 'openssl' in self.ctx.recipe_build_order: |
94 |
| - recipe = Recipe.get_recipe('openssl', self.ctx) |
95 |
| - openssl_build_dir = recipe.get_build_dir(arch.arch) |
96 |
| - setuplocal = join('Modules', 'Setup.local') |
97 |
| - shprint(sh.cp, join(self.get_recipe_dir(), 'Setup.local-ssl'), setuplocal) |
98 |
| - shprint(sh.sed, '-i.backup', 's#^SSL=.*#SSL={}#'.format(openssl_build_dir), setuplocal) |
99 |
| - env['OPENSSL_VERSION'] = recipe.version |
100 |
| - |
101 |
| - if 'sqlite3' in self.ctx.recipe_build_order: |
102 |
| - # Include sqlite3 in python2 build |
103 |
| - recipe = Recipe.get_recipe('sqlite3', self.ctx) |
104 |
| - include = ' -I' + recipe.get_build_dir(arch.arch) |
105 |
| - lib = ' -L' + recipe.get_lib_dir(arch) + ' -lsqlite3' |
106 |
| - # Insert or append to env |
107 |
| - flag = 'CPPFLAGS' |
108 |
| - env[flag] = env[flag] + include if flag in env else include |
109 |
| - flag = 'LDFLAGS' |
110 |
| - env[flag] = env[flag] + lib if flag in env else lib |
111 |
| - |
112 |
| - # NDK has langinfo.h but doesn't define nl_langinfo() |
113 |
| - env['ac_cv_header_langinfo_h'] = 'no' |
114 |
| - configure = sh.Command('./configure') |
115 |
| - shprint(configure, |
116 |
| - '--host={}'.format(env['HOSTARCH']), |
117 |
| - '--build={}'.format(env['BUILDARCH']), |
118 |
| - # 'OPT={}'.format(env['OFLAG']), |
119 |
| - '--prefix={}'.format(realpath('./python-install')), |
120 |
| - '--enable-shared', |
121 |
| - '--disable-toolbox-glue', |
122 |
| - '--disable-framework', |
123 |
| - _env=env) |
124 |
| - |
125 |
| - # tito left this comment in the original source. It's still true! |
126 |
| - # FIXME, the first time, we got a error at: |
127 |
| - # python$EXE ../../Tools/scripts/h2py.py -i '(u_long)' /usr/include/netinet/in.h |
128 |
| - # /home/tito/code/python-for-android/build/python/Python-2.7.2/python: 1: Syntax error: word unexpected (expecting ")") |
129 |
| - # because at this time, python is arm, not x86. even that, why /usr/include/netinet/in.h is used ? |
130 |
| - # check if we can avoid this part. |
131 |
| - |
132 |
| - make = sh.Command(env['MAKE'].split(' ')[0]) |
133 |
| - print('First install (expected to fail...') |
134 |
| - try: |
135 |
| - shprint(make, '-j5', 'install', 'HOSTPYTHON={}'.format(hostpython), |
136 |
| - 'HOSTPGEN={}'.format(hostpgen), |
137 |
| - 'CROSS_COMPILE_TARGET=yes', |
138 |
| - 'INSTSONAME=libpython2.7.so', |
139 |
| - _env=env) |
140 |
| - except sh.ErrorReturnCode_2: |
141 |
| - print('First python2 make failed. This is expected, trying again.') |
142 |
| - |
143 |
| - print('Second install (expected to work)') |
144 |
| - shprint(sh.touch, 'python.exe', 'python') |
145 |
| - shprint(make, '-j5', 'install', 'HOSTPYTHON={}'.format(hostpython), |
146 |
| - 'HOSTPGEN={}'.format(hostpgen), |
147 |
| - 'CROSS_COMPILE_TARGET=yes', |
148 |
| - 'INSTSONAME=libpython2.7.so', |
149 |
| - _env=env) |
150 |
| - |
151 |
| - if is_darwin(): |
152 |
| - shprint(sh.cp, join(self.get_recipe_dir(), 'patches', '_scproxy.py'), |
153 |
| - join('python-install', 'Lib')) |
154 |
| - shprint(sh.cp, join(self.get_recipe_dir(), 'patches', '_scproxy.py'), |
155 |
| - join('python-install', 'lib', 'python2.7')) |
156 |
| - |
157 |
| - # reduce python |
158 |
| - for dir_name in ('test', join('json', 'tests'), 'lib-tk', |
159 |
| - join('sqlite3', 'test'), join('unittest, test'), |
160 |
| - join('lib2to3', 'tests'), join('bsddb', 'tests'), |
161 |
| - join('distutils', 'tests'), join('email', 'test'), |
162 |
| - 'curses'): |
163 |
| - shprint(sh.rm, '-rf', join('python-install', |
164 |
| - 'lib', 'python2.7', dir_name)) |
165 |
| - |
166 |
| - # info('Copying python-install to dist-dependent location') |
167 |
| - # shprint(sh.cp, '-a', 'python-install', self.ctx.get_python_install_dir()) |
168 |
| - |
169 |
| - # print('Copying hostpython binary to targetpython folder') |
170 |
| - # shprint(sh.cp, self.ctx.hostpython, |
171 |
| - # join(self.ctx.get_python_install_dir(), 'bin', 'python.host')) |
172 |
| - # self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host') |
173 |
| - |
174 |
| - # print('python2 build done, exiting for debug') |
175 |
| - # exit(1) |
176 |
| - |
177 |
| - def create_python_bundle(self, dirn, arch): |
178 |
| - info("Filling private directory") |
179 |
| - if not exists(join(dirn, "lib")): |
180 |
| - info("lib dir does not exist, making") |
181 |
| - shprint(sh.cp, "-a", |
182 |
| - join("python-install", "lib"), dirn) |
183 |
| - shprint(sh.mkdir, "-p", |
184 |
| - join(dirn, "include", "python2.7")) |
185 |
| - |
186 |
| - libpymodules_fn = join("libs", arch.arch, "libpymodules.so") |
187 |
| - if exists(libpymodules_fn): |
188 |
| - shprint(sh.mv, libpymodules_fn, dirn) |
189 |
| - shprint(sh.cp, |
190 |
| - join('python-install', 'include', |
191 |
| - 'python2.7', 'pyconfig.h'), |
192 |
| - join(dirn, 'include', 'python2.7/')) |
193 |
| - |
194 |
| - info('Removing some unwanted files') |
195 |
| - shprint(sh.rm, '-f', join(dirn, 'lib', 'libpython2.7.so')) |
196 |
| - shprint(sh.rm, '-rf', join(dirn, 'lib', 'pkgconfig')) |
197 |
| - |
198 |
| - libdir = join(dirn, 'lib', 'python2.7') |
199 |
| - site_packages_dir = join(libdir, 'site-packages') |
200 |
| - with current_directory(libdir): |
201 |
| - removes = [] |
202 |
| - for dirname, root, filenames in walk("."): |
203 |
| - for filename in filenames: |
204 |
| - for suffix in EXCLUDE_EXTS: |
205 |
| - if filename.endswith(suffix): |
206 |
| - removes.append(filename) |
207 |
| - shprint(sh.rm, '-f', *removes) |
208 |
| - |
209 |
| - info('Deleting some other stuff not used on android') |
210 |
| - # To quote the original distribute.sh, 'well...' |
211 |
| - shprint(sh.rm, '-rf', 'lib2to3') |
212 |
| - shprint(sh.rm, '-rf', 'idlelib') |
213 |
| - shprint(sh.rm, '-f', *glob.glob('config/libpython*.a')) |
214 |
| - shprint(sh.rm, '-rf', 'config/python.o') |
215 |
| - |
216 |
| - return site_packages_dir |
217 |
| - |
218 |
| - def include_root(self, arch_name): |
219 |
| - return join(self.get_build_dir(arch_name), 'python-install', 'include', 'python2.7') |
220 |
| - |
221 |
| - def link_root(self, arch_name): |
222 |
| - return join(self.get_build_dir(arch_name), 'python-install', 'lib') |
| 48 | + ('patches/disable-openpty.patch', check_all( |
| 49 | + is_api_lt(21), is_ndk('crystax'))) |
| 50 | + ] |
| 51 | + |
| 52 | + configure_args = ('--host={android_host}', |
| 53 | + '--build={android_build}', |
| 54 | + '--enable-shared', |
| 55 | + '--disable-ipv6', |
| 56 | + '--disable-toolbox-glue', |
| 57 | + '--disable-framework', |
| 58 | + 'ac_cv_file__dev_ptmx=yes', |
| 59 | + 'ac_cv_file__dev_ptc=no', |
| 60 | + '--without-ensurepip', |
| 61 | + 'ac_cv_little_endian_double=yes', |
| 62 | + |
| 63 | + # why python3 works without it? |
| 64 | + 'ac_cv_header_langinfo_h=no', |
| 65 | + |
| 66 | + '--prefix={prefix}', |
| 67 | + '--exec-prefix={exec_prefix}') |
223 | 68 |
|
224 | 69 |
|
225 | 70 | recipe = Python2Recipe()
|
0 commit comments