update gyp_crashpad_android.py

This patch updates gyp_crashpad_android.py to function with NDK r20,
removes the requirement to generate a standalone toolchain, and updates
documentation on building for Android.

Also some gyp build fixes.

Change-Id: Ide338417ab2a21eca7a4bf42c1fb834e5639c186
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/1798746
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
Joshua Peraza 2019-09-11 11:30:22 -07:00 committed by Commit Bot
parent 06fdbdecdc
commit e97cf7b29c
5 changed files with 44 additions and 107 deletions

View File

@ -28,82 +28,45 @@ def main(args):
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Set up an Android cross build', description='Set up an Android cross build',
epilog='Additional arguments will be passed to gyp_crashpad.py.') epilog='Additional arguments will be passed to gyp_crashpad.py.')
parser.add_argument('--arch', required=True, help='Target architecture')
parser.add_argument('--api-level', required=True, help='Target API level')
parser.add_argument('--ndk', required=True, help='Standalone NDK toolchain') parser.add_argument('--ndk', required=True, help='Standalone NDK toolchain')
parser.add_argument('--compiler',
default='clang',
choices=('clang', 'gcc'),
help='The compiler to use, clang by default')
(parsed, extra_command_line_args) = parser.parse_known_args(args) (parsed, extra_command_line_args) = parser.parse_known_args(args)
NDK_ERROR=( ndk_bin_dir = os.path.join(parsed.ndk,
'NDK must be a valid standalone NDK toolchain.\n' + 'toolchains',
'See https://developer.android.com/ndk/guides/standalone_toolchain.html') 'llvm',
arch_dirs = glob.glob(os.path.join(parsed.ndk, '*-linux-android*')) 'prebuilt',
if len(arch_dirs) != 1: 'linux-x86_64',
parser.error(NDK_ERROR) 'bin')
if not os.path.exists(ndk_bin_dir):
parser.error("missing toolchain")
arch_triplet = os.path.basename(arch_dirs[0]) ARCH_TO_ARCH_TRIPLET = {
ARCH_TRIPLET_TO_ARCH = { 'arm': 'armv7a-linux-androideabi',
'arm-linux-androideabi': 'arm', 'arm64': 'aarch64-linux-android',
'aarch64-linux-android': 'arm64', 'ia32': 'i686-linux-android',
'i686-linux-android': 'ia32', 'x64': 'x86_64-linux-android',
'x86_64-linux-android': 'x64',
'mipsel-linux-android': 'mips',
'mips64el-linux-android': 'mips64',
} }
if arch_triplet not in ARCH_TRIPLET_TO_ARCH:
parser.error(NDK_ERROR)
arch = ARCH_TRIPLET_TO_ARCH[arch_triplet]
ndk_bin_dir = os.path.join(parsed.ndk, 'bin') clang_prefix = ARCH_TO_ARCH_TRIPLET[parsed.arch] + parsed.api_level
os.environ['CC_target'] = os.path.join(ndk_bin_dir, clang_prefix + '-clang')
os.environ['CXX_target'] = os.path.join(ndk_bin_dir, clang_prefix + '-clang++')
clang_path = os.path.join(ndk_bin_dir, 'clang') extra_args = ['-D', 'android_api_level=' + parsed.api_level]
extra_args = []
if parsed.compiler == 'clang': # ARM only includes 'v7a' in the tool prefix for clang
os.environ['CC_target'] = clang_path tool_prefix = ('arm-linux-androideabi' if parsed.arch == 'arm'
os.environ['CXX_target'] = os.path.join(ndk_bin_dir, 'clang++') else ARCH_TO_ARCH_TRIPLET[parsed.arch])
elif parsed.compiler == 'gcc':
os.environ['CC_target'] = os.path.join(ndk_bin_dir,
'%s-gcc' % arch_triplet)
os.environ['CXX_target'] = os.path.join(ndk_bin_dir,
'%s-g++' % arch_triplet)
# Unlike the Clang build, when using GCC with unified headers, __ANDROID_API__
# isnt set automatically and must be pushed in to the build. Fish the correct
# value out of the Clang wrapper script. If deprecated headers are in use, the
# Clang wrapper wont mention __ANDROID_API__, but the standalone toolchains
# <android/api-level.h> will #define it for both Clang and GCC.
#
# android_api_level is extracted in this manner even when compiling with Clang
# so that its available for use in GYP conditions that need to test the API
# level, but beware that itll only be available when unified headers are in
# use.
#
# Unified headers are the way of the future, according to
# https://android.googlesource.com/platform/ndk/+/ndk-r14/CHANGELOG.md and
# https://android.googlesource.com/platform/ndk/+/master/docs/UnifiedHeaders.md.
# Traditional (deprecated) headers have been removed entirely as of NDK r16.
# https://android.googlesource.com/platform/ndk/+/ndk-release-r16/CHANGELOG.md.
with open(clang_path, 'r') as file:
clang_script_contents = file.read()
matches = re.finditer(r'\s-D__ANDROID_API__=([\d]+)\s',
clang_script_contents)
match = next(matches, None)
if match:
android_api = int(match.group(1))
extra_args.extend(['-D', 'android_api_level=%d' % android_api])
if next(matches, None):
raise AssertionError('__ANDROID_API__ defined too many times')
for tool in ('ar', 'nm', 'readelf'): for tool in ('ar', 'nm', 'readelf'):
os.environ['%s_target' % tool.upper()] = ( os.environ['%s_target' % tool.upper()] = (
os.path.join(ndk_bin_dir, '%s-%s' % (arch_triplet, tool))) os.path.join(ndk_bin_dir, '%s-%s' % (tool_prefix, tool)))
return gyp_crashpad.main( return gyp_crashpad.main(
['-D', 'OS=android', ['-D', 'OS=android',
'-D', 'target_arch=%s' % arch, '-D', 'target_arch=%s' % parsed.arch,
'-D', 'clang=%d' % (1 if parsed.compiler == 'clang' else 0), '-D', 'clang=1',
'-f', 'ninja-android'] + '-f', 'ninja-android'] +
extra_args + extra_args +
extra_command_line_args) extra_command_line_args)

View File

@ -135,66 +135,38 @@ target_sysroot = "//third_party/linux/sysroot"
### Android ### Android
Crashpads Android port is in its early stages. This build relies on This build relies on cross-compilation. Its possible to develop Crashpad for
cross-compilation. Its possible to develop Crashpad for Android on any platform Android on any platform that the [Android NDK (Native Development Kit)]
that the [Android NDK (Native Development (https://developer.android.com/ndk/) runs on.
Kit)](https://developer.android.com/ndk/) runs on.
If its not already present on your system, [download the NDK package for your If its not already present on your system, [download the NDK package for your
system](https://developer.android.com/ndk/downloads/) and expand it to a system](https://developer.android.com/ndk/downloads/) and expand it to a
suitable location. These instructions assume that its been expanded to suitable location. These instructions assume that its been expanded to
`~/android-ndk-r16`. `~/android-ndk-r20`.
To build Crashpad, portions of the NDK must be reassembled into a [standalone
toolchain](https://developer.android.com/ndk/guides/standalone_toolchain.html).
This is a repackaged subset of the NDK suitable for cross-compiling for a single
Android architecture (such as `arm`, `arm64`, `x86`, and `x86_64`) targeting a
specific [Android API
level](https://source.android.com/source/build-numbers.html). The standalone
toolchain only needs to be built from the NDK one time for each set of options
desired. To build a standalone toolchain targeting 64-bit ARM and API level 21
(Android 5.0 “Lollipop”), run:
```
$ cd ~
$ python android-ndk-r16/build/tools/make_standalone_toolchain.py \
--arch=arm64 --api=21 --install-dir=android-ndk-r16_arm64_api21
```
Note that Chrome uses Android API level 21 for 64-bit platforms and 16 for Note that Chrome uses Android API level 21 for 64-bit platforms and 16 for
32-bit platforms. See Chromes 32-bit platforms. See Chromes
[`build/config/android/config.gni`](https://chromium.googlesource.com/chromium/src/+/master/build/config/android/config.gni) [`build/config/android/config.gni`](https://chromium.googlesource.com/chromium/src/+/master/build/config/android/config.gni)
which sets `_android_api_level` and `_android64_api_level`. which sets `_android_api_level` and `_android64_api_level`.
To configure a Crashpad build for Android using the standalone toolchain To configure a Crashpad build for Android use `gyp_crashpad_android.py`. This
assembled above, use `gyp_crashpad_android.py`. This script is a wrapper for script is a wrapper for `gyp_crashpad.py` that sets several environment
`gyp_crashpad.py` that sets several environment variables directing the build to variables directing the build to the toolchain, and several GYP options to
the standalone toolchain, and several GYP options to identify an Android build. identify an Android build. This must be done after any `gclient sync`, or
This must be done after any `gclient sync`, or instead of any `gclient runhooks` instead of any `gclient runhooks` operation.
operation.
``` ```
$ cd ~/crashpad/crashpad $ cd ~/crashpad/crashpad
$ python build/gyp_crashpad_android.py \ python build/gyp_crashpad_android.py \
--ndk ~/android-ndk-r16_arm64_api21 \ --ndk ~/usr/lib/android-ndk-r20 --arch arm64 --api-level 21 \
--generator-output out/android_arm64_api21 --generator-output=out/android_arm64_api21 \
``` ```
`gyp_crashpad_android.py` detects the build type based on the characteristics of To build, direct `ninja` to the specific `out` directory chosen by the
the standalone toolchain given in its `--ndk` argument.
`gyp_crashpad_android.py` sets the build up to use Clang by default. Its also
possible to use GCC by providing the `--compiler=gcc` argument to
`gyp_crashpad_android.py`.
The Android port is incomplete, but targets known to be working include
`crashpad_test`, `crashpad_util`, and their tests. This list will grow over
time. To build, direct `ninja` to the specific `out` directory chosen by the
`--generator-output` argument to `gyp_crashpad_android.py`. `--generator-output` argument to `gyp_crashpad_android.py`.
``` ```
$ ninja -C out/android_arm64_api21/out/Debug \ $ ninja -C out/android_arm64_api21/out/Debug all
crashpad_test_test crashpad_util_test
``` ```
## Testing ## Testing

View File

@ -39,6 +39,8 @@
'crash_report_upload_thread.h', 'crash_report_upload_thread.h',
'handler_main.cc', 'handler_main.cc',
'handler_main.h', 'handler_main.h',
'linux/capture_snapshot.cc',
'linux/capture_snapshot.h',
'linux/crash_report_exception_handler.cc', 'linux/crash_report_exception_handler.cc',
'linux/crash_report_exception_handler.h', 'linux/crash_report_exception_handler.h',
'linux/exception_handler_server.cc', 'linux/exception_handler_server.cc',

View File

@ -395,8 +395,8 @@
['OS=="linux" or OS=="android"', { ['OS=="linux" or OS=="android"', {
'sources': [ 'sources': [
'net/http_transport_socket.cc', 'net/http_transport_socket.cc',
'util/process_memory_sanitized.cc', 'process/process_memory_sanitized.cc',
'util/process_memory_sanitized.h', 'process/process_memory_sanitized.h',
], ],
}, { # else: OS!="linux" }, { # else: OS!="linux"
'sources!': [ 'sources!': [

View File

@ -156,7 +156,7 @@
}], }],
['OS=="linux" or OS=="android"', { ['OS=="linux" or OS=="android"', {
'sources': [ 'sources': [
'util/process_memory_sanitized_test.cc', 'process/process_memory_sanitized_test.cc',
], ],
}], }],
['OS!="linux" and OS!="android"', { ['OS!="linux" and OS!="android"', {