Skip to content

Commit d919ba7

Browse files
committed
Add support for minimum Android API.
This allows the compilation to use a different version for compiling while targetting a higher API version. Typically, you may need to use API 23 for Java, but want to run on API 19. If you compile with API 23, when running on older device (let's say 4.4.2), you'll end up with a symbol not found "srand", "signal", etc. It is important to set the Android API minimum version when compiling in order to avoid theses symbol issues. CF: https://stackoverflow.com/a/41079462/69877
1 parent 2b3d52b commit d919ba7

File tree

12 files changed

+57
-26
lines changed

12 files changed

+57
-26
lines changed

pythonforandroid/build.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ def ndk_dir(self, value):
160160
self._ndk_dir = value
161161

162162
def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
163-
user_android_api, user_ndk_ver):
163+
user_android_api, user_android_min_api,
164+
user_ndk_ver):
164165
'''Checks that build dependencies exist and sets internal variables
165166
for the Android SDK etc.
166167
@@ -226,6 +227,30 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
226227
error('You probably want to build with --arch=armeabi-v7a instead')
227228
exit(1)
228229

230+
# try to determinate min_api
231+
android_min_api = None
232+
if user_android_min_api:
233+
android_min_api = user_android_min_api
234+
if android_min_api is not None:
235+
info('Getting Minimum Android API version from user argument')
236+
if android_min_api is None:
237+
android_min_api = environ.get("ANDROIDMINAPI", None)
238+
if android_min_api is not None:
239+
info('Found Android minimum api in $ANDROIDMINAPI')
240+
if android_min_api is None:
241+
info('Minimum Android API was not set, using current Android API '
242+
'{}'.format(android_api))
243+
android_min_api = android_api
244+
android_min_api = int(android_min_api)
245+
self.android_min_api = android_min_api
246+
247+
info("Requested API {} (minimum {})".format(
248+
self.android_api, self.android_min_api))
249+
250+
if self.android_min_api > android_api:
251+
error('Android minimum api cannot be higher than Android api')
252+
exit(1)
253+
229254
if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
230255
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
231256
targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n')
@@ -369,7 +394,7 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
369394
self.ndk_platform = join(
370395
self.ndk_dir,
371396
'platforms',
372-
'android-{}'.format(self.android_api),
397+
'android-{}'.format(self.android_min_api),
373398
platform_dir)
374399
if not exists(self.ndk_platform):
375400
warning('ndk_platform doesn\'t exist: {}'.format(

pythonforandroid/patching.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,31 @@ def is_x(arch, **kwargs):
3030

3131
def is_api_gt(apiver):
3232
def is_x(recipe, **kwargs):
33-
return recipe.ctx.android_api > apiver
33+
return recipe.ctx.android_min_api > apiver
3434
return is_x
3535

3636

3737
def is_api_gte(apiver):
3838
def is_x(recipe, **kwargs):
39-
return recipe.ctx.android_api >= apiver
39+
return recipe.ctx.android_min_api >= apiver
4040
return is_x
4141

4242

4343
def is_api_lt(apiver):
4444
def is_x(recipe, **kwargs):
45-
return recipe.ctx.android_api < apiver
45+
return recipe.ctx.android_min_api < apiver
4646
return is_x
4747

4848

4949
def is_api_lte(apiver):
5050
def is_x(recipe, **kwargs):
51-
return recipe.ctx.android_api <= apiver
51+
return recipe.ctx.android_min_api <= apiver
5252
return is_x
5353

5454

5555
def is_api(apiver):
5656
def is_x(recipe, **kwargs):
57-
return recipe.ctx.android_api == apiver
57+
return recipe.ctx.android_min_api == apiver
5858
return is_x
5959

6060

@@ -68,4 +68,3 @@ def is_ndk(ndk):
6868
def is_x(recipe, **kwargs):
6969
return recipe.ctx.ndk == ndk
7070
return is_x
71-

pythonforandroid/recipe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ def get_recipe_env(self, arch):
884884
)
885885
env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
886886
env['CFLAGS'] += " -I{pyroot}/include/python2.7 " \
887-
" -I{ctx.ndk_dir}/platforms/android-{ctx.android_api}/arch-{arch_noeabi}/usr/include" \
887+
" -I{ctx.ndk_dir}/platforms/android-{ctx.android_min_api}/arch-{arch_noeabi}/usr/include" \
888888
" -I{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/include" \
889889
" -I{ctx.ndk_dir}/sources/cxx-stl/gnu-libstdc++/{ctx.toolchain_version}/libs/{arch.arch}/include".format(**keys)
890890
env['CXXFLAGS'] = env['CFLAGS'] + ' -frtti -fexceptions'

pythonforandroid/recipes/boost/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def prebuild_arch(self, arch):
2525
bash = sh.Command('bash')
2626
shprint(bash, join(self.ctx.ndk_dir, 'build/tools/make-standalone-toolchain.sh'),
2727
'--arch=' + env['ARCH'],
28-
'--platform=android-' + str(self.ctx.android_api),
28+
'--platform=android-' + str(self.ctx.android_min_api),
2929
'--toolchain=' + env['CROSSHOST'] + '-' + env['TOOLCHAIN_VERSION'],
3030
'--install-dir=' + env['CROSSHOME']
3131
)
@@ -57,11 +57,11 @@ def get_recipe_env(self, arch):
5757
env['BOOST_ROOT'] = env['BOOST_BUILD_PATH'] # find boost source
5858
env['PYTHON_ROOT'] = self.ctx.get_python_install_dir()
5959
env['ARCH'] = self.select_build_arch(arch)
60-
env['ANDROIDAPI'] = str(self.ctx.android_api)
60+
env['ANDROIDAPI'] = str(self.ctx.android_min_api)
6161
env['CROSSHOST'] = env['ARCH'] + '-linux-androideabi'
6262
env['CROSSHOME'] = join(env['BOOST_ROOT'], 'standalone-' + env['ARCH'] + '-toolchain')
6363
env['TOOLCHAIN_PREFIX'] = join(env['CROSSHOME'], 'bin', env['CROSSHOST'])
6464
return env
6565

6666

67-
recipe = BoostRecipe()
67+
recipe = BoostRecipe()

pythonforandroid/recipes/boost/user-config.jam

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os ;
22

33
local ANDROIDNDK = [ os.environ ANDROIDNDK ] ;
4-
local ANDROIDAPI = [ os.environ ANDROIDAPI ] ;
4+
local ANDROIDMINAPI = [ os.environ ANDROIDMINAPI ] ;
55
local TOOLCHAIN_VERSION = [ os.environ TOOLCHAIN_VERSION ] ;
66
local TOOLCHAIN_PREFIX = [ os.environ TOOLCHAIN_PREFIX ] ;
77
local ARCH = [ os.environ ARCH ] ;
@@ -16,11 +16,11 @@ using gcc : $(ARCH) : $(TOOLCHAIN_PREFIX)-g++ :
1616
<cxxflags>-DBOOST_AC_USE_PTHREADS
1717
<cxxflags>-frtti
1818
<cxxflags>-fexceptions
19-
<compileflags>-I$(ANDROIDNDK)/platforms/android-$(ANDROIDAPI)/arch-$(ARCH)/usr/include
19+
<compileflags>-I$(ANDROIDNDK)/platforms/android-$(ANDROIDMINAPI)/arch-$(ARCH)/usr/include
2020
<compileflags>-I$(ANDROIDNDK)/sources/cxx-stl/gnu-libstdc++/$(TOOLCHAIN_VERSION)/include
2121
<compileflags>-I$(ANDROIDNDK)/sources/cxx-stl/gnu-libstdc++/$(TOOLCHAIN_VERSION)/libs/$(ARCH)/include
2222
<compileflags>-I$(PYTHON_ROOT)/include/python2.7
23-
<linkflags>--sysroot=$(ANDROIDNDK)/platforms/android-$(ANDROIDAPI)/arch-$(ARCH)
23+
<linkflags>--sysroot=$(ANDROIDNDK)/platforms/android-$(ANDROIDMINAPI)/arch-$(ARCH)
2424
<linkflags>-L$(ANDROIDNDK)/sources/cxx-stl/gnu-libstdc++/$(TOOLCHAIN_VERSION)/libs/$(ARCH)
2525
<linkflags>-L$(PYTHON_ROOT)/lib
2626
<linkflags>-lgnustl_shared

pythonforandroid/recipes/ffmpeg/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ def build_arch(self, arch):
4040

4141
if 'openssl' in self.ctx.recipe_build_order:
4242
flags += [
43-
'--enable-openssl',
43+
'--enable-openssl',
4444
'--enable-nonfree',
4545
'--enable-protocol=https,tls_openssl',
4646
]
4747
build_dir = Recipe.get_recipe('openssl', self.ctx).get_build_dir(arch.arch)
4848
cflags += ['-I' + build_dir + '/include/']
4949
ldflags += ['-L' + build_dir]
5050

51-
if 'ffpyplayer_codecs' in self.ctx.recipe_build_order:
51+
if 'ffpyplayer_codecs' in self.ctx.recipe_build_order:
5252
# libx264
5353
flags += ['--enable-libx264']
5454
build_dir = Recipe.get_recipe('libx264', self.ctx).get_build_dir(arch.arch)
@@ -107,16 +107,16 @@ def build_arch(self, arch):
107107

108108
# android:
109109
flags += [
110-
'--target-os=android',
111-
'--cross-prefix=arm-linux-androideabi-',
110+
'--target-os=android',
111+
'--cross-prefix=arm-linux-androideabi-',
112112
'--arch=arm',
113113
'--sysroot=' + self.ctx.ndk_platform,
114114
'--enable-neon',
115115
'--prefix={}'.format(realpath('.')),
116116
]
117117
cflags += [
118-
'-mfpu=vfpv3-d16',
119-
'-mfloat-abi=softfp',
118+
'-mfpu=vfpv3-d16',
119+
'-mfloat-abi=softfp',
120120
'-fPIC',
121121
]
122122

pythonforandroid/recipes/icu/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def get_lib_dir(self, arch):
2121
return lib_dir
2222

2323
def prepare_build_dir(self, arch):
24-
if self.ctx.android_api > 19:
24+
if self.ctx.android_min_api > 19:
2525
# greater versions do not have /usr/include/sys/exec_elf.h
2626
raise RuntimeError("icu needs an android api <= 19")
2727

pythonforandroid/recipes/leveldb/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_recipe_env(self, arch):
3232
if 'snappy' in recipe.ctx.recipe_build_order:
3333
env['CFLAGS'] += ' -DSNAPPY' + \
3434
' -I./snappy'
35-
env['CFLAGS'] += ' -I' + self.ctx.ndk_dir + '/platforms/android-' + str(self.ctx.android_api) + '/arch-' + arch.arch.replace('eabi', '') + '/usr/include' + \
35+
env['CFLAGS'] += ' -I' + self.ctx.ndk_dir + '/platforms/android-' + str(self.ctx.android_min_api) + '/arch-' + arch.arch.replace('eabi', '') + '/usr/include' + \
3636
' -I' + self.ctx.ndk_dir + '/sources/cxx-stl/gnu-libstdc++/' + self.ctx.toolchain_version + '/include' + \
3737
' -I' + self.ctx.ndk_dir + '/sources/cxx-stl/gnu-libstdc++/' + self.ctx.toolchain_version + '/libs/' + arch.arch + '/include'
3838
env['CXXFLAGS'] = env['CFLAGS']

pythonforandroid/recipes/libtorrent/user-config-openssl.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<compileflags>-I$(PYTHON_ROOT)/include/python2.7
1515
+<compileflags>-I$(OPENSSL_BUILD_PATH)/include
1616
+<compileflags>-I$(OPENSSL_BUILD_PATH)/include/openssl
17-
<linkflags>--sysroot=$(ANDROIDNDK)/platforms/android-$(ANDROIDAPI)/arch-$(ARCH)
17+
<linkflags>--sysroot=$(ANDROIDNDK)/platforms/android-$(ANDROIDMINAPI)/arch-$(ARCH)
1818
<linkflags>-L$(ANDROIDNDK)/sources/cxx-stl/gnu-libstdc++/$(TOOLCHAIN_VERSION)/libs/$(ARCH)
1919
<linkflags>-L$(PYTHON_ROOT)/lib
2020
+<linkflags>-L$(OPENSSL_BUILD_PATH)

pythonforandroid/recipes/protobuf_cpp/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def get_recipe_env(self, arch):
9292
env['PYTHON_ROOT'] = self.ctx.get_python_install_dir()
9393
env['TARGET_OS'] = 'OS_ANDROID_CROSSCOMPILE'
9494
env['CFLAGS'] += ' -I' + self.ctx.ndk_dir + '/platforms/android-' + str(
95-
self.ctx.android_api) + '/arch-' + arch.arch.replace('eabi', '') + '/usr/include' + \
95+
self.ctx.android_min_api) + '/arch-' + arch.arch.replace('eabi', '') + '/usr/include' + \
9696
' -I' + self.ctx.ndk_dir + '/sources/cxx-stl/gnu-libstdc++/' + self.ctx.toolchain_version + '/include' + \
9797
' -I' + self.ctx.ndk_dir + '/sources/cxx-stl/gnu-libstdc++/' + self.ctx.toolchain_version + '/libs/' + arch.arch + '/include' + \
9898
' -I' + env['PYTHON_ROOT'] + '/include/python2.7'

pythonforandroid/recipes/pymunk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def get_recipe_env(self, arch):
1818
arch_noeabi = arch.arch.replace('eabi', '')
1919
env['LDFLAGS'] += " -shared -llog"
2020
env['LDFLAGS'] += " -landroid -lpython2.7"
21-
env['LDFLAGS'] += " --sysroot={ctx.ndk_dir}/platforms/android-{ctx.android_api}/arch-{arch_noeabi}".format(
21+
env['LDFLAGS'] += " --sysroot={ctx.ndk_dir}/platforms/android-{ctx.android_min_api}/arch-{arch_noeabi}".format(
2222
ctx=self.ctx, arch_noeabi=arch_noeabi)
2323
return env
2424

pythonforandroid/toolchain.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ def wrapper_func(self, args):
141141
ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir,
142142
user_ndk_dir=self.ndk_dir,
143143
user_android_api=self.android_api,
144+
user_android_min_api=self.android_min_api,
144145
user_ndk_ver=self.ndk_version)
145146
dist = self._dist
146147
if dist.needs_build:
@@ -256,6 +257,9 @@ def __init__(self):
256257
generic_parser.add_argument(
257258
'--android-api', '--android_api', dest='android_api', default=0, type=int,
258259
help='The Android API level to build against.')
260+
generic_parser.add_argument(
261+
'--android-minapi', '--android_minapi', dest='android_min_api', default=0, type=int,
262+
help='The Minimum Android API level to build against (will be used for all C compilation).')
259263
generic_parser.add_argument(
260264
'--ndk-version', '--ndk_version', dest='ndk_version', default='',
261265
help=('The version of the Android NDK. This is optional, '
@@ -499,6 +503,7 @@ def add_parser(subparsers, *args, **kwargs):
499503
self.sdk_dir = args.sdk_dir
500504
self.ndk_dir = args.ndk_dir
501505
self.android_api = args.android_api
506+
self.android_min_api = args.android_min_api
502507
self.ndk_version = args.ndk_version
503508
self.ctx.symlink_java_src = args.symlink_java_src
504509
self.ctx.java_build_tool = args.java_build_tool
@@ -904,6 +909,7 @@ def sdk_tools(self, args):
904909
ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir,
905910
user_ndk_dir=self.ndk_dir,
906911
user_android_api=self.android_api,
912+
user_android_min_api=self.android_min_api,
907913
user_ndk_ver=self.ndk_version)
908914
android = sh.Command(join(ctx.sdk_dir, 'tools', args.tool))
909915
output = android(
@@ -931,6 +937,7 @@ def _adb(self, commands):
931937
ctx.prepare_build_environment(user_sdk_dir=self.sdk_dir,
932938
user_ndk_dir=self.ndk_dir,
933939
user_android_api=self.android_api,
940+
user_android_min_api=self.android_min_api,
934941
user_ndk_ver=self.ndk_version)
935942
if platform in ('win32', 'cygwin'):
936943
adb = sh.Command(join(ctx.sdk_dir, 'platform-tools', 'adb.exe'))

0 commit comments

Comments
 (0)