Integrate fixes from https://github.com/kivy/python-for-android/pull/1197 for minimum Android API support. Minimum Android API set to 21.

This commit is contained in:
Akinwale Ariwodola 2018-04-11 11:30:16 -04:00
parent a90c795891
commit 43deedd994
6 changed files with 62 additions and 25 deletions

View file

@ -92,7 +92,7 @@ android.permissions = INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
android.api = 23 android.api = 23
# (int) Minimum API required # (int) Minimum API required
android.minapi = 16 android.minapi = 21
# (int) Android SDK version to use # (int) Android SDK version to use
android.sdk = 23 android.sdk = 23

View file

@ -92,7 +92,7 @@ android.permissions = INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
android.api = 23 android.api = 23
# (int) Minimum API required # (int) Minimum API required
android.minapi = 16 android.minapi = 21
# (int) Android SDK version to use # (int) Android SDK version to use
android.sdk = 23 android.sdk = 23

View file

@ -47,6 +47,8 @@ class Context(object):
symlink_java_src = False # If True, will symlink instead of copying during build symlink_java_src = False # If True, will symlink instead of copying during build
java_build_tool = 'auto'
@property @property
def packages_path(self): def packages_path(self):
'''Where packages are downloaded before being unpacked''' '''Where packages are downloaded before being unpacked'''
@ -158,7 +160,8 @@ class Context(object):
self._ndk_dir = value self._ndk_dir = value
def prepare_build_environment(self, user_sdk_dir, user_ndk_dir, def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
user_android_api, user_ndk_ver): user_android_api, user_android_min_api,
user_ndk_ver):
'''Checks that build dependencies exist and sets internal variables '''Checks that build dependencies exist and sets internal variables
for the Android SDK etc. for the Android SDK etc.
@ -171,8 +174,6 @@ class Context(object):
if self._build_env_prepared: if self._build_env_prepared:
return return
# AND: This needs revamping to carefully check each dependency
# in turn
ok = True ok = True
# Work out where the Android SDK is # Work out where the Android SDK is
@ -184,7 +185,7 @@ class Context(object):
if sdk_dir is None: # This seems used more conventionally if sdk_dir is None: # This seems used more conventionally
sdk_dir = environ.get('ANDROID_HOME', None) sdk_dir = environ.get('ANDROID_HOME', None)
if sdk_dir is None: # Checks in the buildozer SDK dir, useful if sdk_dir is None: # Checks in the buildozer SDK dir, useful
# # for debug tests of p4a # for debug tests of p4a
possible_dirs = glob.glob(expanduser(join( possible_dirs = glob.glob(expanduser(join(
'~', '.buildozer', 'android', 'platform', 'android-sdk-*'))) '~', '.buildozer', 'android', 'platform', 'android-sdk-*')))
possible_dirs = [d for d in possible_dirs if not possible_dirs = [d for d in possible_dirs if not
@ -226,6 +227,30 @@ class Context(object):
error('You probably want to build with --arch=armeabi-v7a instead') error('You probably want to build with --arch=armeabi-v7a instead')
exit(1) exit(1)
# try to determinate min_api
android_min_api = None
if user_android_min_api:
android_min_api = user_android_min_api
if android_min_api is not None:
info('Getting Minimum Android API version from user argument')
if android_min_api is None:
android_min_api = environ.get("ANDROIDMINAPI", None)
if android_min_api is not None:
info('Found Android minimum api in $ANDROIDMINAPI')
if android_min_api is None:
info('Minimum Android API was not set, using current Android API '
'{}'.format(android_api))
android_min_api = android_api
android_min_api = int(android_min_api)
self.android_min_api = android_min_api
info("Requested API {} (minimum {})".format(
self.android_api, self.android_min_api))
if self.android_min_api > android_api:
error('Android minimum api cannot be higher than Android api')
exit(1)
if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')): if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager')) avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n') targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n')
@ -235,6 +260,7 @@ class Context(object):
else: else:
error('Could not find `android` or `sdkmanager` binaries in ' error('Could not find `android` or `sdkmanager` binaries in '
'Android SDK. Exiting.') 'Android SDK. Exiting.')
exit(1)
apis = [s for s in targets if re.match(r'^ *API level: ', s)] apis = [s for s in targets if re.match(r'^ *API level: ', s)]
apis = [re.findall(r'[0-9]+', s) for s in apis] apis = [re.findall(r'[0-9]+', s) for s in apis]
apis = [int(s[0]) for s in apis if s] apis = [int(s[0]) for s in apis if s]
@ -323,8 +349,9 @@ class Context(object):
warning('If the NDK dir result is correct, you don\'t ' warning('If the NDK dir result is correct, you don\'t '
'need to manually set the NDK ver.') 'need to manually set the NDK ver.')
if ndk_ver is None: if ndk_ver is None:
warning('Android NDK version could not be found, exiting.') warning('Android NDK version could not be found. This probably'
exit(1) 'won\'t cause any problems, but if necessary you can'
'set it with `--ndk-version=...`.')
self.ndk_ver = ndk_ver self.ndk_ver = ndk_ver
info('Using {} NDK {}'.format(self.ndk.capitalize(), self.ndk_ver)) info('Using {} NDK {}'.format(self.ndk.capitalize(), self.ndk_ver))
@ -359,7 +386,7 @@ class Context(object):
ok = False ok = False
warning("Missing requirement: cython is not installed") warning("Missing requirement: cython is not installed")
# AND: need to change if supporting multiple archs at once # This would need to be changed if supporting multiarch APKs
arch = self.archs[0] arch = self.archs[0]
platform_dir = arch.platform_dir platform_dir = arch.platform_dir
toolchain_prefix = arch.toolchain_prefix toolchain_prefix = arch.toolchain_prefix
@ -367,7 +394,7 @@ class Context(object):
self.ndk_platform = join( self.ndk_platform = join(
self.ndk_dir, self.ndk_dir,
'platforms', 'platforms',
'android-{}'.format(self.android_api), 'android-{}'.format(self.android_min_api),
platform_dir) platform_dir)
if not exists(self.ndk_platform): if not exists(self.ndk_platform):
warning('ndk_platform doesn\'t exist: {}'.format( warning('ndk_platform doesn\'t exist: {}'.format(
@ -496,7 +523,7 @@ class Context(object):
dir. dir.
''' '''
# AND: This *must* be replaced with something more general in # This needs to be replaced with something more general in
# order to support multiple python versions and/or multiple # order to support multiple python versions and/or multiple
# archs. # archs.
if self.python_recipe.from_crystax: if self.python_recipe.from_crystax:
@ -575,7 +602,6 @@ def build_recipes(build_order, python_modules, ctx):
.format(recipe.name)) .format(recipe.name))
# 4) biglink everything # 4) biglink everything
# AND: Should make this optional
info_main('# Biglinking object files') info_main('# Biglinking object files')
if not ctx.python_recipe or not ctx.python_recipe.from_crystax: if not ctx.python_recipe or not ctx.python_recipe.from_crystax:
biglink(ctx, arch) biglink(ctx, arch)
@ -666,12 +692,17 @@ def biglink(ctx, arch):
info('target {}'.format(join(ctx.get_libs_dir(arch.arch), info('target {}'.format(join(ctx.get_libs_dir(arch.arch),
'libpymodules.so'))) 'libpymodules.so')))
do_biglink = copylibs_function if ctx.copy_libs else biglink_function do_biglink = copylibs_function if ctx.copy_libs else biglink_function
do_biglink(
join(ctx.get_libs_dir(arch.arch), 'libpymodules.so'), # Move to the directory containing crtstart_so.o and crtend_so.o
obj_dir.split(' '), # This is necessary with newer NDKs? A gcc bug?
extra_link_dirs=[join(ctx.bootstrap.build_dir, with current_directory(join(ctx.ndk_platform, 'usr', 'lib')):
'obj', 'local', arch.arch)], do_biglink(
env=env) join(ctx.get_libs_dir(arch.arch), 'libpymodules.so'),
obj_dir.split(' '),
extra_link_dirs=[join(ctx.bootstrap.build_dir,
'obj', 'local', arch.arch),
os.path.abspath('.')],
env=env)
def biglink_function(soname, objs_paths, extra_link_dirs=[], env=None): def biglink_function(soname, objs_paths, extra_link_dirs=[], env=None):

View file

@ -30,31 +30,31 @@ def is_arch(xarch):
def is_api_gt(apiver): def is_api_gt(apiver):
def is_x(recipe, **kwargs): def is_x(recipe, **kwargs):
return recipe.ctx.android_api > apiver return recipe.ctx.android_min_api > apiver
return is_x return is_x
def is_api_gte(apiver): def is_api_gte(apiver):
def is_x(recipe, **kwargs): def is_x(recipe, **kwargs):
return recipe.ctx.android_api >= apiver return recipe.ctx.android_min_api >= apiver
return is_x return is_x
def is_api_lt(apiver): def is_api_lt(apiver):
def is_x(recipe, **kwargs): def is_x(recipe, **kwargs):
return recipe.ctx.android_api < apiver return recipe.ctx.android_min_api < apiver
return is_x return is_x
def is_api_lte(apiver): def is_api_lte(apiver):
def is_x(recipe, **kwargs): def is_x(recipe, **kwargs):
return recipe.ctx.android_api <= apiver return recipe.ctx.android_min_api <= apiver
return is_x return is_x
def is_api(apiver): def is_api(apiver):
def is_x(recipe, **kwargs): def is_x(recipe, **kwargs):
return recipe.ctx.android_api == apiver return recipe.ctx.android_min_api == apiver
return is_x return is_x
@ -68,4 +68,3 @@ def is_ndk(ndk):
def is_x(recipe, **kwargs): def is_x(recipe, **kwargs):
return recipe.ctx.ndk == ndk return recipe.ctx.ndk == ndk
return is_x return is_x

View file

@ -931,7 +931,7 @@ class CppCompiledComponentsPythonRecipe(CompiledComponentsPythonRecipe):
) )
env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions' env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
env['CFLAGS'] += " -I{pyroot}/include/python2.7 " \ env['CFLAGS'] += " -I{pyroot}/include/python2.7 " \
" -I{ctx.ndk_dir}/platforms/android-{ctx.android_api}/arch-{arch_noeabi}/usr/include" \ " -I{ctx.ndk_dir}/platforms/android-{ctx.android_min_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}/include" \
" -I{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/libs/{arch.arch}/include".format(**keys) " -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['CXXFLAGS'] = env['CFLAGS'] + ' -frtti -fexceptions'

View file

@ -141,6 +141,7 @@ def require_prebuilt_dist(func):
ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir, ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir,
user_ndk_dir=self.ndk_dir, user_ndk_dir=self.ndk_dir,
user_android_api=self.android_api, user_android_api=self.android_api,
user_android_min_api=self.android_min_api,
user_ndk_ver=self.ndk_version) user_ndk_ver=self.ndk_version)
dist = self._dist dist = self._dist
if dist.needs_build: if dist.needs_build:
@ -256,6 +257,9 @@ class ToolchainCL(object):
generic_parser.add_argument( generic_parser.add_argument(
'--android-api', '--android_api', dest='android_api', default=0, type=int, '--android-api', '--android_api', dest='android_api', default=0, type=int,
help='The Android API level to build against.') help='The Android API level to build against.')
generic_parser.add_argument(
'--android-minapi', '--android_minapi', dest='android_min_api', default=0, type=int,
help='The Minimum Android API level to build against (will be used for all C compilation).')
generic_parser.add_argument( generic_parser.add_argument(
'--ndk-version', '--ndk_version', dest='ndk_version', default='', '--ndk-version', '--ndk_version', dest='ndk_version', default='',
help=('The version of the Android NDK. This is optional, ' help=('The version of the Android NDK. This is optional, '
@ -499,6 +503,7 @@ class ToolchainCL(object):
self.sdk_dir = args.sdk_dir self.sdk_dir = args.sdk_dir
self.ndk_dir = args.ndk_dir self.ndk_dir = args.ndk_dir
self.android_api = args.android_api self.android_api = args.android_api
self.android_min_api = args.android_min_api
self.ndk_version = args.ndk_version self.ndk_version = args.ndk_version
self.ctx.symlink_java_src = args.symlink_java_src self.ctx.symlink_java_src = args.symlink_java_src
self.ctx.java_build_tool = args.java_build_tool self.ctx.java_build_tool = args.java_build_tool
@ -904,6 +909,7 @@ class ToolchainCL(object):
ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir, ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir,
user_ndk_dir=self.ndk_dir, user_ndk_dir=self.ndk_dir,
user_android_api=self.android_api, user_android_api=self.android_api,
user_android_min_api=self.android_min_api,
user_ndk_ver=self.ndk_version) user_ndk_ver=self.ndk_version)
android = sh.Command(join(ctx.sdk_dir, 'tools', args.tool)) android = sh.Command(join(ctx.sdk_dir, 'tools', args.tool))
output = android( output = android(
@ -931,6 +937,7 @@ class ToolchainCL(object):
ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir, ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir,
user_ndk_dir=self.ndk_dir, user_ndk_dir=self.ndk_dir,
user_android_api=self.android_api, user_android_api=self.android_api,
user_android_min_api=self.android_min_api,
user_ndk_ver=self.ndk_version) user_ndk_ver=self.ndk_version)
if platform in ('win32', 'cygwin'): if platform in ('win32', 'cygwin'):
adb = sh.Command(join(ctx.sdk_dir, 'platform-tools', 'adb.exe')) adb = sh.Command(join(ctx.sdk_dir, 'platform-tools', 'adb.exe'))