Source code

Revision control

Other Tools

1
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2
# vim: set filetype=python:
3
# This Source Code Form is subject to the terms of the Mozilla Public
4
# License, v. 2.0. If a copy of the MPL was not distributed with this
5
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7
8
@depends(mozbuild_state_path, '--help')
9
@imports('os')
10
@imports(_from='mozboot.android', _import='NDK_VERSION')
11
def default_android_ndk_root(mozbuild_state_path, _):
12
path = os.path.join(mozbuild_state_path, 'android-ndk-%s' % NDK_VERSION)
13
if os.path.isdir(path):
14
return path
15
16
17
js_option('--with-android-ndk', nargs=1,
18
default=default_android_ndk_root,
19
help='location where the Android NDK can be found{|}')
20
21
js_option('--with-android-toolchain', nargs=1,
22
help='location of the Android toolchain')
23
24
option('--with-android-googlevr-sdk', nargs=1,
25
help='location of the Android GoogleVR SDK')
26
27
28
@depends(target)
29
def min_android_version(target):
30
if target.cpu in ['aarch64', 'x86_64']:
31
# 64-bit support was added in API 21.
32
return '21'
33
return '16'
34
35
36
js_option('--with-android-version',
37
nargs=1,
38
help='android platform version{|}',
39
default=min_android_version)
40
41
42
@depends('--with-android-version', min_android_version)
43
@imports(_from='__builtin__', _import='ValueError')
44
def android_version(value, min_version):
45
if not value:
46
# Someone has passed --without-android-version.
47
die('--with-android-version cannot be disabled.')
48
49
try:
50
version = int(value[0])
51
except ValueError:
52
die('--with-android-version expects an integer value')
53
54
if version < int(min_version):
55
die('--with-android-version must be at least %s (got %s)',
56
min_version, value[0])
57
58
return version
59
60
61
add_old_configure_assignment('android_version', android_version)
62
63
64
@depends('--with-android-ndk')
65
@imports(_from='os.path', _import='isdir')
66
def ndk(value):
67
if value:
68
if not isdir(value[0]):
69
die("The path you specified with --with-android-ndk (%s) is not "
70
"a directory" % value[0])
71
return value[0]
72
73
die('You must specify --with-android-ndk=/path/to/ndk when targeting Android, '
74
'or try |mach bootstrap|.')
75
76
77
set_config('ANDROID_NDK', ndk)
78
add_old_configure_assignment('android_ndk', ndk)
79
80
81
@depends(ndk)
82
@checking('for android ndk version')
83
@imports(_from='__builtin__', _import='open')
84
@imports(_from='mozboot.android', _import='NDK_VERSION')
85
def ndk_version(ndk):
86
if not ndk:
87
# Building 'js/src' for non-Android.
88
return
89
with open(os.path.join(ndk, 'source.properties'), 'r') as f:
90
revision = [line for line in f if line.startswith('Pkg.Revision')]
91
if not revision:
92
die('Cannot determine NDK version from source.properties')
93
if len(revision) != 1:
94
die('Too many Pkg.Revision lines in source.properties')
95
96
(_, version) = revision[0].split('=')
97
if not version:
98
die('Unexpected Pkg.Revision line in source.properties')
99
100
(major, minor, revision) = version.strip().split('.')
101
if not major or not minor:
102
die('Unexpected NDK version string: ' + version)
103
104
# source.properties contains a $MAJOR.$MINOR.$PATCH revision number,
105
# but the more common nomenclature that Google uses is alphanumeric
106
# version strings like "r20" or "r19c". Convert the source.properties
107
# notation into an alphanumeric string.
108
int_minor = int(minor)
109
alphas = "abcdefghijklmnop"
110
ascii_minor = alphas[int_minor] if int_minor > 0 else ''
111
human = "r%s%s" % (major, ascii_minor)
112
113
if NDK_VERSION != human:
114
die('The only supported version of the NDK is %s (have %s)\n'
115
'Please run |mach bootstrap| '
116
'to install the correct NDK.' % (NDK_VERSION, human))
117
118
return namespace(
119
major=major,
120
minor=minor,
121
)
122
123
124
set_config('ANDROID_NDK_MAJOR_VERSION', ndk_version.major)
125
set_config('ANDROID_NDK_MINOR_VERSION', ndk_version.minor)
126
127
128
@depends(target, android_version, ndk)
129
@checking('for android platform directory')
130
@imports(_from='os.path', _import='isdir')
131
def android_platform(target, android_version, ndk):
132
if target.os != 'Android':
133
return
134
135
if 'aarch64' == target.cpu:
136
target_dir_name = 'arm64'
137
else:
138
target_dir_name = target.cpu
139
140
# Not all Android releases have their own platform release. We use
141
# the next lower platform version in these cases.
142
if android_version in (11, 10):
143
platform_version = 9
144
elif android_version in (20, 22):
145
platform_version = android_version - 1
146
else:
147
platform_version = android_version
148
149
platform_dir = os.path.join(ndk,
150
'platforms',
151
'android-%s' % platform_version,
152
'arch-%s' % target_dir_name)
153
154
if not isdir(platform_dir):
155
die("Android platform directory not found. With the current "
156
"configuration, it should be in %s" % platform_dir)
157
158
return platform_dir
159
160
161
add_old_configure_assignment('android_platform', android_platform)
162
set_config('ANDROID_PLATFORM', android_platform)
163
164
165
@depends(android_platform, ndk, target)
166
@checking('for android sysroot directory')
167
@imports(_from='os.path', _import='isdir')
168
def android_sysroot(android_platform, ndk, target):
169
if target.os != 'Android':
170
return
171
172
# NDK r15 has both unified and non-unified headers, but we only support
173
# non-unified for that NDK, so look for that first.
174
search_dirs = [
175
# (<if this directory exists>, <return this directory>)
176
(os.path.join(android_platform, 'usr', 'include'), android_platform),
177
(os.path.join(ndk, 'sysroot'), os.path.join(ndk, 'sysroot')),
178
]
179
180
for test_dir, sysroot_dir in search_dirs:
181
if isdir(test_dir):
182
return sysroot_dir
183
184
die("Android sysroot directory not found in %s." %
185
str([sysroot_dir for test_dir, sysroot_dir in search_dirs]))
186
187
188
add_old_configure_assignment('android_sysroot', android_sysroot)
189
190
191
@depends(android_platform, ndk, target)
192
@checking('for android system directory')
193
@imports(_from='os.path', _import='isdir')
194
def android_system(android_platform, ndk, target):
195
if target.os != 'Android':
196
return
197
198
# NDK r15 has both unified and non-unified headers, but we only support
199
# non-unified for that NDK, so look for that first.
200
search_dirs = [
201
os.path.join(android_platform, 'usr', 'include'),
202
os.path.join(ndk, 'sysroot', 'usr', 'include', target.toolchain),
203
]
204
205
for system_dir in search_dirs:
206
if isdir(system_dir):
207
return system_dir
208
209
die("Android system directory not found in %s." % str(search_dirs))
210
211
212
add_old_configure_assignment('android_system', android_system)
213
214
215
@depends(target, host, ndk, '--with-android-toolchain')
216
@checking('for the Android toolchain directory', lambda x: x or 'not found')
217
@imports(_from='os.path', _import='isdir')
218
@imports(_from='mozbuild.shellutil', _import='quote')
219
def android_toolchain(target, host, ndk, toolchain):
220
if not ndk:
221
return
222
if toolchain:
223
return toolchain[0]
224
else:
225
if target.cpu == 'arm' and target.endianness == 'little':
226
target_base = 'arm-linux-androideabi'
227
elif target.cpu == 'x86':
228
target_base = 'x86'
229
elif target.cpu == 'x86_64':
230
target_base = 'x86_64'
231
elif target.cpu == 'aarch64' and target.endianness == 'little':
232
target_base = 'aarch64-linux-android'
233
else:
234
die('Target cpu is not supported.')
235
236
toolchain_format = '%s/toolchains/%s-4.9/prebuilt/%s-%s'
237
host_kernel = 'windows' if host.kernel == 'WINNT' else host.kernel.lower()
238
239
toolchain = toolchain_format % (ndk, target_base,
240
host_kernel, host.cpu)
241
log.debug('Trying %s' % quote(toolchain))
242
if not isdir(toolchain) and host.cpu == 'x86_64':
243
toolchain = toolchain_format % (ndk, target_base,
244
host_kernel, 'x86')
245
log.debug('Trying %s' % quote(toolchain))
246
if isdir(toolchain):
247
return toolchain
248
die('You have to specify --with-android-toolchain='
249
'/path/to/ndk/toolchain.')
250
251
252
set_config('ANDROID_TOOLCHAIN', android_toolchain)
253
254
255
@depends(target)
256
def android_toolchain_prefix_base(target):
257
if target.cpu == 'x86':
258
# Ideally, the --target should just have the right x86 variant
259
# in the first place.
260
return 'i686-linux-android'
261
return target.toolchain
262
263
264
js_option(env='STLPORT_CPPFLAGS',
265
nargs=1,
266
help='Options compiler should pass for standard C++ library')
267
268
269
@depends('STLPORT_CPPFLAGS', ndk)
270
@imports(_from='os.path', _import='isdir')
271
def stlport_cppflags(value, ndk):
272
if value and len(value):
273
return value.split()
274
if not ndk:
275
return
276
277
ndk_base = os.path.join(ndk, 'sources', 'cxx-stl')
278
cxx_base = os.path.join(ndk_base, 'llvm-libc++')
279
cxx_include = os.path.join(cxx_base, 'libcxx', 'include')
280
cxxabi_base = os.path.join(ndk_base, 'llvm-libc++abi')
281
cxxabi_include = os.path.join(cxxabi_base, 'libcxxabi', 'include')
282
283
if not isdir(cxx_include):
284
# NDK r13 removes the inner "libcxx" directory.
285
cxx_include = os.path.join(cxx_base, 'include')
286
if not isdir(cxx_include):
287
die("Couldn't find path to libc++ includes in the android ndk")
288
289
if not isdir(cxxabi_include):
290
# NDK r13 removes the inner "libcxxabi" directory.
291
cxxabi_include = os.path.join(cxxabi_base, 'include')
292
if not isdir(cxxabi_include):
293
die("Couldn't find path to libc++abi includes in the android ndk")
294
295
# Add android/support/include/ for prototyping long double math
296
# functions, locale-specific C library functions, multibyte support,
297
# etc.
298
return [
299
# You'd think we'd want to use -stdlib=libc++, but this doesn't work
301
# Using -stdlib=libc++ and removing some of the -I below also doesn't
302
# work because not everything that is in cxx_include comes in the C++
303
# header directory that comes with clang.
304
'-stdlib=libstdc++',
305
'-I%s' % cxx_include,
306
'-I%s' % os.path.join(ndk, 'sources', 'android', 'support', 'include'),
307
'-I%s' % cxxabi_include]
308
309
310
add_old_configure_assignment('stlport_cppflags', stlport_cppflags)
311
312
313
@depends(android_system, android_sysroot, android_toolchain, android_version)
314
def extra_toolchain_flags(android_system, android_sysroot, toolchain_dir,
315
android_version):
316
if not android_sysroot:
317
return []
318
flags = ['-isystem',
319
android_system,
320
'-isystem',
321
os.path.join(android_sysroot, 'usr', 'include'),
322
'-gcc-toolchain',
323
toolchain_dir,
324
'-D__ANDROID_API__=%d' % android_version]
325
return flags
326
327
328
@depends(android_toolchain_prefix_base, android_toolchain)
329
def android_toolchain_prefix(prefix_base, toolchain):
330
if toolchain:
331
return '%s/bin/%s-' % (toolchain, prefix_base)
332
333
334
imply_option('--with-toolchain-prefix', android_toolchain_prefix,
335
reason='--with-android-ndk')
336
337
338
@depends(extra_toolchain_flags, stlport_cppflags, android_toolchain,
339
android_toolchain_prefix_base)
340
@imports(_from='os.path', _import='isdir')
341
def bindgen_cflags_android(toolchain_flags, stlport_flags, toolchain,
342
toolchain_prefix):
343
if not toolchain_flags:
344
return
345
346
gcc_include = os.path.join(
347
toolchain, 'lib', 'gcc', toolchain_prefix, '4.9.x')
348
if not isdir(gcc_include):
349
gcc_include = os.path.join(
350
toolchain, 'lib', 'gcc', toolchain_prefix, '4.9')
351
352
return toolchain_flags + stlport_flags + [
353
'-I%s' % os.path.join(gcc_include, 'include'),
354
'-I%s' % os.path.join(gcc_include, 'include-fixed'),
355
]
356
357
358
@depends('--with-android-googlevr-sdk', target)
359
@checking('for GoogleVR SDK', lambda x: x.result)
360
@imports(_from='os.path', _import='exists')
361
@imports(_from='os.path', _import='abspath')
362
def googlevr_sdk(value, target):
363
if not value:
364
return namespace(
365
result='Not specified'
366
)
367
path = abspath(value[0])
368
if not exists(path):
369
die('Could not find GoogleVR SDK %s', path)
370
include = '%s/libraries/headers/' % path
371
if 'arm' == target.cpu:
372
arch = 'armeabi-v7a'
373
elif 'aarch64' == target.cpu:
374
arch = 'arm64-v8a'
375
elif 'x86' == target.cpu:
376
arch = 'x86'
377
else:
378
die('Unsupported GoogleVR cpu architecture %s' % target.cpu)
379
380
libs = '{0}/libraries/jni/{1}/'.format(path, arch)
381
382
if not exists(libs):
383
die('Could not find GoogleVR NDK at %s. Did you try running '
384
'\'./gradlew :extractNdk\' in %s?', libs, path)
385
386
return namespace(
387
result=path,
388
include=include,
389
libs=libs,
390
enabled=True,
391
)
392
393
394
set_define('MOZ_ANDROID_GOOGLE_VR', googlevr_sdk.enabled)
395
set_config('MOZ_ANDROID_GOOGLE_VR', googlevr_sdk.enabled)
396
set_config('MOZ_ANDROID_GOOGLE_VR_INCLUDE', googlevr_sdk.include)
397
set_config('MOZ_ANDROID_GOOGLE_VR_LIBS', googlevr_sdk.libs)