Skip to content

Commit 9bfaf33

Browse files
committed
ndk lib folder (or ndk platform) now is ABI specific
1 parent 0182e05 commit 9bfaf33

File tree

17 files changed

+114
-102
lines changed

17 files changed

+114
-102
lines changed

pythonforandroid/archs.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from distutils.spawn import find_executable
22
from os import environ
3-
from os.path import join, split
3+
from os.path import join, split, exists
44
from multiprocessing import cpu_count
55
from glob import glob
66

7+
from pythonforandroid.logger import warning
78
from pythonforandroid.recipe import Recipe
89
from pythonforandroid.util import BuildInterruptingException, build_platform
910

@@ -30,7 +31,7 @@ class Arch:
3031
common_cppflags = [
3132
'-DANDROID',
3233
'-D__ANDROID_API__={ctx.ndk_api}',
33-
'-I{ctx.ndk_dir}/sysroot/usr/include/{command_prefix}',
34+
'-I{ctx.ndk_sysroot}/usr/include/{command_prefix}',
3435
'-I{python_includes}',
3536
]
3637

@@ -57,6 +58,24 @@ def __init__(self, ctx):
5758
def __str__(self):
5859
return self.arch
5960

61+
@property
62+
def ndk_lib_dir(self):
63+
return join(self.ctx.ndk_sysroot, 'usr', 'lib', self.command_prefix, str(self.ctx.ndk_api))
64+
65+
@property
66+
def ndk_platform(self):
67+
warning("ndk_platform is deprecated and should be avoided in new recipes")
68+
ndk_platform = join(
69+
self.ctx.ndk_dir,
70+
'platforms',
71+
'android-{}'.format(self.ctx.ndk_api),
72+
self.platform_dir)
73+
if not exists(ndk_platform):
74+
BuildInterruptingException(
75+
"The requested platform folder doesn't exist. If you're building on ndk >= r22, and seeing this error, one of the required recipe is using a removed feature."
76+
)
77+
return ndk_platform
78+
6079
@property
6180
def include_dirs(self):
6281
return [
@@ -213,8 +232,8 @@ def get_env(self, with_flags_in_cc=True):
213232
# Android's arch/toolchain
214233
env['ARCH'] = self.arch
215234
env['NDK_API'] = 'android-{}'.format(str(self.ctx.ndk_api))
216-
env['TOOLCHAIN_PREFIX'] = self.ctx.toolchain_prefix
217-
env['TOOLCHAIN_VERSION'] = self.ctx.toolchain_version
235+
env['TOOLCHAIN_PREFIX'] = self.toolchain_prefix
236+
env['TOOLCHAIN_VERSION'] = self.toolchain_version
218237

219238
# Custom linker options
220239
env['LDSHARED'] = env['CC'] + ' ' + ' '.join(self.common_ldshared)

pythonforandroid/build.py

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,18 @@
2424
from pythonforandroid.recommendations import (
2525
check_ndk_version, check_target_api, check_ndk_api,
2626
RECOMMENDED_NDK_API, RECOMMENDED_TARGET_API)
27+
from pythonforandroid.util import build_platform
2728

2829

29-
def get_ndk_platform_dir(ndk_dir, ndk_api, arch):
30-
ndk_platform_dir_exists = True
31-
platform_dir = arch.platform_dir
32-
ndk_platform = join(
33-
ndk_dir,
34-
'platforms',
35-
'android-{}'.format(ndk_api),
36-
platform_dir)
37-
if not exists(ndk_platform):
38-
warning("ndk_platform doesn't exist: {}".format(ndk_platform))
39-
ndk_platform_dir_exists = False
40-
return ndk_platform, ndk_platform_dir_exists
30+
def get_ndk_standalone(ndk_dir):
31+
return join(ndk_dir, 'toolchains', 'llvm', 'prebuilt', build_platform)
32+
33+
34+
def get_ndk_sysroot(ndk_dir):
35+
sysroot = join(get_ndk_standalone(ndk_dir), 'sysroot')
36+
if not exists(sysroot):
37+
warning("sysroot doesn't exist: {}".format(sysroot))
38+
return sysroot
4139

4240

4341
def get_toolchain_versions(ndk_dir, arch):
@@ -114,7 +112,8 @@ class Context:
114112

115113
ccache = None # whether to use ccache
116114

117-
ndk_platform = None # the ndk platform directory
115+
ndk_standalone = None
116+
ndk_include_dir = None # usr/include
118117

119118
bootstrap = None
120119
bootstrap_build_dir = None
@@ -296,7 +295,9 @@ def prepare_build_environment(self,
296295
android_api = int(android_api)
297296
self.android_api = android_api
298297

299-
check_target_api(android_api, self.archs[0].arch)
298+
for arch in self.archs:
299+
# Maybe We could remove this one in a near future (ARMv5 is definitely old)
300+
check_target_api(android_api, arch)
300301
apis = get_available_apis(self.sdk_dir)
301302
info('Available Android APIs are ({})'.format(
302303
', '.join(map(str, apis))))
@@ -375,60 +376,60 @@ def prepare_build_environment(self,
375376
' a python 3 target (which is the default)'
376377
' then THINGS WILL BREAK.')
377378

378-
# This would need to be changed if supporting multiarch APKs
379-
arch = self.archs[0]
380-
toolchain_prefix = arch.toolchain_prefix
381-
self.ndk_platform, ndk_platform_dir_exists = get_ndk_platform_dir(
382-
self.ndk_dir, self.ndk_api, arch)
383-
ok = ok and ndk_platform_dir_exists
384-
385379
py_platform = sys.platform
386380
if py_platform in ['linux2', 'linux3']:
387381
py_platform = 'linux'
388-
toolchain_versions, toolchain_path_exists = get_toolchain_versions(
389-
self.ndk_dir, arch)
390-
ok = ok and toolchain_path_exists
391-
toolchain_versions.sort()
392-
393-
toolchain_versions_gcc = []
394-
for toolchain_version in toolchain_versions:
395-
if toolchain_version[0].isdigit():
396-
# GCC toolchains begin with a number
397-
toolchain_versions_gcc.append(toolchain_version)
398-
399-
if toolchain_versions:
400-
info('Found the following toolchain versions: {}'.format(
401-
toolchain_versions))
402-
info('Picking the latest gcc toolchain, here {}'.format(
403-
toolchain_versions_gcc[-1]))
404-
toolchain_version = toolchain_versions_gcc[-1]
405-
else:
406-
warning('Could not find any toolchain for {}!'.format(
407-
toolchain_prefix))
408-
ok = False
409-
410-
self.toolchain_prefix = toolchain_prefix
411-
self.toolchain_version = toolchain_version
412-
# Modify the path so that sh finds modules appropriately
413-
environ['PATH'] = (
414-
'{ndk_dir}/toolchains/{toolchain_prefix}-{toolchain_version}/'
415-
'prebuilt/{py_platform}-x86/bin/:{ndk_dir}/toolchains/'
416-
'{toolchain_prefix}-{toolchain_version}/prebuilt/'
417-
'{py_platform}-x86_64/bin/:{ndk_dir}:{sdk_dir}/'
418-
'tools:{path}').format(
419-
sdk_dir=self.sdk_dir, ndk_dir=self.ndk_dir,
420-
toolchain_prefix=toolchain_prefix,
421-
toolchain_version=toolchain_version,
422-
py_platform=py_platform, path=environ.get('PATH'))
423-
424-
for executable in ("pkg-config", "autoconf", "automake", "libtoolize",
425-
"tar", "bzip2", "unzip", "make", "gcc", "g++"):
426-
if not sh.which(executable):
427-
warning(f"Missing executable: {executable} is not installed")
428-
429-
if not ok:
430-
raise BuildInterruptingException(
431-
'python-for-android cannot continue due to the missing executables above')
382+
383+
self.ndk_standalone = get_ndk_standalone(self.ndk_dir)
384+
self.ndk_sysroot = get_ndk_sysroot(self.ndk_dir)
385+
ok = ok and exists(self.ndk_sysroot)
386+
self.ndk_include_dir = join(self.ndk_sysroot, 'usr', 'include')
387+
388+
for arch in self.archs:
389+
390+
toolchain_versions, toolchain_path_exists = get_toolchain_versions(
391+
self.ndk_dir, arch)
392+
ok = ok and toolchain_path_exists
393+
toolchain_versions.sort()
394+
395+
toolchain_versions_gcc = []
396+
for toolchain_version in toolchain_versions:
397+
if toolchain_version[0].isdigit():
398+
# GCC toolchains begin with a number
399+
toolchain_versions_gcc.append(toolchain_version)
400+
401+
if toolchain_versions:
402+
info('Found the following toolchain versions: {}'.format(
403+
toolchain_versions))
404+
info('Picking the latest gcc toolchain, here {}'.format(
405+
toolchain_versions_gcc[-1]))
406+
toolchain_version = toolchain_versions_gcc[-1]
407+
else:
408+
warning('Could not find any toolchain for {}!'.format(
409+
arch.toolchain_prefix))
410+
ok = False
411+
412+
# Modify the path so that sh finds modules appropriately
413+
arch.toolchain_version = toolchain_version
414+
environ['PATH'] = (
415+
'{ndk_dir}/toolchains/{toolchain_prefix}-{toolchain_version}/'
416+
'prebuilt/{py_platform}-x86/bin/:{ndk_dir}/toolchains/'
417+
'{toolchain_prefix}-{toolchain_version}/prebuilt/'
418+
'{py_platform}-x86_64/bin/:{ndk_dir}:{sdk_dir}/'
419+
'tools:{path}').format(
420+
sdk_dir=self.sdk_dir, ndk_dir=self.ndk_dir,
421+
toolchain_prefix=arch.toolchain_prefix,
422+
toolchain_version=toolchain_version,
423+
py_platform=py_platform, path=environ.get('PATH'))
424+
425+
for executable in ("pkg-config", "autoconf", "automake", "libtoolize",
426+
"tar", "bzip2", "unzip", "make", "gcc", "g++"):
427+
if not sh.which(executable):
428+
warning(f"Missing executable: {executable} is not installed")
429+
430+
if not ok:
431+
raise BuildInterruptingException(
432+
'python-for-android cannot continue due to the missing executables above')
432433

433434
def __init__(self):
434435
self.include_dirs = []
@@ -441,9 +442,6 @@ def __init__(self):
441442
self._ndk_api = None
442443
self.ndk = None
443444

444-
self.toolchain_prefix = None
445-
self.toolchain_version = None
446-
447445
self.local_recipes = None
448446
self.copy_libs = False
449447

@@ -887,7 +885,7 @@ def biglink(ctx, arch):
887885

888886
# Move to the directory containing crtstart_so.o and crtend_so.o
889887
# This is necessary with newer NDKs? A gcc bug?
890-
with current_directory(join(ctx.ndk_platform, 'usr', 'lib')):
888+
with current_directory(arch.ndk_lib_dir):
891889
do_biglink(
892890
join(ctx.get_libs_dir(arch.arch), 'libpymodules.so'),
893891
obj_dir.split(' '),

pythonforandroid/recipe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ def get_recipe_env(self, arch, with_flags_in_cc=True):
11421142
env['LDSHARED'] = env['CC'] + ' -shared'
11431143
# shprint(sh.whereis, env['LDSHARED'], _env=env)
11441144
env['LIBLINK'] = 'NOTNONE'
1145-
env['NDKPLATFORM'] = self.ctx.ndk_platform
1145+
env['NDKPLATFORM'] = self.ctx.ndk_sysroot # FIXME?
11461146
if self.ctx.copy_libs:
11471147
env['COPYLIBS'] = '1'
11481148

pythonforandroid/recipes/Pillow/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ class PillowRecipe(CompiledComponentsPythonRecipe):
3535
def get_recipe_env(self, arch=None, with_flags_in_cc=True):
3636
env = super().get_recipe_env(arch, with_flags_in_cc)
3737

38-
env['ANDROID_ROOT'] = join(self.ctx.ndk_platform, 'usr')
39-
ndk_lib_dir = join(self.ctx.ndk_platform, 'usr', 'lib')
40-
ndk_include_dir = join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')
38+
env['ANDROID_ROOT'] = join(arch.ndk_platform, 'usr')
39+
ndk_lib_dir = arch.ndk_lib_dir
40+
ndk_include_dir = self.ctx.ndk_include_dir
4141

4242
png = self.get_recipe('png', self.ctx)
4343
png_lib_dir = join(png.get_build_dir(arch.arch), '.libs')

pythonforandroid/recipes/audiostream/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def get_recipe_env(self, arch):
2525
jni_path=join(self.ctx.bootstrap.build_dir, 'jni'),
2626
sdl_include=sdl_include,
2727
sdl_mixer_include=sdl_mixer_include)
28-
env['NDKPLATFORM'] = self.ctx.ndk_platform
28+
env['NDKPLATFORM'] = arch.ndk_platform
2929
env['LIBLINK'] = 'NOTNONE' # Hacky fix. Needed by audiostream setup.py
3030
return env
3131

pythonforandroid/recipes/cffi/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ def get_recipe_env(self, arch=None):
3535
self.ctx.get_libs_dir(arch.arch))
3636
env['LDFLAGS'] += ' -L{}'.format(os.path.join(self.ctx.bootstrap.build_dir, 'libs', arch.arch))
3737
# required for libc and libdl
38-
ndk_dir = self.ctx.ndk_platform
39-
ndk_lib_dir = os.path.join(ndk_dir, 'usr', 'lib')
40-
env['LDFLAGS'] += ' -L{}'.format(ndk_lib_dir)
38+
env['LDFLAGS'] += ' -L{}'.format(arch.ndk_lib_dir)
4139
env['PYTHONPATH'] = ':'.join([
4240
self.ctx.get_site_packages_dir(),
4341
env['BUILDLIB_PATH'],

pythonforandroid/recipes/evdev/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class EvdevRecipe(CompiledComponentsPythonRecipe):
1818

1919
def get_recipe_env(self, arch=None):
2020
env = super().get_recipe_env(arch)
21-
env['NDKPLATFORM'] = self.ctx.ndk_platform
21+
env['NDKPLATFORM'] = arch.ndk_platform
2222
return env
2323

2424

pythonforandroid/recipes/freetype/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ def get_recipe_env(self, arch=None, with_harfbuzz=False):
4747
)
4848

4949
# android's zlib support
50-
zlib_lib_path = join(self.ctx.ndk_platform, 'usr', 'lib')
51-
zlib_includes = join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')
50+
zlib_lib_path = arch.ndk_lib_dir
51+
zlib_includes = self.ctx.ndk_include_dir
5252

5353
def add_flag_if_not_added(flag, env_key):
5454
if flag not in env[env_key]:

pythonforandroid/recipes/libogg/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def build_arch(self, arch):
1212
with current_directory(self.get_build_dir(arch.arch)):
1313
env = self.get_recipe_env(arch)
1414
flags = [
15-
'--with-sysroot=' + self.ctx.ndk_platform,
15+
'--with-sysroot=' + arch.ndk_platform,
1616
'--host=' + arch.toolchain_prefix,
1717
]
1818
configure = sh.Command('./configure')

pythonforandroid/recipes/librt/__init__.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@ class LibRt(Recipe):
1818
libc, so we create a symbolic link which we will remove when our build
1919
finishes'''
2020

21-
@property
22-
def libc_path(self):
23-
return join(self.ctx.ndk_platform, 'usr', 'lib', 'libc')
24-
2521
def build_arch(self, arch):
22+
libc_path = join(arch.ndk_platform, 'usr', 'lib', 'libc')
2623
# Create a temporary folder to add to link path with a fake librt.so:
2724
fake_librt_temp_folder = join(
2825
self.get_build_dir(arch.arch),
@@ -35,13 +32,13 @@ def build_arch(self, arch):
3532
if exists(join(fake_librt_temp_folder, "librt.so")):
3633
remove(join(fake_librt_temp_folder, "librt.so"))
3734
shprint(sh.ln, '-sf',
38-
self.libc_path + '.so',
35+
libc_path + '.so',
3936
join(fake_librt_temp_folder, "librt.so"),
4037
)
4138
if exists(join(fake_librt_temp_folder, "librt.a")):
4239
remove(join(fake_librt_temp_folder, "librt.a"))
4340
shprint(sh.ln, '-sf',
44-
self.libc_path + '.a',
41+
libc_path + '.a',
4542
join(fake_librt_temp_folder, "librt.a"),
4643
)
4744

pythonforandroid/recipes/libvorbis/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def build_arch(self, arch):
2121
with current_directory(self.get_build_dir(arch.arch)):
2222
env = self.get_recipe_env(arch)
2323
flags = [
24-
'--with-sysroot=' + self.ctx.ndk_platform,
24+
'--with-sysroot=' + arch.ndk_platform,
2525
'--host=' + arch.toolchain_prefix,
2626
]
2727
configure = sh.Command('./configure')

pythonforandroid/recipes/lxml/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ def get_recipe_env(self, arch):
5151
env['LIBS'] += ' -lxml2'
5252

5353
# android's ndk flags
54-
ndk_lib_dir = join(self.ctx.ndk_platform, 'usr', 'lib')
55-
ndk_include_dir = join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')
54+
ndk_lib_dir = arch.ndk_lib_dir
55+
ndk_include_dir = self.ndk_include_dir
5656
cflags += ' -I' + ndk_include_dir
5757
env['LDFLAGS'] += ' -L' + ndk_lib_dir
5858
env['LIBS'] += ' -lz -lm -lc'

pythonforandroid/recipes/openssl/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ def get_recipe_env(self, arch=None):
9696
env = super().get_recipe_env(arch)
9797
env['OPENSSL_VERSION'] = self.version
9898
env['MAKE'] = 'make' # This removes the '-j5', which isn't safe
99-
env['ANDROID_NDK'] = self.ctx.ndk_dir
99+
env['CC'] = 'clang'
100+
env['ANDROID_NDK_HOME'] = self.ctx.ndk_dir
100101
return env
101102

102103
def select_build_arch(self, arch):

pythonforandroid/recipes/pygame/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ def prebuild_arch(self, arch):
2828
with current_directory(self.get_build_dir(arch.arch)):
2929
setup_template = open(join("buildconfig", "Setup.Android.SDL2.in")).read()
3030
env = self.get_recipe_env(arch)
31-
env['ANDROID_ROOT'] = join(self.ctx.ndk_platform, 'usr')
32-
33-
ndk_lib_dir = join(self.ctx.ndk_platform, 'usr', 'lib')
31+
env['ANDROID_ROOT'] = join(arch.ndk_platform, 'usr')
3432

3533
png = self.get_recipe('png', self.ctx)
3634
png_lib_dir = join(png.get_build_dir(arch.arch), '.libs')
@@ -43,7 +41,7 @@ def prebuild_arch(self, arch):
4341
sdl_includes=(
4442
" -I" + join(self.ctx.bootstrap.build_dir, 'jni', 'SDL', 'include') +
4543
" -L" + join(self.ctx.bootstrap.build_dir, "libs", str(arch)) +
46-
" -L" + png_lib_dir + " -L" + jpeg_lib_dir + " -L" + ndk_lib_dir),
44+
" -L" + png_lib_dir + " -L" + jpeg_lib_dir + " -L" + arch.ndk_lib_dir),
4745
sdl_ttf_includes="-I"+join(self.ctx.bootstrap.build_dir, 'jni', 'SDL2_ttf'),
4846
sdl_image_includes="-I"+join(self.ctx.bootstrap.build_dir, 'jni', 'SDL2_image'),
4947
sdl_mixer_includes="-I"+join(self.ctx.bootstrap.build_dir, 'jni', 'SDL2_mixer'),

0 commit comments

Comments
 (0)