forked from kivy/python-for-android
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathrecommendations.py
More file actions
232 lines (191 loc) · 8.12 KB
/
recommendations.py
File metadata and controls
232 lines (191 loc) · 8.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
"""Simple functions for checking dependency versions."""
import sys
from distutils.version import LooseVersion
from os.path import join
from pythonforandroid.logger import info, warning
from pythonforandroid.util import BuildInterruptingException
# We only check the NDK major version
MIN_NDK_VERSION = 19
MAX_NDK_VERSION = 20
# DO NOT CHANGE LINE FORMAT: buildozer parses the existence of a RECOMMENDED_NDK_VERSION
RECOMMENDED_NDK_VERSION = "19c"
NDK_DOWNLOAD_URL = "https://developer.android.com/ndk/downloads/"
# Important log messages
NEW_NDK_MESSAGE = 'Newer NDKs may not be fully supported by p4a.'
UNKNOWN_NDK_MESSAGE = (
'Could not determine NDK version, no source.properties in the NDK dir.'
)
PARSE_ERROR_NDK_MESSAGE = (
'Could not parse $NDK_DIR/source.properties, not checking NDK version.'
)
READ_ERROR_NDK_MESSAGE = (
'Unable to read the NDK version from the given directory {ndk_dir}.'
)
ENSURE_RIGHT_NDK_MESSAGE = (
'Make sure your NDK version is greater than {min_supported}. If you get '
'build errors, download the recommended NDK {rec_version} from {ndk_url}.'
)
NDK_LOWER_THAN_SUPPORTED_MESSAGE = (
'The minimum supported NDK version is {min_supported}. '
'You can download it from {ndk_url}.'
)
UNSUPPORTED_NDK_API_FOR_ARMEABI_MESSAGE = (
'Asked to build for armeabi architecture with API '
'{req_ndk_api}, but API {max_ndk_api} or greater does not support armeabi.'
)
CURRENT_NDK_VERSION_MESSAGE = (
'Found NDK version {ndk_version}'
)
RECOMMENDED_NDK_VERSION_MESSAGE = (
'Maximum recommended NDK version is {recommended_ndk_version}, but newer versions may work.'
)
def check_ndk_version(ndk_dir):
"""
Check the NDK version against what is currently recommended and raise an
exception of :class:`~pythonforandroid.util.BuildInterruptingException` in
case that the user tries to use an NDK lower than minimum supported,
specified via attribute `MIN_NDK_VERSION`.
.. versionchanged:: 2019.06.06.1.dev0
Added the ability to get android's NDK `letter version` and also
rewrote to raise an exception in case that an NDK version lower than
the minimum supported is detected.
"""
version = read_ndk_version(ndk_dir)
if version is None:
warning(READ_ERROR_NDK_MESSAGE.format(ndk_dir=ndk_dir))
warning(
ENSURE_RIGHT_NDK_MESSAGE.format(
min_supported=MIN_NDK_VERSION,
rec_version=RECOMMENDED_NDK_VERSION,
ndk_url=NDK_DOWNLOAD_URL,
)
)
return
# create a dictionary which will describe the relationship of the android's
# NDK minor version with the `human readable` letter version, egs:
# Pkg.Revision = 17.1.4828580 => ndk-17b
# Pkg.Revision = 17.2.4988734 => ndk-17c
# Pkg.Revision = 19.0.5232133 => ndk-19 (No letter)
minor_to_letter = {0: ''}
minor_to_letter.update(
{n + 1: chr(i) for n, i in enumerate(range(ord('b'), ord('b') + 25))}
)
major_version = version.version[0]
letter_version = minor_to_letter[version.version[1]]
string_version = '{major_version}{letter_version}'.format(
major_version=major_version, letter_version=letter_version
)
info(CURRENT_NDK_VERSION_MESSAGE.format(ndk_version=string_version))
if major_version < MIN_NDK_VERSION:
raise BuildInterruptingException(
NDK_LOWER_THAN_SUPPORTED_MESSAGE.format(
min_supported=MIN_NDK_VERSION, ndk_url=NDK_DOWNLOAD_URL
),
instructions=(
'Please, go to the android NDK page ({ndk_url}) and download a'
' supported version.\n*** The currently recommended NDK'
' version is {rec_version} ***'.format(
ndk_url=NDK_DOWNLOAD_URL,
rec_version=RECOMMENDED_NDK_VERSION,
)
),
)
elif major_version > MAX_NDK_VERSION:
warning(
RECOMMENDED_NDK_VERSION_MESSAGE.format(
recommended_ndk_version=RECOMMENDED_NDK_VERSION
)
)
warning(NEW_NDK_MESSAGE)
def read_ndk_version(ndk_dir):
"""Read the NDK version from the NDK dir, if possible"""
try:
with open(join(ndk_dir, 'source.properties')) as fileh:
ndk_data = fileh.read()
except IOError:
info(UNKNOWN_NDK_MESSAGE)
return
for line in ndk_data.split('\n'):
if line.startswith('Pkg.Revision'):
break
else:
info(PARSE_ERROR_NDK_MESSAGE)
return
# Line should have the form "Pkg.Revision = ..."
ndk_version = LooseVersion(line.split('=')[-1].strip())
return ndk_version
MIN_TARGET_API = 26
# highest version tested to work fine with SDL2
# should be a good default for other bootstraps too
RECOMMENDED_TARGET_API = 27
ARMEABI_MAX_TARGET_API = 21
OLD_API_MESSAGE = (
'Target APIs lower than 26 are no longer supported on Google Play, '
'and are not recommended. Note that the Target API can be higher than '
'your device Android version, and should usually be as high as possible.')
def check_target_api(api, arch):
"""Warn if the user's target API is less than the current minimum
recommendation
"""
if api >= ARMEABI_MAX_TARGET_API and arch == 'armeabi':
raise BuildInterruptingException(
UNSUPPORTED_NDK_API_FOR_ARMEABI_MESSAGE.format(
req_ndk_api=api, max_ndk_api=ARMEABI_MAX_TARGET_API
),
instructions='You probably want to build with --arch=armeabi-v7a instead')
if api < MIN_TARGET_API:
warning('Target API {} < {}'.format(api, MIN_TARGET_API))
warning(OLD_API_MESSAGE)
MIN_NDK_API = 21
RECOMMENDED_NDK_API = 21
OLD_NDK_API_MESSAGE = ('NDK API less than {} is not supported'.format(MIN_NDK_API))
TARGET_NDK_API_GREATER_THAN_TARGET_API_MESSAGE = (
'Target NDK API is {ndk_api}, '
'higher than the target Android API {android_api}.'
)
def check_ndk_api(ndk_api, android_api):
"""Warn if the user's NDK is too high or low."""
if ndk_api > android_api:
raise BuildInterruptingException(
TARGET_NDK_API_GREATER_THAN_TARGET_API_MESSAGE.format(
ndk_api=ndk_api, android_api=android_api
),
instructions=('The NDK API is a minimum supported API number and must be lower '
'than the target Android API'))
if ndk_api < MIN_NDK_API:
warning(OLD_NDK_API_MESSAGE)
MIN_PYTHON_MAJOR_VERSION = 3
MIN_PYTHON_MINOR_VERSION = 6
MIN_PYTHON_VERSION = LooseVersion('{major}.{minor}'.format(major=MIN_PYTHON_MAJOR_VERSION,
minor=MIN_PYTHON_MINOR_VERSION))
PY2_ERROR_TEXT = (
'python-for-android no longer supports running under Python 2. Either upgrade to '
'Python {min_version} or higher (recommended), or revert to python-for-android 2019.07.08.'
).format(min_version=MIN_PYTHON_VERSION)
PY_VERSION_ERROR_TEXT = (
'Your Python version {user_major}.{user_minor} is not supported by python-for-android, '
'please upgrade to {min_version} or higher.'
).format(
user_major=sys.version_info.major,
user_minor=sys.version_info.minor,
min_version=MIN_PYTHON_VERSION)
def check_python_version():
# Python 2 special cased because it's a major transition. In the
# future the major or minor versions can increment more quietly.
if sys.version_info.major == 2:
raise BuildInterruptingException(PY2_ERROR_TEXT)
if (
sys.version_info.major < MIN_PYTHON_MAJOR_VERSION or
sys.version_info.minor < MIN_PYTHON_MINOR_VERSION
):
raise BuildInterruptingException(PY_VERSION_ERROR_TEXT)
def print_recommendations():
"""
Print the main recommended dependency versions as simple key-value pairs.
"""
print('Min supported NDK version: {}'.format(MIN_NDK_VERSION))
print('Recommended NDK version: {}'.format(RECOMMENDED_NDK_VERSION))
print('Min target API: {}'.format(MIN_TARGET_API))
print('Recommended target API: {}'.format(RECOMMENDED_TARGET_API))
print('Min NDK API: {}'.format(MIN_NDK_API))
print('Recommended NDK API: {}'.format(RECOMMENDED_NDK_API))