| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 | |
| 3 # Copyright (c) 2012 The Dart Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 | |
| 7 """ | |
| 8 This script performs the final link step for Android NDK executables. | |
| 9 Usage: | |
| 10 ./android_link {arm,arm64,ia32} {executable,library,shared_library} | |
| 11 {host,target} [linker args] | |
| 12 """ | |
| 13 | |
| 14 import os | |
| 15 import subprocess | |
| 16 import sys | |
| 17 | |
| 18 # Figure out where we are. | |
| 19 SCRIPT_DIR = os.path.dirname(sys.argv[0]) | |
| 20 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) | |
| 21 THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party') | |
| 22 | |
| 23 | |
| 24 def CheckDirExists(path, docstring): | |
| 25 if not os.path.isdir(path): | |
| 26 raise Exception('Could not find %s directory %s' | |
| 27 % (docstring, path)) | |
| 28 | |
| 29 | |
| 30 def execute(args): | |
| 31 process = subprocess.Popen(args) | |
| 32 process.wait() | |
| 33 return process.returncode | |
| 34 | |
| 35 | |
| 36 def main(): | |
| 37 if len(sys.argv) < 5: | |
| 38 raise Exception(sys.argv[0] + " failed: not enough arguments") | |
| 39 | |
| 40 # gyp puts -shared first in a shared_library link. Remove it. | |
| 41 if sys.argv[1] == '-shared': | |
| 42 sys.argv.remove('-shared') | |
| 43 | |
| 44 # Grab the command line arguments. | |
| 45 target_arch = sys.argv[1] | |
| 46 link_type = sys.argv[2] | |
| 47 link_target = sys.argv[3] | |
| 48 link_args = sys.argv[4:] | |
| 49 | |
| 50 # Check arguments. | |
| 51 if target_arch not in ['arm', 'arm64', 'ia32', 'x64', 'simdbc', 'simdbc64']: | |
| 52 raise Exception(sys.argv[0] + | |
| 53 " first argument must be 'arm', 'arm64', 'ia32', 'x64', " | |
| 54 "'simdbc', or 'simdbc64'") | |
| 55 if link_type not in ['executable', 'library', 'shared_library']: | |
| 56 raise Exception(sys.argv[0] + | |
| 57 " second argument must be 'executable' or 'library'") | |
| 58 if link_target not in ['host', 'target']: | |
| 59 raise Exception(sys.argv[0] + " third argument must be 'host' or 'target'") | |
| 60 | |
| 61 # TODO(zra): Figure out how to link a shared library with the NDK | |
| 62 # cross-compilers. For now, we disable it by generating empty files | |
| 63 # for the results. We disable it here to avoid inspecting the OS type in | |
| 64 # the gyp files. | |
| 65 if link_type == 'shared_library': | |
| 66 print "NOT linking shared library for Android." | |
| 67 o_index = link_args.index('-o') | |
| 68 output = os.path.join(DART_ROOT, link_args[o_index + 1]) | |
| 69 open(output, 'a').close() | |
| 70 sys.exit(0) | |
| 71 | |
| 72 # Set up path to the Android NDK. | |
| 73 CheckDirExists(THIRD_PARTY_ROOT, 'third party tools') | |
| 74 android_tools = os.path.join(THIRD_PARTY_ROOT, 'android_tools') | |
| 75 CheckDirExists(android_tools, 'Android tools') | |
| 76 android_ndk_root = os.path.join(android_tools, 'ndk') | |
| 77 CheckDirExists(android_ndk_root, 'Android NDK') | |
| 78 | |
| 79 # Set up the directory of the Android NDK cross-compiler toolchain. | |
| 80 toolchain_arch = 'arm-linux-androideabi-4.9' | |
| 81 if target_arch == 'arm64' or target_arch == "simdbc64": | |
| 82 toolchain_arch = 'aarch64-linux-android-4.9' | |
| 83 if target_arch == 'ia32': | |
| 84 toolchain_arch = 'x86-4.9' | |
| 85 if target_arch == 'x64': | |
| 86 toolchain_arch = 'x86_64-4.9' | |
| 87 toolchain_dir = 'linux-x86_64' | |
| 88 android_toolchain = os.path.join(android_ndk_root, | |
| 89 'toolchains', toolchain_arch, | |
| 90 'prebuilt', toolchain_dir, 'bin') | |
| 91 CheckDirExists(android_toolchain, 'Android toolchain') | |
| 92 | |
| 93 # Set up the path to the linker executable. | |
| 94 android_linker = os.path.join(android_toolchain, 'arm-linux-androideabi-g++') | |
| 95 if target_arch == 'arm64' or target_arch == "simdbc64": | |
| 96 android_linker = os.path.join( | |
| 97 android_toolchain, 'aarch64-linux-android-c++') | |
| 98 if target_arch == 'ia32': | |
| 99 android_linker = os.path.join(android_toolchain, 'i686-linux-android-g++') | |
| 100 if target_arch == 'x64': | |
| 101 android_linker = os.path.join(android_toolchain, 'x86_64-linux-android-g++') | |
| 102 | |
| 103 # Grab the path to libgcc.a, which we must explicitly add to the link, | |
| 104 # by invoking the cross-compiler with the -print-libgcc-file-name flag. | |
| 105 android_gcc = os.path.join(android_toolchain, 'arm-linux-androideabi-gcc') | |
| 106 if target_arch == 'arm64' or target_arch == "simdbc64": | |
| 107 android_gcc = os.path.join(android_toolchain, 'aarch64-linux-android-gcc') | |
| 108 if target_arch == 'ia32': | |
| 109 android_gcc = os.path.join(android_toolchain, 'i686-linux-android-gcc') | |
| 110 if target_arch == 'x64': | |
| 111 android_gcc = os.path.join(android_toolchain, 'x86_64-linux-android-gcc') | |
| 112 android_libgcc = subprocess.check_output( | |
| 113 [android_gcc, '-print-libgcc-file-name']).strip() | |
| 114 | |
| 115 # Set up the path to the system root directory, which is where we'll find the | |
| 116 # Android specific system includes and libraries. | |
| 117 android_ndk_sysroot = os.path.join(android_ndk_root, | |
| 118 'platforms', 'android-14', 'arch-arm') | |
| 119 libdir = 'lib' | |
| 120 if target_arch == 'arm64' or target_arch == "simdbc64": | |
| 121 android_ndk_sysroot = os.path.join(android_ndk_root, | |
| 122 'platforms', 'android-21', 'arch-arm64') | |
| 123 if target_arch == 'ia32': | |
| 124 android_ndk_sysroot = os.path.join(android_ndk_root, | |
| 125 'platforms', 'android-14', 'arch-x86') | |
| 126 if target_arch == 'x64': | |
| 127 android_ndk_sysroot = os.path.join(android_ndk_root, | |
| 128 'platforms', 'android-21', 'arch-x86_64') | |
| 129 libdir = 'lib64' | |
| 130 CheckDirExists(android_ndk_sysroot, 'Android sysroot') | |
| 131 android_ndk_lib = os.path.join(android_ndk_sysroot, 'usr', libdir) | |
| 132 crtend_android = os.path.join(android_ndk_lib, 'crtend_android.o') | |
| 133 | |
| 134 if link_target == 'target': | |
| 135 # We meddle with the android link command line here because gyp does not | |
| 136 # allow configurations to modify link_settings, or set variables. | |
| 137 | |
| 138 # Add and remove libraries as listed in configurations_android.gypi | |
| 139 libs_to_rm = ['-lrt', '-lpthread',] | |
| 140 libs_to_add = ['-lstlport_static', android_libgcc, '-lc', '-ldl', | |
| 141 '-lstdc++', '-lm',] | |
| 142 | |
| 143 # Add crtend_android to end if we are linking an executable. | |
| 144 if link_type == 'executable': | |
| 145 libs_to_add.extend(['-llog', '-lz', crtend_android]) | |
| 146 | |
| 147 # Filter out -l libs and add the right Android ones. | |
| 148 link_args = [i for i in link_args if i not in libs_to_rm] | |
| 149 link_args.extend(libs_to_add) | |
| 150 | |
| 151 # Filter out tcmalloc. | |
| 152 link_args = [i for i in link_args if "tcmalloc" not in i] | |
| 153 | |
| 154 link_args.insert(0, android_linker) | |
| 155 else: | |
| 156 link_args.extend(['-ldl', '-lrt']) | |
| 157 link_args.insert(0, 'g++') | |
| 158 | |
| 159 sys.exit(execute(link_args)) | |
| 160 | |
| 161 if __name__ == '__main__': | |
| 162 main() | |
| OLD | NEW |