mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-06 12:43:53 +00:00
b3c3de5de5
NDK headers are grouped into a "sysroot" directory, which doesn't contain architecture-specific bits, and a "system" directory, which contains only the architecture-specific bits. Previously, both directories are the same, under platforms/android-*/arch-*/. However, with unified headers in NDK r16, the two are different, so we need to support that in the Android build scripts. Unified headers also rely on the build system defining the __ANDROID_API__ macro, so we add support for that as well. MozReview-Commit-ID: 9zBNQC3BRFl --HG-- extra : rebase_source : 9ded282343df64d9cc4abcf7d7c6b03ac3423ff0
403 lines
13 KiB
Python
403 lines
13 KiB
Python
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
|
# vim: set filetype=python:
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
js_option('--with-android-ndk', nargs=1,
|
|
help='location where the Android NDK can be found')
|
|
|
|
js_option('--with-android-toolchain', nargs=1,
|
|
help='location of the Android toolchain')
|
|
|
|
option('--with-android-googlevr-sdk', nargs=1,
|
|
help='location of the Android GoogleVR SDK')
|
|
|
|
|
|
@depends(target)
|
|
def min_android_version(target):
|
|
if target.cpu in ['aarch64', 'x86_64', 'mips64']:
|
|
# 64-bit support was added in API 21.
|
|
return '21'
|
|
return '9'
|
|
|
|
|
|
js_option('--with-android-version',
|
|
nargs=1,
|
|
help='android platform version',
|
|
default=min_android_version)
|
|
|
|
|
|
@depends('--with-android-version', min_android_version, '--help')
|
|
@imports(_from='__builtin__', _import='ValueError')
|
|
def android_version(value, min_version, _):
|
|
if not value:
|
|
# Someone has passed --without-android-version.
|
|
die('--with-android-version cannot be disabled.')
|
|
|
|
try:
|
|
version = int(value[0])
|
|
except ValueError:
|
|
die('--with-android-version expects an integer value')
|
|
|
|
if version < int(min_version):
|
|
die('--with-android-version must be at least %s (got %s)',
|
|
min_version, value[0])
|
|
|
|
return version
|
|
|
|
|
|
add_old_configure_assignment('android_version', android_version)
|
|
|
|
|
|
@depends('--with-android-ndk', build_project, '--help')
|
|
def ndk(value, build_project, help):
|
|
if help:
|
|
return
|
|
if build_project == 'mobile/android' and not value:
|
|
die('You must specify --with-android-ndk=/path/to/ndk when '
|
|
'building mobile/android')
|
|
if value:
|
|
return value[0]
|
|
|
|
|
|
set_config('ANDROID_NDK', ndk)
|
|
add_old_configure_assignment('android_ndk', ndk)
|
|
|
|
|
|
@depends(ndk)
|
|
@checking('for android ndk version')
|
|
@imports(_from='__builtin__', _import='open')
|
|
def ndk_version(ndk):
|
|
if not ndk:
|
|
# Building 'js/src' for non-Android.
|
|
return
|
|
with open(os.path.join(ndk, 'source.properties'), 'r') as f:
|
|
for line in f:
|
|
if not line.startswith('Pkg.Revision'):
|
|
continue
|
|
(_, version) = line.split('=')
|
|
if version:
|
|
return version.strip()
|
|
die('Unexpected Pkg.Revision line in source.properties')
|
|
die('Cannot determine NDK version from source.properties')
|
|
|
|
|
|
@depends(ndk_version)
|
|
def ndk_major_version(ndk_version):
|
|
if not ndk_version:
|
|
# Building 'js/src' for non-Android.
|
|
return
|
|
(major, minor, revision) = ndk_version.split('.')
|
|
if major:
|
|
return major
|
|
die('Unexpected NDK version string: ' + ndk_version)
|
|
|
|
|
|
set_config('ANDROID_NDK_MAJOR_VERSION', ndk_major_version)
|
|
|
|
|
|
@depends(ndk_version)
|
|
def ndk_minor_version(ndk_version):
|
|
if not ndk_version:
|
|
# Building 'js/src' for non-Android.
|
|
return
|
|
(major, minor, revision) = ndk_version.split('.')
|
|
if minor:
|
|
return minor
|
|
die('Unexpected NDK version string: ' + ndk_version)
|
|
|
|
|
|
set_config('ANDROID_NDK_MINOR_VERSION', ndk_minor_version)
|
|
|
|
|
|
@depends(target, android_version, ndk, '--help')
|
|
@checking('for android platform directory')
|
|
@imports(_from='os.path', _import='isdir')
|
|
def android_platform(target, android_version, ndk, _):
|
|
if target.os != 'Android':
|
|
return
|
|
|
|
if 'mips' in target.cpu:
|
|
target_dir_name = 'mips'
|
|
elif 'aarch64' == target.cpu:
|
|
target_dir_name = 'arm64'
|
|
else:
|
|
target_dir_name = target.cpu
|
|
|
|
# Not all Android releases have their own platform release. We use
|
|
# the next lower platform version in these cases.
|
|
if android_version in (11, 10):
|
|
platform_version = 9
|
|
elif android_version in (20, 22):
|
|
platform_version = android_version - 1
|
|
else:
|
|
platform_version = android_version
|
|
|
|
platform_dir = os.path.join(ndk,
|
|
'platforms',
|
|
'android-%s' % platform_version,
|
|
'arch-%s' % target_dir_name)
|
|
|
|
if not isdir(platform_dir):
|
|
die("Android platform directory not found. With the current "
|
|
"configuration, it should be in %s" % platform_dir)
|
|
|
|
return platform_dir
|
|
|
|
|
|
add_old_configure_assignment('android_platform', android_platform)
|
|
|
|
|
|
@depends(android_platform, ndk, target, '--help')
|
|
@checking('for android sysroot directory')
|
|
@imports(_from='os.path', _import='isdir')
|
|
def android_sysroot(android_platform, ndk, target, _):
|
|
if target.os != 'Android':
|
|
return
|
|
|
|
# NDK r15 has both unified and non-unified headers, but we only support
|
|
# non-unified for that NDK, so look for that first.
|
|
search_dirs = [
|
|
# (<if this directory exists>, <return this directory>)
|
|
(os.path.join(android_platform, 'usr', 'include'), android_platform),
|
|
(os.path.join(ndk, 'sysroot'), os.path.join(ndk, 'sysroot')),
|
|
]
|
|
|
|
for test_dir, sysroot_dir in search_dirs:
|
|
if isdir(test_dir):
|
|
return sysroot_dir
|
|
|
|
die("Android sysroot directory not found in %s." %
|
|
str([sysroot_dir for test_dir, sysroot_dir in search_dirs]))
|
|
|
|
|
|
add_old_configure_assignment('android_sysroot', android_sysroot)
|
|
|
|
|
|
@depends(android_platform, ndk, target, '--help')
|
|
@checking('for android system directory')
|
|
@imports(_from='os.path', _import='isdir')
|
|
def android_system(android_platform, ndk, target, _):
|
|
if target.os != 'Android':
|
|
return
|
|
|
|
# NDK r15 has both unified and non-unified headers, but we only support
|
|
# non-unified for that NDK, so look for that first.
|
|
search_dirs = [
|
|
os.path.join(android_platform, 'usr', 'include'),
|
|
os.path.join(ndk, 'sysroot', 'usr', 'include', target.toolchain),
|
|
]
|
|
|
|
for system_dir in search_dirs:
|
|
if isdir(system_dir):
|
|
return system_dir
|
|
|
|
die("Android system directory not found in %s." % str(search_dirs))
|
|
|
|
|
|
add_old_configure_assignment('android_system', android_system)
|
|
|
|
|
|
@depends(target, host, ndk, '--with-android-toolchain', '--help')
|
|
@checking('for the Android toolchain directory', lambda x: x or 'not found')
|
|
@imports(_from='os.path', _import='isdir')
|
|
@imports(_from='mozbuild.shellutil', _import='quote')
|
|
def android_toolchain(target, host, ndk, toolchain, _):
|
|
if not ndk:
|
|
return
|
|
if toolchain:
|
|
return toolchain[0]
|
|
else:
|
|
if target.cpu == 'arm' and target.endianness == 'little':
|
|
target_base = 'arm-linux-androideabi'
|
|
elif target.cpu == 'x86':
|
|
target_base = 'x86'
|
|
elif target.cpu == 'mips32' and target.endianness == 'little':
|
|
target_base = 'mipsel-linux-android'
|
|
elif target.cpu == 'aarch64' and target.endianness == 'little':
|
|
target_base = 'aarch64-linux-android'
|
|
else:
|
|
die('Target cpu is not supported.')
|
|
|
|
toolchain_format = '%s/toolchains/%s-4.9/prebuilt/%s-%s'
|
|
|
|
toolchain = toolchain_format % (ndk, target_base,
|
|
host.kernel.lower(), host.cpu)
|
|
log.debug('Trying %s' % quote(toolchain))
|
|
if not isdir(toolchain) and host.cpu == 'x86_64':
|
|
toolchain = toolchain_format % (ndk, target_base, version,
|
|
host.kernel.lower(), 'x86')
|
|
log.debug('Trying %s' % quote(toolchain))
|
|
if isdir(toolchain):
|
|
return toolchain
|
|
die('You have to specify --with-android-toolchain='
|
|
'/path/to/ndk/toolchain.')
|
|
|
|
|
|
set_config('ANDROID_TOOLCHAIN', android_toolchain)
|
|
|
|
|
|
@depends(target)
|
|
def android_toolchain_prefix_base(target):
|
|
if target.cpu == 'x86':
|
|
# Ideally, the --target should just have the right x86 variant
|
|
# in the first place.
|
|
return 'i686-linux-android'
|
|
return target.toolchain
|
|
|
|
|
|
option(env='STLPORT_CPPFLAGS',
|
|
nargs=1,
|
|
help='Options compiler should pass for standard C++ library')
|
|
|
|
|
|
@depends('STLPORT_CPPFLAGS', ndk, '--help')
|
|
@imports(_from='os.path', _import='isdir')
|
|
def stlport_cppflags(value, ndk, _):
|
|
if value and len(value):
|
|
return value.split()
|
|
if not ndk:
|
|
return
|
|
|
|
ndk_base = os.path.join(ndk, 'sources', 'cxx-stl')
|
|
cxx_base = os.path.join(ndk_base, 'llvm-libc++')
|
|
cxx_include = os.path.join(cxx_base, 'libcxx', 'include')
|
|
cxxabi_base = os.path.join(ndk_base, 'llvm-libc++abi')
|
|
cxxabi_include = os.path.join(cxxabi_base, 'libcxxabi', 'include')
|
|
|
|
if not isdir(cxx_include):
|
|
# NDK r13 removes the inner "libcxx" directory.
|
|
cxx_include = os.path.join(cxx_base, 'include')
|
|
if not isdir(cxx_include):
|
|
die("Couldn't find path to libc++ includes in the android ndk")
|
|
|
|
if not isdir(cxxabi_include):
|
|
# NDK r13 removes the inner "libcxxabi" directory.
|
|
cxxabi_include = os.path.join(cxxabi_base, 'include')
|
|
if not isdir(cxxabi_include):
|
|
die("Couldn't find path to libc++abi includes in the android ndk")
|
|
|
|
# Add android/support/include/ for prototyping long double math
|
|
# functions, locale-specific C library functions, multibyte support,
|
|
# etc.
|
|
return [
|
|
'-I%s' % cxx_include,
|
|
'-I%s' % os.path.join(ndk, 'sources', 'android', 'support', 'include'),
|
|
'-I%s' % cxxabi_include]
|
|
|
|
|
|
add_old_configure_assignment('stlport_cppflags', stlport_cppflags)
|
|
|
|
|
|
@depends(android_system, android_sysroot, android_toolchain, android_version,
|
|
stlport_cppflags)
|
|
def extra_toolchain_flags(android_system, android_sysroot, toolchain_dir,
|
|
android_version, stlport_cppflags):
|
|
if not android_sysroot:
|
|
return []
|
|
flags = ['-isystem',
|
|
android_system,
|
|
'-isystem',
|
|
os.path.join(android_sysroot, 'usr', 'include'),
|
|
'-gcc-toolchain',
|
|
toolchain_dir,
|
|
'-D__ANDROID_API__=%d' % android_version]
|
|
flags.extend(stlport_cppflags if stlport_cppflags else [])
|
|
return flags
|
|
|
|
|
|
@depends(android_toolchain_prefix_base, android_toolchain)
|
|
def android_toolchain_prefix(prefix_base, toolchain):
|
|
if toolchain:
|
|
return '%s/bin/%s-' % (toolchain, prefix_base)
|
|
|
|
|
|
imply_option('--with-toolchain-prefix', android_toolchain_prefix,
|
|
reason='--with-android-ndk')
|
|
|
|
|
|
@depends(extra_toolchain_flags, android_toolchain,
|
|
android_toolchain_prefix_base, '--help')
|
|
@imports(_from='os.path', _import='isdir')
|
|
def bindgen_cflags_defaults(toolchain_flags, toolchain, toolchain_prefix, _):
|
|
if not toolchain_flags:
|
|
return
|
|
|
|
gcc_include = os.path.join(
|
|
toolchain, 'lib', 'gcc', toolchain_prefix, '4.9.x')
|
|
if not isdir(gcc_include):
|
|
gcc_include = os.path.join(
|
|
toolchain, 'lib', 'gcc', toolchain_prefix, '4.9')
|
|
|
|
cflags_format = "%s -I%s -I%s"
|
|
return cflags_format % (' '.join(toolchain_flags),
|
|
os.path.join(gcc_include, 'include'),
|
|
os.path.join(gcc_include, 'include-fixed'))
|
|
|
|
|
|
@depends(host, ndk)
|
|
@imports(_from='os.path', _import='exists')
|
|
@imports(_from='os.path', _import='isdir')
|
|
def android_clang_compiler(host, ndk):
|
|
if not ndk:
|
|
return
|
|
|
|
llvm_path = '%s/toolchains/llvm/prebuilt/%s-%s/bin' % (ndk,
|
|
host.kernel.lower(),
|
|
host.cpu)
|
|
if not isdir(llvm_path) and host.cpu == 'x86_64':
|
|
llvm_path = toolchain_format % (ndk, host.kernel.lower(), 'x86')
|
|
|
|
if not isdir(llvm_path):
|
|
die("Couldn't find path to LLVM toolchain at %s" % llvm_path)
|
|
|
|
clang = '%s/clang' % llvm_path
|
|
if not exists(clang):
|
|
die("Couln't find clang in LLVM toolchain at %s" % clang)
|
|
|
|
return clang
|
|
|
|
|
|
@depends('--with-android-googlevr-sdk', target)
|
|
@checking('for GoogleVR SDK', lambda x: x.result)
|
|
@imports(_from='os.path', _import='exists')
|
|
@imports(_from='os.path', _import='abspath')
|
|
def googlevr_sdk(value, target):
|
|
if not value:
|
|
return namespace(
|
|
result='Not specified'
|
|
)
|
|
path = abspath(value[0])
|
|
if not exists(path):
|
|
die('Could not find GoogleVR SDK %s', path)
|
|
include = '%s/libraries/headers/' % path
|
|
if 'arm' == target.cpu:
|
|
arch = 'armeabi-v7a'
|
|
elif 'aarch64' == target.cpu:
|
|
arch = 'arm64-v8a'
|
|
elif 'x86' == target.cpu:
|
|
arch = 'x86'
|
|
else:
|
|
die('Unsupported GoogleVR cpu architecture %s' % target.cpu)
|
|
|
|
libs = '{0}/libraries/jni/{1}/'.format(path, arch)
|
|
|
|
if not exists(libs):
|
|
die('Could not find GoogleVR NDK at %s. Did you try running '
|
|
'\'./gradlew :extractNdk\' in %s?', libs, path)
|
|
|
|
return namespace(
|
|
result=path,
|
|
include=include,
|
|
libs=libs,
|
|
enabled=True,
|
|
)
|
|
|
|
|
|
set_define('MOZ_ANDROID_GOOGLE_VR', googlevr_sdk.enabled)
|
|
set_config('MOZ_ANDROID_GOOGLE_VR', googlevr_sdk.enabled)
|
|
set_config('MOZ_ANDROID_GOOGLE_VR_INCLUDE', googlevr_sdk.include)
|
|
set_config('MOZ_ANDROID_GOOGLE_VR_LIBS', googlevr_sdk.libs)
|