gyp_crashpad_android.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. # Copyright 2017 The Crashpad Authors. All rights reserved.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. import argparse
  17. import glob
  18. import gyp_crashpad
  19. import os
  20. import re
  21. import subprocess
  22. import sys
  23. def main(args):
  24. parser = argparse.ArgumentParser(
  25. description='Set up an Android cross build',
  26. epilog='Additional arguments will be passed to gyp_crashpad.py.')
  27. parser.add_argument('--ndk', required=True, help='Standalone NDK toolchain')
  28. parser.add_argument('--compiler',
  29. default='clang',
  30. choices=('clang', 'gcc'),
  31. help='The compiler to use, clang by default')
  32. (parsed, extra_command_line_args) = parser.parse_known_args(args)
  33. NDK_ERROR=(
  34. 'NDK must be a valid standalone NDK toolchain.\n' +
  35. 'See https://developer.android.com/ndk/guides/standalone_toolchain.html')
  36. arch_dirs = glob.glob(os.path.join(parsed.ndk, '*-linux-android*'))
  37. if len(arch_dirs) != 1:
  38. parser.error(NDK_ERROR)
  39. arch_triplet = os.path.basename(arch_dirs[0])
  40. ARCH_TRIPLET_TO_ARCH = {
  41. 'arm-linux-androideabi': 'arm',
  42. 'aarch64-linux-android': 'arm64',
  43. 'i686-linux-android': 'ia32',
  44. 'x86_64-linux-android': 'x64',
  45. 'mipsel-linux-android': 'mips',
  46. 'mips64el-linux-android': 'mips64',
  47. }
  48. if arch_triplet not in ARCH_TRIPLET_TO_ARCH:
  49. parser.error(NDK_ERROR)
  50. arch = ARCH_TRIPLET_TO_ARCH[arch_triplet]
  51. ndk_bin_dir = os.path.join(parsed.ndk, 'bin')
  52. clang_path = os.path.join(ndk_bin_dir, 'clang')
  53. extra_args = []
  54. if parsed.compiler == 'clang':
  55. os.environ['CC_target'] = clang_path
  56. os.environ['CXX_target'] = os.path.join(ndk_bin_dir, 'clang++')
  57. elif parsed.compiler == 'gcc':
  58. os.environ['CC_target'] = os.path.join(ndk_bin_dir,
  59. '%s-gcc' % arch_triplet)
  60. os.environ['CXX_target'] = os.path.join(ndk_bin_dir,
  61. '%s-g++' % arch_triplet)
  62. # Unlike the Clang build, when using GCC with “unified headers,”
  63. # __ANDROID_API__ isn’t set automatically and must be pushed in to the
  64. # build. Fish the correct value out of the Clang wrapper script. If unified
  65. # headers are not being used, the Clang wrapper won’t mention
  66. # __ANDROID_API__, but the standalone toolchain’s <android/api-level.h> will
  67. # #define it for both Clang and GCC.
  68. #
  69. # Unified headers are the way of the future, according to
  70. # https://android.googlesource.com/platform/ndk/+/ndk-r14/CHANGELOG.md and
  71. # https://android.googlesource.com/platform/ndk/+/master/docs/UnifiedHeaders.md.
  72. with open(clang_path, 'r') as file:
  73. clang_script_contents = file.read()
  74. matches = re.finditer(r'\s-D__ANDROID_API__=([\d]+)\s',
  75. clang_script_contents)
  76. match = next(matches, None)
  77. if match:
  78. android_api = int(match.group(1))
  79. extra_args.extend(['-D', 'android_api_level=%d' % android_api])
  80. if next(matches, None):
  81. raise AssertionError('__ANDROID_API__ defined too many times')
  82. for tool in ('ar', 'nm', 'readelf'):
  83. os.environ['%s_target' % tool.upper()] = (
  84. os.path.join(ndk_bin_dir, '%s-%s' % (arch_triplet, tool)))
  85. return gyp_crashpad.main(
  86. ['-D', 'OS=android',
  87. '-D', 'target_arch=%s' % arch,
  88. '-D', 'clang=%d' % (1 if parsed.compiler == 'clang' else 0),
  89. '-f', 'ninja-android'] +
  90. extra_args +
  91. extra_command_line_args)
  92. if __name__ == '__main__':
  93. sys.exit(main(sys.argv[1:]))