Index: tools/fuchsia_link.py |
diff --git a/tools/fuchsia_link.py b/tools/fuchsia_link.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..c3c537b6b55af02dc0346a999c55a6a0a164a4b2 |
--- /dev/null |
+++ b/tools/fuchsia_link.py |
@@ -0,0 +1,127 @@ |
+#!/usr/bin/env python |
+ |
+# Copyright (c) 2016 The Dart Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+""" |
+This script performs the final link step for Fuchsia NDK executables. |
+Usage: |
+./fuchsia_link {arm,arm64,ia32} {executable,library,shared_library} |
+ {host,target} [linker args] |
+""" |
+ |
+import os |
+import subprocess |
+import sys |
+ |
+# Figure out where we are. |
+SCRIPT_DIR = os.path.dirname(sys.argv[0]) |
+DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) |
+THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party') |
+ |
+ |
+def CheckDirExists(path, docstring): |
+ if not os.path.isdir(path): |
+ raise Exception('Could not find %s directory %s' |
+ % (docstring, path)) |
+ |
+ |
+def execute(args): |
+ process = subprocess.Popen(args) |
+ process.wait() |
+ return process.returncode |
+ |
+ |
+def main(): |
+ if len(sys.argv) < 5: |
+ raise Exception(sys.argv[0] + " failed: not enough arguments") |
+ |
+ # gyp puts -shared first in a shared_library link. Remove it. |
+ if sys.argv[1] == '-shared': |
+ sys.argv.remove('-shared') |
+ |
+ # Grab the command line arguments. |
+ target_arch = sys.argv[1] |
+ link_type = sys.argv[2] |
+ link_target = sys.argv[3] |
+ link_args = sys.argv[4:] |
+ |
+ # Check arguments. |
+ if target_arch not in ['arm64', 'x64',]: |
+ raise Exception(sys.argv[0] + |
+ " first argument must be 'arm64', or 'x64'") |
+ if link_type not in ['executable', 'library', 'shared_library']: |
+ raise Exception(sys.argv[0] + |
+ " second argument must be 'executable' or 'library' or 'shared_library'") |
+ if link_target not in ['host', 'target']: |
+ raise Exception(sys.argv[0] + " third argument must be 'host' or 'target'") |
+ |
+ # TODO(zra): Figure out how to link a shared library with the |
+ # cross-compilers. For now, we disable it by generating empty files |
+ # for the results. We disable it here to avoid inspecting the OS type in |
+ # the gyp files. |
+ if link_type == 'shared_library': |
+ print "NOT linking shared library for Fuchsia." |
+ o_index = link_args.index('-o') |
+ output = os.path.join(DART_ROOT, link_args[o_index + 1]) |
+ open(output, 'a').close() |
+ sys.exit(0) |
+ |
+ # Set up path to the Fuchsia NDK. |
+ CheckDirExists(THIRD_PARTY_ROOT, 'third party tools') |
+ fuchsia_tools = os.path.join(THIRD_PARTY_ROOT, 'fuchsia_tools') |
+ CheckDirExists(fuchsia_tools, 'Fuchsia tools') |
+ |
+ # Set up the directory of the Fuchsia NDK cross-compiler toolchain. |
+ toolchain_arch = 'x86_64-elf-5.3.0-Linux-x86_64' |
+ if target_arch == 'arm64': |
+ toolchain_arch = 'aarch64-elf-5.3.0-Linux-x86_64' |
+ fuchsia_toolchain = os.path.join( |
+ fuchsia_tools, 'toolchains', toolchain_arch, 'bin') |
+ CheckDirExists(fuchsia_toolchain, 'Fuchsia toolchain') |
+ |
+ # Set up the path to the linker executable. |
+ fuchsia_linker = os.path.join(fuchsia_toolchain, 'x86_64-elf-g++') |
+ if target_arch == 'arm64': |
+ fuchsia_linker = os.path.join(fuchsia_toolchain, 'aarch64-elf-c++') |
+ |
+ # Grab the path to libgcc.a, which we must explicitly add to the link, |
+ # by invoking the cross-compiler with the -print-libgcc-file-name flag. |
+ fuchsia_gcc = os.path.join(fuchsia_toolchain, 'x86_64-elf-gcc') |
+ if target_arch == 'arm64': |
+ fuchsia_gcc = os.path.join(fuchsia_toolchain, 'aarch64-elf-gcc') |
+ fuchsia_libgcc = subprocess.check_output( |
+ [fuchsia_gcc, '-print-libgcc-file-name']).strip() |
+ |
+ # Set up the path to the system root directory, which is where we'll find the |
+ # Fuchsia specific system includes and libraries. |
+ fuchsia_sysroot = os.path.join(fuchsia_tools, 'sysroot', 'x86_64') |
+ if target_arch == 'arm64': |
+ fuchsia_sysroot = os.path.join(fuchsia_tools, 'sysroot', 'arm64') |
+ CheckDirExists(fuchsia_sysroot, 'Fuchsia sysroot') |
+ fuchsia_lib = os.path.join(fuchsia_sysroot, 'usr', 'lib') |
+ crtn_fuchsia = os.path.join(fuchsia_lib, 'crtn.o') |
+ |
+ if link_target == 'target': |
+ # Add and remove libraries as listed in configurations_fuchsia.gypi |
+ libs_to_rm = ['-lrt', '-lpthread', '-ldl'] |
+ libs_to_add = [fuchsia_libgcc, '-lc',] |
+ |
+ # Add crtn_fuchsia to end if we are linking an executable. |
+ if link_type == 'executable': |
+ libs_to_add.extend([crtn_fuchsia]) |
+ |
+ link_args = [i for i in link_args if i not in libs_to_rm] |
+ link_args.extend(libs_to_add) |
+ |
+ link_args.insert(0, fuchsia_linker) |
+ else: |
+ link_args.extend(['-ldl', '-lrt']) |
+ link_args.insert(0, 'g++') |
+ |
+ print ' '.join(link_args) |
+ sys.exit(execute(link_args)) |
+ |
+if __name__ == '__main__': |
+ main() |