Skip to content

Commit 653e7a5

Browse files
committed
Adds NDK 23 and Gradle 7 support
1 parent 8b173d9 commit 653e7a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+151
-337
lines changed

ci/constants.py

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ class TargetPython(Enum):
3232
'zope_interface',
3333
# Requires zope_interface, which is broken.
3434
'twisted',
35+
# Mirko: FIXME
36+
'icu',
37+
'genericndkbuild',
38+
'evdev'
3539
])
3640

3741
BROKEN_RECIPES = {

ci/makefiles/android.mk

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Downloads and installs the Android SDK depending on supplied platform: darwin or linux
22

33
# Those android NDK/SDK variables can be override when running the file
4-
ANDROID_NDK_VERSION ?= 19b
4+
ANDROID_NDK_VERSION ?= 23b
55
ANDROID_SDK_TOOLS_VERSION ?= 6514223
66
ANDROID_SDK_BUILD_TOOLS_VERSION ?= 29.0.3
77
ANDROID_HOME ?= $(HOME)/.android
@@ -22,7 +22,7 @@ ANDROID_SDK_TOOLS_DL_URL=https://dl.google.com/android/repository/$(ANDROID_SDK_
2222

2323
ANDROID_NDK_HOME=$(ANDROID_HOME)/android-ndk
2424
ANDROID_NDK_FOLDER=$(ANDROID_HOME)/android-ndk-r$(ANDROID_NDK_VERSION)
25-
ANDROID_NDK_ARCHIVE=android-ndk-r$(ANDROID_NDK_VERSION)-$(TARGET_OS)-x86_64.zip
25+
ANDROID_NDK_ARCHIVE=android-ndk-r$(ANDROID_NDK_VERSION)-$(TARGET_OS).zip
2626
ANDROID_NDK_DL_URL=https://dl.google.com/android/repository/$(ANDROID_NDK_ARCHIVE)
2727

2828
$(info Target install OS is : $(target_os))
@@ -59,7 +59,7 @@ extract_android_sdk:
5959
extract_android_ndk:
6060
mkdir -p $(ANDROID_NDK_FOLDER) \
6161
&& unzip -q $(ANDROID_NDK_ARCHIVE) -d $(ANDROID_HOME) \
62-
&& ln -sfn $(ANDROID_NDK_FOLDER) $(ANDROID_NDK_HOME) \
62+
&& mv $(ANDROID_NDK_FOLDER) $(ANDROID_NDK_HOME) \
6363
&& rm -f $(ANDROID_NDK_ARCHIVE)
6464

6565
# updates Android SDK, install Android API, Build Tools and accept licenses

pythonforandroid/archs.py

+14-53
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
from distutils.spawn import find_executable
22
from os import environ
3-
from os.path import join, split, exists
3+
from os.path import join
44
from multiprocessing import cpu_count
5-
from glob import glob
65

7-
from pythonforandroid.logger import warning
86
from pythonforandroid.recipe import Recipe
97
from pythonforandroid.util import BuildInterruptingException, build_platform
108

119

1210
class Arch:
1311

14-
toolchain_prefix = None
15-
'''The prefix for the toolchain dir in the NDK.'''
16-
1712
command_prefix = None
1813
'''The prefix for NDK commands such as gcc.'''
1914

@@ -30,8 +25,7 @@ class Arch:
3025

3126
common_cppflags = [
3227
'-DANDROID',
33-
'-D__ANDROID_API__={ctx.ndk_api}',
34-
'-I{ctx.ndk_sysroot}/usr/include/{command_prefix}',
28+
'-I{ctx.ndk_sysroot}/usr/include',
3529
'-I{python_includes}',
3630
]
3731

@@ -62,20 +56,6 @@ def __str__(self):
6256
def ndk_lib_dir(self):
6357
return join(self.ctx.ndk_sysroot, 'usr', 'lib', self.command_prefix, str(self.ctx.ndk_api))
6458

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-
7959
@property
8060
def include_dirs(self):
8161
return [
@@ -97,13 +77,10 @@ def target(self):
9777
@property
9878
def clang_path(self):
9979
"""Full path of the clang compiler"""
100-
llvm_dirname = split(
101-
glob(join(self.ctx.ndk_dir, 'toolchains', 'llvm*'))[-1]
102-
)[-1]
10380
return join(
10481
self.ctx.ndk_dir,
10582
'toolchains',
106-
llvm_dirname,
83+
'llvm',
10784
'prebuilt',
10885
build_platform,
10986
'bin',
@@ -190,12 +167,10 @@ def get_env(self, with_flags_in_cc=True):
190167
)
191168

192169
# Compiler: `CC` and `CXX` (and make sure that the compiler exists)
193-
environ['PATH'] = '{clang_path}:{path}'.format(
194-
clang_path=self.clang_path, path=environ['PATH']
195-
)
196-
cc = find_executable(self.clang_exe, path=environ['PATH'])
170+
env['PATH'] = self.ctx.env['PATH']
171+
cc = find_executable(self.clang_exe, path=env['PATH'])
197172
if cc is None:
198-
print('Searching path are: {!r}'.format(environ['PATH']))
173+
print('Searching path are: {!r}'.format(env['PATH']))
199174
raise BuildInterruptingException(
200175
'Couldn\'t find executable for CC. This indicates a '
201176
'problem locating the {} executable in the Android '
@@ -219,21 +194,18 @@ def get_env(self, with_flags_in_cc=True):
219194
execxx=self.clang_exe_cxx,
220195
ccache=ccache)
221196

222-
# Android's binaries
223-
command_prefix = self.command_prefix
224-
env['AR'] = '{}-ar'.format(command_prefix)
225-
env['RANLIB'] = '{}-ranlib'.format(command_prefix)
226-
env['STRIP'] = '{}-strip --strip-unneeded'.format(command_prefix)
197+
# Android's LLVM binutils
198+
env['AR'] = f'{self.clang_path}/llvm-ar'
199+
env['RANLIB'] = f'{self.clang_path}/llvm-ranlib'
200+
env['STRIP'] = f'{self.clang_path}/llvm-strip --strip-unneeded'
201+
env['READELF'] = f'{self.clang_path}/llvm-readelf'
202+
env['OBJCOPY'] = f'{self.clang_path}/llvm-objcopy'
203+
227204
env['MAKE'] = 'make -j{}'.format(str(cpu_count()))
228-
env['READELF'] = '{}-readelf'.format(command_prefix)
229-
env['NM'] = '{}-nm'.format(command_prefix)
230-
env['LD'] = '{}-ld'.format(command_prefix)
231205

232206
# Android's arch/toolchain
233207
env['ARCH'] = self.arch
234208
env['NDK_API'] = 'android-{}'.format(str(self.ctx.ndk_api))
235-
env['TOOLCHAIN_PREFIX'] = self.toolchain_prefix
236-
env['TOOLCHAIN_VERSION'] = self.ctx.toolchain_version
237209

238210
# Custom linker options
239211
env['LDSHARED'] = env['CC'] + ' ' + ' '.join(self.common_ldshared)
@@ -251,8 +223,6 @@ def get_env(self, with_flags_in_cc=True):
251223
),
252224
)
253225

254-
env['PATH'] = environ['PATH']
255-
256226
# for reproducible builds
257227
if 'SOURCE_DATE_EPOCH' in environ:
258228
for k in 'LC_ALL TZ SOURCE_DATE_EPOCH PYTHONHASHSEED BUILD_DATE BUILD_TIME'.split():
@@ -264,9 +234,7 @@ def get_env(self, with_flags_in_cc=True):
264234

265235
class ArchARM(Arch):
266236
arch = "armeabi"
267-
toolchain_prefix = 'arm-linux-androideabi'
268237
command_prefix = 'arm-linux-androideabi'
269-
platform_dir = 'arch-arm'
270238

271239
@property
272240
def target(self):
@@ -290,12 +258,9 @@ class ArchARMv7_a(ArchARM):
290258

291259
class Archx86(Arch):
292260
arch = 'x86'
293-
toolchain_prefix = 'x86'
294261
command_prefix = 'i686-linux-android'
295-
platform_dir = 'arch-x86'
296262
arch_cflags = [
297263
'-march=i686',
298-
'-mtune=intel',
299264
'-mssse3',
300265
'-mfpmath=sse',
301266
'-m32',
@@ -304,26 +269,22 @@ class Archx86(Arch):
304269

305270
class Archx86_64(Arch):
306271
arch = 'x86_64'
307-
toolchain_prefix = 'x86_64'
308272
command_prefix = 'x86_64-linux-android'
309-
platform_dir = 'arch-x86_64'
310273
arch_cflags = [
311274
'-march=x86-64',
312275
'-msse4.2',
313276
'-mpopcnt',
314277
'-m64',
315-
'-mtune=intel',
316278
'-fPIC',
317279
]
318280

319281

320282
class ArchAarch_64(Arch):
321283
arch = 'arm64-v8a'
322-
toolchain_prefix = 'aarch64-linux-android'
323284
command_prefix = 'aarch64-linux-android'
324-
platform_dir = 'arch-arm64'
325285
arch_cflags = [
326286
'-march=armv8-a',
287+
'-fPIC'
327288
# '-I' + join(dirname(__file__), 'includes', 'arm64-v8a'),
328289
]
329290

pythonforandroid/bootstraps/common/build/gradle/wrapper/gradle-wrapper.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip

pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ buildscript {
55
jcenter()
66
}
77
dependencies {
8-
classpath 'com.android.tools.build:gradle:3.5.4'
8+
classpath 'com.android.tools.build:gradle:7.0.1'
99
}
1010
}
1111

pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
{{ args.extra_manifest_application_arguments }}
6363
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
6464
android:hardwareAccelerated="true"
65-
>
65+
android:extractNativeLibs="true" >
6666
{% for l in args.android_used_libs %}
6767
<uses-library android:name="{{ l }}" />
6868
{% endfor %}

pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
android:allowBackup="{{ args.allow_backup }}"
5151
{% if args.backup_rules %}android:fullBackupContent="@xml/{{ args.backup_rules }}"{% endif %}
5252
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
53-
android:hardwareAccelerated="true" >
53+
android:hardwareAccelerated="true"
54+
android:extractNativeLibs="true" >
5455
{% for l in args.android_used_libs %}
5556
<uses-library android:name="{{ l }}" />
5657
{% endfor %}

pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
5353
android:hardwareAccelerated="true"
5454
android:usesCleartextTraffic="true"
55+
android:extractNativeLibs="true"
5556
{% if debug %}android:debuggable="true"{% endif %}
5657
>
5758
{% for l in args.android_used_libs %}

pythonforandroid/build.py

+9-81
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from os.path import (
2-
abspath, join, realpath, dirname, expanduser, exists,
3-
split, isdir
2+
abspath, join, realpath, dirname, expanduser, exists
43
)
54
from os import environ
65
import copy
@@ -40,78 +39,6 @@ def get_ndk_sysroot(ndk_dir):
4039
return sysroot, sysroot_exists
4140

4241

43-
def get_toolchain_versions(ndk_dir, arch):
44-
toolchain_versions = []
45-
toolchain_path_exists = True
46-
toolchain_prefix = arch.toolchain_prefix
47-
toolchain_path = join(ndk_dir, 'toolchains')
48-
if isdir(toolchain_path):
49-
toolchain_contents = glob.glob('{}/{}-*'.format(toolchain_path,
50-
toolchain_prefix))
51-
toolchain_versions = [split(path)[-1][len(toolchain_prefix) + 1:]
52-
for path in toolchain_contents]
53-
else:
54-
warning('Could not find toolchain subdirectory!')
55-
toolchain_path_exists = False
56-
return toolchain_versions, toolchain_path_exists
57-
58-
59-
def select_and_check_toolchain_version(sdk_dir, ndk_dir, arch, ndk_sysroot_exists, py_platform):
60-
toolchain_versions, toolchain_path_exists = get_toolchain_versions(ndk_dir, arch)
61-
ok = ndk_sysroot_exists and toolchain_path_exists
62-
toolchain_versions.sort()
63-
64-
toolchain_versions_gcc = []
65-
for toolchain_version in toolchain_versions:
66-
if toolchain_version[0].isdigit():
67-
# GCC toolchains begin with a number
68-
toolchain_versions_gcc.append(toolchain_version)
69-
70-
if toolchain_versions:
71-
info('Found the following toolchain versions: {}'.format(
72-
toolchain_versions))
73-
info('Picking the latest gcc toolchain, here {}'.format(
74-
toolchain_versions_gcc[-1]))
75-
toolchain_version = toolchain_versions_gcc[-1]
76-
else:
77-
warning('Could not find any toolchain for {}!'.format(
78-
arch.toolchain_prefix))
79-
ok = False
80-
81-
# Modify the path so that sh finds modules appropriately
82-
environ['PATH'] = (
83-
'{ndk_dir}/toolchains/{toolchain_prefix}-{toolchain_version}/'
84-
'prebuilt/{py_platform}-x86/bin/:{ndk_dir}/toolchains/'
85-
'{toolchain_prefix}-{toolchain_version}/prebuilt/'
86-
'{py_platform}-x86_64/bin/:{ndk_dir}:{sdk_dir}/'
87-
'tools:{path}').format(
88-
sdk_dir=sdk_dir, ndk_dir=ndk_dir,
89-
toolchain_prefix=arch.toolchain_prefix,
90-
toolchain_version=toolchain_version,
91-
py_platform=py_platform, path=environ.get('PATH'))
92-
93-
for executable in (
94-
"pkg-config",
95-
"autoconf",
96-
"automake",
97-
"libtoolize",
98-
"tar",
99-
"bzip2",
100-
"unzip",
101-
"make",
102-
"gcc",
103-
"g++",
104-
):
105-
if not sh.which(executable):
106-
warning(f"Missing executable: {executable} is not installed")
107-
108-
if not ok:
109-
raise BuildInterruptingException(
110-
'python-for-android cannot continue due to the missing executables above')
111-
112-
return toolchain_version
113-
114-
11542
def get_targets(sdk_dir):
11643
if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
11744
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
@@ -441,11 +368,14 @@ def prepare_build_environment(self,
441368
self.ndk_sysroot, ndk_sysroot_exists = get_ndk_sysroot(self.ndk_dir)
442369
self.ndk_include_dir = join(self.ndk_sysroot, 'usr', 'include')
443370

444-
for arch in self.archs:
445-
# We assume that the toolchain version is the same for all the archs.
446-
self.toolchain_version = select_and_check_toolchain_version(
447-
self.sdk_dir, self.ndk_dir, arch, ndk_sysroot_exists, py_platform
448-
)
371+
self.env["PATH"] = ":".join(
372+
[
373+
f"{ndk_dir}/toolchains/llvm/prebuilt/{py_platform}-x86_64/bin",
374+
ndk_dir,
375+
f"{sdk_dir}/tools",
376+
environ.get("PATH"),
377+
]
378+
)
449379

450380
def __init__(self):
451381
self.include_dirs = []
@@ -458,8 +388,6 @@ def __init__(self):
458388
self._ndk_api = None
459389
self.ndk = None
460390

461-
self.toolchain_version = None
462-
463391
self.local_recipes = None
464392
self.copy_libs = False
465393

pythonforandroid/recipe.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ def build_arch(self, arch, *extra_args):
818818
env = self.get_recipe_env(arch)
819819
with current_directory(self.get_build_dir(arch.arch)):
820820
shprint(
821-
sh.ndk_build,
821+
sh.Command(join(self.ctx.ndk_dir, "ndk-build")),
822822
'V=1',
823823
'NDK_DEBUG=' + ("1" if self.ctx.build_as_debuggable else "0"),
824824
'APP_PLATFORM=android-' + str(self.ctx.ndk_api),
@@ -1142,7 +1142,6 @@ 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_sysroot # FIXME?
11461145
if self.ctx.copy_libs:
11471146
env['COPYLIBS'] = '1'
11481147

pythonforandroid/recipes/audiostream/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ 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'] = arch.ndk_platform
28+
# NDKPLATFORM is our switch for detecting Android platform, so can't be None
29+
env['NDKPLATFORM'] = "NOTNONE"
2930
env['LIBLINK'] = 'NOTNONE' # Hacky fix. Needed by audiostream setup.py
3031
return env
3132

0 commit comments

Comments
 (0)