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,ia32} {executable,library,shared_library} {host,target} |
| 11 [linker args] |
| 12 """ |
| 13 |
| 14 import optparse |
| 15 import os |
| 16 import subprocess |
| 17 import sys |
| 18 |
| 19 # Figure out where we are. |
| 20 SCRIPT_DIR = os.path.dirname(sys.argv[0]) |
| 21 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) |
| 22 THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party') |
| 23 |
| 24 |
| 25 def CheckDirExists(path, docstring): |
| 26 if not os.path.isdir(path): |
| 27 raise Exception('Could not find %s directory %s' |
| 28 % (docstring, path)) |
| 29 |
| 30 |
| 31 def execute(args): |
| 32 process = subprocess.Popen(args) |
| 33 process.wait() |
| 34 return process.returncode |
| 35 |
| 36 |
| 37 def main(): |
| 38 if len(sys.argv) < 5: |
| 39 raise Exception(sys.argv[0] + " failed: not enough arguments") |
| 40 |
| 41 # gyp puts -shared first in a shared_library link. Remove it. |
| 42 if sys.argv[1] == '-shared': |
| 43 sys.argv.remove('-shared') |
| 44 |
| 45 # Grab the command line arguments. |
| 46 target_arch = sys.argv[1] |
| 47 link_type = sys.argv[2] |
| 48 link_target = sys.argv[3] |
| 49 link_args = sys.argv[4:] |
| 50 |
| 51 # Check arguments. |
| 52 if target_arch not in ['arm', 'ia32']: |
| 53 raise Exception(sys.argv[0] + " first argument must be 'arm' or 'ia32'") |
| 54 if link_type not in ['executable', 'library', 'shared_library']: |
| 55 raise Exception(sys.argv[0] + |
| 56 " second argument must be 'executable' or 'library'") |
| 57 if link_target not in ['host', 'target']: |
| 58 raise Exception(sys.argv[0] + " third argument must be 'host' or 'target'") |
| 59 |
| 60 # TODO(zra): Figure out how to link a shared library with the NDK |
| 61 # cross-compilers. For now, we disable it by generating empty files |
| 62 # for the results. We disable it here to avoid inspecting the OS type in |
| 63 # the gyp files. |
| 64 if link_type == 'shared_library': |
| 65 print "NOT linking shared library for Android." |
| 66 o_index = link_args.index('-o') |
| 67 output = os.path.join(DART_ROOT, link_args[o_index + 1]) |
| 68 open(output, 'a').close() |
| 69 sys.exit(0) |
| 70 |
| 71 # Set up path to the Android NDK. |
| 72 CheckDirExists(THIRD_PARTY_ROOT, 'third party tools'); |
| 73 android_tools = os.path.join(THIRD_PARTY_ROOT, 'android_tools') |
| 74 CheckDirExists(android_tools, 'Android tools') |
| 75 android_ndk_root = os.path.join(android_tools, 'ndk') |
| 76 CheckDirExists(android_ndk_root, 'Android NDK') |
| 77 |
| 78 # Set up the directory of the Android NDK cross-compiler toolchain. |
| 79 toolchain_arch = 'arm-linux-androideabi-4.6' |
| 80 if target_arch == 'ia32': |
| 81 toolchain_arch = 'x86-4.6' |
| 82 toolchain_dir = 'linux-x86' |
| 83 android_toolchain = os.path.join(android_ndk_root, |
| 84 'toolchains', toolchain_arch, |
| 85 'prebuilt', toolchain_dir, 'bin') |
| 86 CheckDirExists(android_toolchain, 'Android toolchain') |
| 87 |
| 88 # Set up the path to the linker executable. |
| 89 android_linker = os.path.join(android_toolchain, 'arm-linux-androideabi-g++') |
| 90 if target_arch == 'ia32': |
| 91 android_linker = os.path.join(android_toolchain, 'i686-linux-android-g++') |
| 92 |
| 93 # Grab the path to libgcc.a, which we must explicitly add to the link, |
| 94 # by invoking the cross-compiler with the -print-libgcc-file-name flag. |
| 95 android_gcc = os.path.join(android_toolchain, 'arm-linux-androideabi-gcc') |
| 96 if target_arch == 'ia32': |
| 97 android_gcc = os.path.join(android_toolchain, 'i686-linux-android-gcc') |
| 98 android_libgcc = subprocess.check_output( |
| 99 [android_gcc, '-print-libgcc-file-name']).strip() |
| 100 |
| 101 # Set up the path to the system root directory, which is where we'll find the |
| 102 # Android specific system includes and libraries. |
| 103 android_ndk_sysroot = os.path.join(android_ndk_root, |
| 104 'platforms', 'android-14', 'arch-arm') |
| 105 if target_arch == 'ia32': |
| 106 android_ndk_sysroot = os.path.join(android_ndk_root, |
| 107 'platforms', 'android-14', 'arch-x86') |
| 108 CheckDirExists(android_ndk_sysroot, 'Android sysroot') |
| 109 android_ndk_lib = os.path.join(android_ndk_sysroot,'usr','lib') |
| 110 android_ndk_include = os.path.join(android_ndk_sysroot, 'usr', 'include') |
| 111 crtend_android = os.path.join(android_ndk_lib, 'crtend_android.o') |
| 112 |
| 113 if link_target == 'target': |
| 114 # Add and remove libraries as listed in configurations_android.gypi |
| 115 libs_to_rm = ['-lrt', '-lpthread', '-lnss3', '-lnssutil3', '-lsmime3', |
| 116 '-lplds4', '-lplc4', '-lnspr4',] |
| 117 libs_to_add = ['-lstlport_static', android_libgcc, '-lc', '-ldl', |
| 118 '-lstdc++', '-lm',] |
| 119 |
| 120 # Add crtend_android to end if we are linking an executable. |
| 121 if link_type == 'executable': |
| 122 libs_to_add.extend(['-llog', '-lz', crtend_android]) |
| 123 |
| 124 link_args = [i for i in link_args if i not in libs_to_rm] |
| 125 link_args.extend(libs_to_add) |
| 126 |
| 127 link_args.insert(0, android_linker) |
| 128 else: |
| 129 link_args.extend(['-ldl', '-lrt']) |
| 130 link_args.insert(0, 'g++') |
| 131 |
| 132 sys.exit(execute(link_args)) |
| 133 |
| 134 if __name__ == '__main__': |
| 135 main() |
OLD | NEW |