add / update recipes and build changes for Python 3.6.6 compatibility ()

* add / update recipes and build changes for Python 3.6.6 compatibility
* include Python 3 apt packages in travis build script
* use Python 3.6 in Travis
* Enable _blake2 and _sha3 in Python 3. Remove unnecessary files.
* change zope.interface version
* update cffi version
This commit is contained in:
Akinwale Ariwodola 2018-10-07 15:59:03 +01:00 committed by GitHub
commit e08f6ee73c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 2063 additions and 3644 deletions
p4a/pythonforandroid

View file

@ -1,11 +1,11 @@
from os.path import join, dirname, isdir, exists, isfile, split, realpath, basename
from os.path import basename, dirname, exists, isdir, isfile, join, realpath
import importlib
import zipfile
import glob
from shutil import rmtree
from six import PY2, with_metaclass
import hashlib
from re import match
import sh
import shutil
@ -20,7 +20,6 @@ from pythonforandroid.logger import (logger, info, warning, error, debug, shprin
from pythonforandroid.util import (urlretrieve, current_directory, ensure_dir)
# this import is necessary to keep imp.load_source from complaining :)
import pythonforandroid.recipes
if PY2:
@ -149,7 +148,7 @@ class Recipe(with_metaclass(RecipeMeta)):
urlretrieve(url, target, report_hook)
return target
elif parsed_url.scheme in ('git', 'git+ssh', 'git+http', 'git+https'):
elif parsed_url.scheme in ('git', 'git+file', 'git+ssh', 'git+http', 'git+https'):
if isdir(target):
with current_directory(target):
shprint(sh.git, 'fetch', '--tags')
@ -168,43 +167,6 @@ class Recipe(with_metaclass(RecipeMeta)):
shprint(sh.git, 'submodule', 'update', '--recursive')
return target
def extract_source(self, source, cwd):
"""
(internal) Extract the `source` into the directory `cwd`.
"""
if not source:
return
if isfile(source):
info("Extract {} into {}".format(source, cwd))
if source.endswith(".tgz") or source.endswith(".tar.gz"):
shprint(sh.tar, "-C", cwd, "-xvzf", source)
elif source.endswith(".tbz2") or source.endswith(".tar.bz2"):
shprint(sh.tar, "-C", cwd, "-xvjf", source)
elif source.endswith(".zip"):
zf = zipfile.ZipFile(source)
zf.extractall(path=cwd)
zf.close()
else:
warning(
"Error: cannot extract, unrecognized extension for {}"
.format(source))
raise Exception()
elif isdir(source):
info("Copying {} into {}".format(source, cwd))
shprint(sh.cp, '-a', source, cwd)
else:
warning(
"Error: cannot extract or copy, unrecognized path {}"
.format(source))
raise Exception()
# def get_archive_rootdir(self, filename):
# if filename.endswith(".tgz") or filename.endswith(".tar.gz") or \
# filename.endswith(".tbz2") or filename.endswith(".tar.bz2"):
@ -225,19 +187,19 @@ class Recipe(with_metaclass(RecipeMeta)):
build directory.
"""
info("Applying patch {}".format(filename))
filename = join(self.recipe_dir, filename)
filename = join(self.get_recipe_dir(), filename)
shprint(sh.patch, "-t", "-d", self.get_build_dir(arch), "-p1",
"-i", filename, _tail=10)
def copy_file(self, filename, dest):
info("Copy {} to {}".format(filename, dest))
filename = join(self.recipe_dir, filename)
filename = join(self.get_recipe_dir(), filename)
dest = join(self.build_dir, dest)
shutil.copy(filename, dest)
def append_file(self, filename, dest):
info("Append {} to {}".format(filename, dest))
filename = join(self.recipe_dir, filename)
filename = join(self.get_recipe_dir(), filename)
dest = join(self.build_dir, dest)
with open(filename, "rb") as fd:
data = fd.read()
@ -329,7 +291,14 @@ class Recipe(with_metaclass(RecipeMeta)):
return join(self.get_build_container_dir(arch), self.name)
def get_recipe_dir(self):
# AND: Redundant, an equivalent property is already set by get_recipe
"""
Returns the local recipe directory or defaults to the core recipe
directory.
"""
if self.ctx.local_recipes is not None:
local_recipe_dir = join(self.ctx.local_recipes, self.name)
if exists(local_recipe_dir):
return local_recipe_dir
return join(self.ctx.root_dir, 'recipes', self.name)
# Public Recipe API to be subclassed if needed
@ -349,6 +318,16 @@ class Recipe(with_metaclass(RecipeMeta)):
return
url = self.versioned_url
ma = match(u'^(.+)#md5=([0-9a-f]{32})$', url)
if ma: # fragmented URL?
if self.md5sum:
raise ValueError(
('Received md5sum from both the {} recipe '
'and its url').format(self.name))
url = ma.group(1)
expected_md5 = ma.group(2)
else:
expected_md5 = self.md5sum
shprint(sh.mkdir, '-p', join(self.ctx.packages_path, self.name))
@ -356,44 +335,41 @@ class Recipe(with_metaclass(RecipeMeta)):
filename = shprint(sh.basename, url).stdout[:-1].decode('utf-8')
do_download = True
marker_filename = '.mark-{}'.format(filename)
if exists(filename) and isfile(filename):
if not exists(marker_filename):
shprint(sh.rm, filename)
elif self.md5sum:
elif expected_md5:
current_md5 = md5sum(filename)
if current_md5 == self.md5sum:
debug('Checked md5sum: downloaded expected content!')
do_download = False
else:
info('Downloaded unexpected content...')
if current_md5 != expected_md5:
debug('* Generated md5sum: {}'.format(current_md5))
debug('* Expected md5sum: {}'.format(self.md5sum))
debug('* Expected md5sum: {}'.format(expected_md5))
raise ValueError(
('Generated md5sum does not match expected md5sum '
'for {} recipe').format(self.name))
do_download = False
else:
do_download = False
info('{} download already cached, skipping'
.format(self.name))
# If we got this far, we will download
if do_download:
debug('Downloading {} from {}'.format(self.name, url))
shprint(sh.rm, '-f', marker_filename)
self.download_file(url, filename)
self.download_file(self.versioned_url, filename)
shprint(sh.touch, marker_filename)
if exists(filename) and isfile(filename) and self.md5sum:
if exists(filename) and isfile(filename) and expected_md5:
current_md5 = md5sum(filename)
if self.md5sum is not None:
if current_md5 == self.md5sum:
debug('Checked md5sum: downloaded expected content!')
else:
info('Downloaded unexpected content...')
if expected_md5 is not None:
if current_md5 != expected_md5:
debug('* Generated md5sum: {}'.format(current_md5))
debug('* Expected md5sum: {}'.format(self.md5sum))
exit(1)
debug('* Expected md5sum: {}'.format(expected_md5))
raise ValueError(
('Generated md5sum does not match expected md5sum '
'for {} recipe').format(self.name))
else:
info('{} download already cached, skipping'.format(self.name))
def unpack(self, arch):
info_main('Unpacking {} for {}'.format(self.name, arch))
@ -404,8 +380,6 @@ class Recipe(with_metaclass(RecipeMeta)):
if user_dir is not None:
info('P4A_{}_DIR exists, symlinking instead'.format(
self.name.lower()))
# AND: Currently there's something wrong if I use ln, fix this
warning('Using cp -a instead of symlink...fix this!')
if exists(self.get_build_dir(arch)):
return
shprint(sh.rm, '-rf', build_dir)
@ -421,11 +395,13 @@ class Recipe(with_metaclass(RecipeMeta)):
filename = shprint(
sh.basename, self.versioned_url).stdout[:-1].decode('utf-8')
ma = match(u'^(.+)#md5=([0-9a-f]{32})$', filename)
if ma: # fragmented URL?
filename = ma.group(1)
with current_directory(build_dir):
directory_name = self.get_build_dir(arch)
# AND: Could use tito's get_archive_rootdir here
if not exists(directory_name) or not isdir(directory_name):
extraction_filename = join(
self.ctx.packages_path, self.name, filename)
@ -638,7 +614,6 @@ class Recipe(with_metaclass(RecipeMeta)):
if len(logger.handlers) > 1:
logger.removeHandler(logger.handlers[1])
recipe = mod.recipe
recipe.recipe_dir = dirname(recipe_file)
recipe.ctx = ctx
cls.recipes[name] = recipe
return recipe
@ -755,6 +730,10 @@ class PythonRecipe(Recipe):
return join(
Recipe.get_recipe('hostpython2', self.ctx).get_build_dir(),
'hostpython')
elif 'hostpython3crystax' in self.ctx.recipe_build_order:
return join(
Recipe.get_recipe('hostpython3crystax', self.ctx).get_build_dir(),
'hostpython')
else:
python_recipe = self.ctx.python_recipe
return 'python{}'.format(python_recipe.version)
@ -779,6 +758,34 @@ class PythonRecipe(Recipe):
env['PYTHONNOUSERSITE'] = '1'
if not self.call_hostpython_via_targetpython:
# sets python headers/linkages...depending on python's recipe
python_version = self.ctx.python_recipe.version
python_short_version = '.'.join(python_version.split('.')[:2])
if 'python2' in self.ctx.recipe_build_order:
env['PYTHON_ROOT'] = self.ctx.get_python_install_dir()
env['CFLAGS'] += ' -I' + env[
'PYTHON_ROOT'] + '/include/python2.7'
env['LDFLAGS'] += ' -L' + env['PYTHON_ROOT'] + '/lib' + \
' -lpython2.7'
elif self.ctx.python_recipe.from_crystax:
ndk_dir_python = join(self.ctx.ndk_dir, 'sources',
'python', python_version)
env['CFLAGS'] += ' -I{} '.format(
join(ndk_dir_python, 'include',
'python'))
env['LDFLAGS'] += ' -L{}'.format(
join(ndk_dir_python, 'libs', arch.arch))
env['LDFLAGS'] += ' -lpython{}m'.format(python_short_version)
elif 'python3' in self.ctx.recipe_build_order:
# This headers are unused cause python3 recipe was removed
# TODO: should be reviewed when python3 recipe added
env['PYTHON_ROOT'] = self.ctx.get_python_install_dir()
env['CFLAGS'] += ' -I' + env[
'PYTHON_ROOT'] + '/include/python{}m'.format(
python_short_version)
env['LDFLAGS'] += ' -L' + env['PYTHON_ROOT'] + '/lib' + \
' -lpython{}m'.format(
python_short_version)
hppath = []
hppath.append(join(dirname(self.hostpython_location), 'Lib'))
hppath.append(join(hppath[0], 'site-packages'))
@ -819,28 +826,12 @@ class PythonRecipe(Recipe):
with current_directory(self.get_build_dir(arch.arch)):
hostpython = sh.Command(self.hostpython_location)
if self.ctx.python_recipe.from_crystax:
# hppath = join(dirname(self.hostpython_location), 'Lib',
# 'site-packages')
hpenv = env.copy()
# if 'PYTHONPATH' in hpenv:
# hpenv['PYTHONPATH'] = ':'.join([hppath] +
# hpenv['PYTHONPATH'].split(':'))
# else:
# hpenv['PYTHONPATH'] = hppath
# hpenv['PYTHONHOME'] = self.ctx.get_python_install_dir()
# shprint(hostpython, 'setup.py', 'build',
# _env=hpenv, *self.setup_extra_args)
shprint(hostpython, 'setup.py', 'install', '-O2',
'--root={}'.format(self.ctx.get_python_install_dir()),
'--install-lib=.',
# AND: will need to unhardcode the 3.5 when adding 2.7 (and other crystax supported versions)
_env=hpenv, *self.setup_extra_args)
# site_packages_dir = self.ctx.get_site_packages_dir()
# built_files = glob.glob(join('build', 'lib*', '*'))
# for filen in built_files:
# shprint(sh.cp, '-r', filen, join(site_packages_dir, split(filen)[-1]))
elif self.call_hostpython_via_targetpython:
shprint(hostpython, 'setup.py', 'install', '-O2', _env=env,
*self.setup_extra_args)
@ -857,7 +848,6 @@ class PythonRecipe(Recipe):
'--root={}'.format(self.ctx.get_python_install_dir()),
'--install-lib=lib/python2.7/site-packages',
_env=hpenv, *self.setup_extra_args)
# AND: Hardcoded python2.7 needs fixing
# If asked, also install in the hostpython build dir
if self.install_in_hostpython:
@ -917,6 +907,7 @@ class CompiledComponentsPythonRecipe(PythonRecipe):
shprint(hostpython, 'setup.py', self.build_cmd, '-v', _env=env,
*self.setup_extra_args)
class CppCompiledComponentsPythonRecipe(CompiledComponentsPythonRecipe):
""" Extensions that require the cxx-stl """
call_hostpython_via_targetpython = False
@ -926,39 +917,34 @@ class CppCompiledComponentsPythonRecipe(CompiledComponentsPythonRecipe):
keys = dict(
ctx=self.ctx,
arch=arch,
arch_noeabi=arch.arch.replace('eabi', ''),
pyroot=self.ctx.get_python_install_dir()
arch_noeabi=arch.arch.replace('eabi', '')
)
env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
env['CFLAGS'] += " -I{pyroot}/include/python2.7 " \
" -I{ctx.ndk_dir}/platforms/android-{ctx.android_min_api}/arch-{arch_noeabi}/usr/include" \
env['CFLAGS'] += " -I{ctx.ndk_dir}/platforms/android-{ctx.android_api}/arch-{arch_noeabi}/usr/include" \
" -I{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/include" \
" -I{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/libs/{arch.arch}/include".format(**keys)
env['CXXFLAGS'] = env['CFLAGS'] + ' -frtti -fexceptions'
env['LDFLAGS'] += " -L{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/libs/{arch.arch}" \
" -lpython2.7" \
" -lgnustl_shared".format(**keys)
return env
def build_compiled_components(self,arch):
def build_compiled_components(self, arch):
super(CppCompiledComponentsPythonRecipe, self).build_compiled_components(arch)
# Copy libgnustl_shared.so
with current_directory(self.get_build_dir(arch.arch)):
sh.cp(
"{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/libs/{arch.arch}/libgnustl_shared.so".format(ctx=self.ctx,arch=arch),
"{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/libs/{arch.arch}/libgnustl_shared.so".format(ctx=self.ctx, arch=arch),
self.ctx.get_libs_dir(arch.arch)
)
class CythonRecipe(PythonRecipe):
pre_build_ext = False
cythonize = True
cython_args = []
call_hostpython_via_targetpython = False
def __init__(self, *args, **kwargs):
super(CythonRecipe, self).__init__(*args, **kwargs)
@ -1082,21 +1068,6 @@ class CythonRecipe(PythonRecipe):
env['LIBLINK_PATH'] = liblink_path
ensure_dir(liblink_path)
if self.ctx.python_recipe.from_crystax:
env['CFLAGS'] = '-I{} '.format(
join(self.ctx.ndk_dir, 'sources', 'python',
self.ctx.python_recipe.version, 'include',
'python')) + env['CFLAGS']
# Temporarily hardcode the -lpython3.x as this does not
# get applied automatically in some environments. This
# will need generalising, along with the other hardcoded
# py3.5 references, to support other python3 or crystax
# python versions.
python3_version = self.ctx.python_recipe.version
python3_version = '.'.join(python3_version.split('.')[:2])
env['LDFLAGS'] = env['LDFLAGS'] + ' -lpython{}m'.format(python3_version)
return env