Start to fusl toolchain

R=viettrungluu@chromium.org

Review URL: https://codereview.chromium.org/1649133002 .
diff --git a/build/toolchain/fusl/BUILD.gn b/build/toolchain/fusl/BUILD.gn
new file mode 100644
index 0000000..e6bb779
--- /dev/null
+++ b/build/toolchain/fusl/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/toolchain/gcc_toolchain.gni")
+
+gcc_toolchain("fusl_x64") {
+  prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin",
+                       root_build_dir)
+
+  cc = "$prefix/clang"
+  cxx = "$prefix/clang++"
+
+  readelf = "readelf"
+  nm = "nm"
+  ar = "ar"
+  ld = cc
+
+  toolchain_cpu = "x64"
+  toolchain_os = "linux"
+  is_clang = true
+
+  use_goma = false
+  use_ccache = false
+}
diff --git a/fusl/BUILD.gn b/fusl/BUILD.gn
index a352bcb..268f30f 100644
--- a/fusl/BUILD.gn
+++ b/fusl/BUILD.gn
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+# Define the sysroot directory.
+sysroot = "$root_out_dir/sysroot"
+
 config("fusl_config") {
   cflags = [
     # Flags from musl
@@ -39,6 +42,8 @@
   ]
 }
 
+# See the discussion below about what these files are, and their
+# relationship to other C runtime files.
 source_set("crt") {
   cflags = []
 
@@ -1467,10 +1472,12 @@
   deps += [ ":libc_${current_cpu}" ]
 }
 
-# Build a sysroot.
-sysroot = "${target_out_dir}/sysroot/"
-sysroot_lib_dir = "${sysroot}/usr/lib"
-sysroot_include_dir = "${sysroot}/usr/include"
+# For simplicity, musl places all its symbols in libc. To support
+# linking against e.g. libm, either implicitly or with an explicit -lm
+# flag, we build empty libraries.
+static_library("libm") {
+  complete_static_lib = true
+}
 
 template("copy_objects") {
   assert(defined(invoker.input_dir), "input_dir must be defined")
@@ -1504,6 +1511,9 @@
   }
 }
 
+sysroot_lib_dir = "${sysroot}/usr/lib"
+sysroot_include_dir = "${sysroot}/usr/include"
+
 copy_objects("copy_crt_objects") {
   sources = [
     "Scrt1.o",
@@ -1548,34 +1558,126 @@
   ]
 }
 
-copy("copy_libc") {
+copy("copy_libs") {
   deps = [
     ":libc",
+    ":libm",
   ]
   sources = [
     "${target_out_dir}/libc.a",
+    "${target_out_dir}/libm.a",
   ]
   outputs = [
-    "${sysroot_lib_dir}/libc.a",
+    "${sysroot_lib_dir}/{{source_name_part}}.a",
   ]
 }
 
-group("sysroot") {
+group("copy_sysroot") {
   deps = [
     ":copy_crt_objects",
     ":copy_include",
     ":copy_include_bits",
-    ":copy_libc",
+    ":copy_libs",
   ]
   if (current_cpu == "x64") {
     deps += [ ":copy_crt_x64_objects" ]
   }
 }
 
+# The crtXXX.o files that are copied elsewhere in this file define
+# _start, and the machinery to implement calling into the init and
+# fini sections. These things are libc dependent and hence part of
+# libc.
+#
+# Unlike the other crtXXX.o files, crtbegin and crtend, are provided
+# by the toolchain, not the libc. So we steal them from the host.
+#
+# crtbegin and crtend know how to call constructors and destructors.
+#
+# libgcc provides runtime support, and so also comes from the
+# compiler. Things in here are stack unwinding, arithmetic not
+# supported on the target architecture, and so on.
+#
+# The best document I am aware of describing the different variants of
+# these files (and crtXXX.o above) is
+# https://dev.gentoo.org/~vapier/crt.txt
+#
+# S and _s mean shared or PIE
+# T and _eh mean static
+action("finish_sysroot") {
+  script = "tools/populate_crt.py"
+
+  clang = "//third_party/llvm-build/Release+Asserts/bin/clang"
+  target = "$sysroot/usr/lib"
+
+  files = [
+    "crtbegin.o",
+    "crtbeginS.o",
+    "crtbeginT.o",
+    "crtend.o",
+    "crtendS.o",
+
+    "libgcc.a",
+    "libgcc_eh.a",
+    "libgcc_s.so",
+  ]
+
+  args = [
+    rebase_path(clang),
+    rebase_path(target),
+  ]
+  args += files
+
+  outputs = [
+    "$target/crtbegin.o",
+    "$target/crtbeginSo.o",
+    "$target/crtbeginT.o",
+    "$target/crtend.o",
+    "$target/crtendS.o",
+
+    "$target/libgcc.a",
+    "$target/libgcc_eh.a",
+    "$target/libgcc_s.so",
+  ]
+
+  deps = [
+    ":copy_sysroot",
+  ]
+}
+
+config("sysroot_config") {
+  rebased_sysroot = rebase_path(sysroot)
+
+  cflags = [
+    "--sysroot=$rebased_sysroot",
+    "-fPIC",
+    "-static",
+  ]
+
+  ldflags = [
+    "--sysroot=$rebased_sysroot",
+    "-static",
+  ]
+}
+
+executable("empty_main") {
+  configs = []
+  configs += [ ":sysroot_config" ]
+
+  sources = [
+    "test/empty_main.c",
+  ]
+
+  deps = [
+    ":finish_sysroot",
+  ]
+}
+
 group("fusl") {
   deps = [
-    ":crt",
-    ":libc",
-    ":sysroot",
+    ":crt(//build/toolchain/fusl:fusl_$current_cpu)",
+    ":empty_main(//build/toolchain/fusl:fusl_$current_cpu)",
+    ":finish_sysroot(//build/toolchain/fusl:fusl_$current_cpu)",
+    ":libc(//build/toolchain/fusl:fusl_$current_cpu)",
   ]
 }
diff --git a/fusl/test/empty_main.c b/fusl/test/empty_main.c
new file mode 100644
index 0000000..42d078b
--- /dev/null
+++ b/fusl/test/empty_main.c
@@ -0,0 +1,7 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+int main(int argc, char** argv) {
+  return 0;
+}
diff --git a/fusl/tools/populate_crt.py b/fusl/tools/populate_crt.py
new file mode 100644
index 0000000..733e5c8
--- /dev/null
+++ b/fusl/tools/populate_crt.py
@@ -0,0 +1,73 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+import shutil
+import subprocess
+import sys
+
+
+"""Populate the compiler-provided portions of the fusl sysroot.
+
+In particular, crtbegin, ocrtend.o,libgcc.a, and so on must be copied
+from the host sysroot to our sysroot.
+"""
+
+def parse_clang_dirs(clang):
+  """Parse the output of |clang -print-search-dirs|.
+
+  This is used to find library search paths. One line of the output
+  is formatted something like:
+
+  libraries: =/usr/lib/gcc/4.8:/lib:/usr/lib
+
+  This functions strips the 'libraries: =' prefix and splits on the
+  colon, returning the list:
+
+  [ '/usr/lib/gcc/4.8', '/lib', '/usr/lib' ]
+  """
+
+  clang_search_dirs = subprocess.check_output([clang, '-print-search-dirs'])
+
+  library_line = None
+  library_line_prefix = 'libraries: ='
+  for line in clang_search_dirs.split('\n'):
+    if line.startswith(library_line_prefix):
+      prefix_length = len(library_line_prefix)
+      library_line = line[prefix_length:]
+      break
+  assert(library_line)
+  return library_line.split(':')
+
+
+def try_populate(artifact, library_paths, target):
+  """Returns whether we found the artifact and copied it."""
+
+  for library_path in library_paths:
+    source = os.path.join(library_path, artifact)
+    if not os.path.isfile(source):
+      continue
+    shutil.copy(source, target)
+    return True
+
+  return False
+
+
+def main():
+  clang = sys.argv[1]
+  target = sys.argv[2]
+  artifacts = sys.argv[3:]
+  assert(len(artifacts))
+
+  library_paths = parse_clang_dirs(clang)
+
+  for artifact in artifacts:
+    if not try_populate(artifact, library_paths, target):
+      print('Unable to locate %s in any of the following paths: %s' %
+            (artifact, library_paths))
+      exit(1)
+
+
+if __name__ == '__main__':
+  main()