diff --git a/build/gyp_crashpad_android.py b/build/gyp_crashpad_android.py index f78c05b9..e17e7a26 100755 --- a/build/gyp_crashpad_android.py +++ b/build/gyp_crashpad_android.py @@ -28,82 +28,45 @@ def main(args): parser = argparse.ArgumentParser( description='Set up an Android cross build', 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('--compiler', - default='clang', - choices=('clang', 'gcc'), - help='The compiler to use, clang by default') (parsed, extra_command_line_args) = parser.parse_known_args(args) - NDK_ERROR=( - 'NDK must be a valid standalone NDK toolchain.\n' + - 'See https://developer.android.com/ndk/guides/standalone_toolchain.html') - arch_dirs = glob.glob(os.path.join(parsed.ndk, '*-linux-android*')) - if len(arch_dirs) != 1: - parser.error(NDK_ERROR) + ndk_bin_dir = os.path.join(parsed.ndk, + 'toolchains', + 'llvm', + 'prebuilt', + 'linux-x86_64', + 'bin') + if not os.path.exists(ndk_bin_dir): + parser.error("missing toolchain") - arch_triplet = os.path.basename(arch_dirs[0]) - ARCH_TRIPLET_TO_ARCH = { - 'arm-linux-androideabi': 'arm', - 'aarch64-linux-android': 'arm64', - 'i686-linux-android': 'ia32', - 'x86_64-linux-android': 'x64', - 'mipsel-linux-android': 'mips', - 'mips64el-linux-android': 'mips64', + ARCH_TO_ARCH_TRIPLET = { + 'arm': 'armv7a-linux-androideabi', + 'arm64': 'aarch64-linux-android', + 'ia32': 'i686-linux-android', + 'x64': 'x86_64-linux-android', } - 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 = [] + extra_args = ['-D', 'android_api_level=' + parsed.api_level] - if parsed.compiler == 'clang': - os.environ['CC_target'] = clang_path - os.environ['CXX_target'] = os.path.join(ndk_bin_dir, 'clang++') - 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__ - # isn’t 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 won’t mention __ANDROID_API__, but the standalone toolchain’s - # will #define it for both Clang and GCC. - # - # android_api_level is extracted in this manner even when compiling with Clang - # so that it’s available for use in GYP conditions that need to test the API - # level, but beware that it’ll 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') + # ARM only includes 'v7a' in the tool prefix for clang + tool_prefix = ('arm-linux-androideabi' if parsed.arch == 'arm' + else ARCH_TO_ARCH_TRIPLET[parsed.arch]) for tool in ('ar', 'nm', 'readelf'): 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( ['-D', 'OS=android', - '-D', 'target_arch=%s' % arch, - '-D', 'clang=%d' % (1 if parsed.compiler == 'clang' else 0), + '-D', 'target_arch=%s' % parsed.arch, + '-D', 'clang=1', '-f', 'ninja-android'] + extra_args + extra_command_line_args) diff --git a/doc/developing.md b/doc/developing.md index f4a95e13..406a234f 100644 --- a/doc/developing.md +++ b/doc/developing.md @@ -135,66 +135,38 @@ target_sysroot = "//third_party/linux/sysroot" ### Android -Crashpad’s Android port is in its early stages. This build relies on -cross-compilation. It’s possible to develop Crashpad for Android on any platform -that the [Android NDK (Native Development -Kit)](https://developer.android.com/ndk/) runs on. +This build relies on cross-compilation. It’s possible to develop Crashpad for +Android on any platform that the [Android NDK (Native Development Kit)] +(https://developer.android.com/ndk/) runs on. If it’s not already present on your system, [download the NDK package for your system](https://developer.android.com/ndk/downloads/) and expand it to a suitable location. These instructions assume that it’s been expanded to -`~/android-ndk-r16`. - -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 -``` +`~/android-ndk-r20`. Note that Chrome uses Android API level 21 for 64-bit platforms and 16 for 32-bit platforms. See Chrome’s [`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`. -To configure a Crashpad build for Android using the standalone toolchain -assembled above, use `gyp_crashpad_android.py`. This script is a wrapper for -`gyp_crashpad.py` that sets several environment variables directing the build to -the standalone toolchain, and several GYP options to identify an Android build. -This must be done after any `gclient sync`, or instead of any `gclient runhooks` -operation. +To configure a Crashpad build for Android use `gyp_crashpad_android.py`. This +script is a wrapper for `gyp_crashpad.py` that sets several environment +variables directing the build to the toolchain, and several GYP options to +identify an Android build. This must be done after any `gclient sync`, or +instead of any `gclient runhooks` operation. ``` $ cd ~/crashpad/crashpad -$ python build/gyp_crashpad_android.py \ - --ndk ~/android-ndk-r16_arm64_api21 \ - --generator-output out/android_arm64_api21 +python build/gyp_crashpad_android.py \ + --ndk ~/usr/lib/android-ndk-r20 --arch arm64 --api-level 21 \ + --generator-output=out/android_arm64_api21 \ ``` -`gyp_crashpad_android.py` detects the build type based on the characteristics of -the standalone toolchain given in its `--ndk` argument. - -`gyp_crashpad_android.py` sets the build up to use Clang by default. It’s 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 +To build, direct `ninja` to the specific `out` directory chosen by the `--generator-output` argument to `gyp_crashpad_android.py`. ``` -$ ninja -C out/android_arm64_api21/out/Debug \ - crashpad_test_test crashpad_util_test +$ ninja -C out/android_arm64_api21/out/Debug all ``` ## Testing diff --git a/handler/handler.gyp b/handler/handler.gyp index 60a6f251..f80b5f02 100644 --- a/handler/handler.gyp +++ b/handler/handler.gyp @@ -39,6 +39,8 @@ 'crash_report_upload_thread.h', 'handler_main.cc', 'handler_main.h', + 'linux/capture_snapshot.cc', + 'linux/capture_snapshot.h', 'linux/crash_report_exception_handler.cc', 'linux/crash_report_exception_handler.h', 'linux/exception_handler_server.cc', diff --git a/util/util.gyp b/util/util.gyp index c7d735fb..b9da2324 100644 --- a/util/util.gyp +++ b/util/util.gyp @@ -395,8 +395,8 @@ ['OS=="linux" or OS=="android"', { 'sources': [ 'net/http_transport_socket.cc', - 'util/process_memory_sanitized.cc', - 'util/process_memory_sanitized.h', + 'process/process_memory_sanitized.cc', + 'process/process_memory_sanitized.h', ], }, { # else: OS!="linux" 'sources!': [ diff --git a/util/util_test.gyp b/util/util_test.gyp index c819e6db..f65a9186 100644 --- a/util/util_test.gyp +++ b/util/util_test.gyp @@ -156,7 +156,7 @@ }], ['OS=="linux" or OS=="android"', { 'sources': [ - 'util/process_memory_sanitized_test.cc', + 'process/process_memory_sanitized_test.cc', ], }], ['OS!="linux" and OS!="android"', {