[fusl] Build libcxx atop fusl

Fixes #657

R=viettrungluu@chromium.org, phosek@chromium.org

Review URL: https://codereview.chromium.org/1596483004 .
diff --git a/build/toolchain/fusl/BUILD.gn b/build/toolchain/fusl/BUILD.gn
index e6bb779..76a2b54 100644
--- a/build/toolchain/fusl/BUILD.gn
+++ b/build/toolchain/fusl/BUILD.gn
@@ -14,7 +14,7 @@
   readelf = "readelf"
   nm = "nm"
   ar = "ar"
-  ld = cc
+  ld = cxx
 
   toolchain_cpu = "x64"
   toolchain_os = "linux"
diff --git a/fusl/BUILD.gn b/fusl/BUILD.gn
index dec809a..147a7ee 100644
--- a/fusl/BUILD.gn
+++ b/fusl/BUILD.gn
@@ -153,7 +153,182 @@
   ]
 }
 
-config("sysroot_config") {
+copy("copy_libcxx") {
+  sources = [
+    "${target_out_dir}/../third_party/libcxx/libcxx.a",
+  ]
+  outputs = [
+    "${sysroot_lib_dir}/libc++.a",
+  ]
+  deps = [
+    "//third_party/libcxx:libcxx",
+  ]
+}
+
+action("copy_libcxx_headers") {
+  script = "tools/copy_libcxx_headers.py"
+
+  deps = [
+    ":copy_sysroot",
+  ]
+
+  source_dir = "//third_party/libcxx/libcxx/include"
+
+  # Annoyingly, this has to be ".../c++/v1" for clang to automatically
+  # add it to the includes.
+  target_dir = "${sysroot_include_dir}/c++/v1"
+
+  args = [
+    rebase_path(source_dir),
+    rebase_path(target_dir),
+  ]
+
+  outputs = [
+    "${target_dir}/__bit_reference",
+    "${target_dir}/__config",
+    "${target_dir}/__config_site.in",
+    "${target_dir}/__debug",
+    "${target_dir}/__functional_03",
+    "${target_dir}/__functional_base",
+    "${target_dir}/__functional_base_03",
+    "${target_dir}/__hash_table",
+    "${target_dir}/__locale",
+    "${target_dir}/__mutex_base",
+    "${target_dir}/__nullptr",
+    "${target_dir}/__refstring",
+    "${target_dir}/__split_buffer",
+    "${target_dir}/__sso_allocator",
+    "${target_dir}/__std_stream",
+    "${target_dir}/__tree",
+    "${target_dir}/__tuple",
+    "${target_dir}/__undef___deallocate",
+    "${target_dir}/__undef_min_max",
+    "${target_dir}/algorithm",
+    "${target_dir}/array",
+    "${target_dir}/atomic",
+    "${target_dir}/bitset",
+    "${target_dir}/cassert",
+    "${target_dir}/ccomplex",
+    "${target_dir}/cctype",
+    "${target_dir}/cerrno",
+    "${target_dir}/cfenv",
+    "${target_dir}/cfloat",
+    "${target_dir}/chrono",
+    "${target_dir}/cinttypes",
+    "${target_dir}/ciso646",
+    "${target_dir}/climits",
+    "${target_dir}/clocale",
+    "${target_dir}/cmath",
+    "${target_dir}/codecvt",
+    "${target_dir}/complex",
+    "${target_dir}/complex.h",
+    "${target_dir}/condition_variable",
+    "${target_dir}/csetjmp",
+    "${target_dir}/csignal",
+    "${target_dir}/cstdarg",
+    "${target_dir}/cstdbool",
+    "${target_dir}/cstddef",
+    "${target_dir}/cstdint",
+    "${target_dir}/cstdio",
+    "${target_dir}/cstdlib",
+    "${target_dir}/cstring",
+    "${target_dir}/ctgmath",
+    "${target_dir}/ctime",
+    "${target_dir}/ctype.h",
+    "${target_dir}/cwchar",
+    "${target_dir}/cwctype",
+    "${target_dir}/deque",
+    "${target_dir}/errno.h",
+    "${target_dir}/exception",
+    "${target_dir}/experimental/__config",
+    "${target_dir}/experimental/algorithm",
+    "${target_dir}/experimental/any",
+    "${target_dir}/experimental/chrono",
+    "${target_dir}/experimental/dynarray",
+    "${target_dir}/experimental/functional",
+    "${target_dir}/experimental/optional",
+    "${target_dir}/experimental/ratio",
+    "${target_dir}/experimental/string_view",
+    "${target_dir}/experimental/system_error",
+    "${target_dir}/experimental/tuple",
+    "${target_dir}/experimental/type_traits",
+    "${target_dir}/experimental/utility",
+    "${target_dir}/ext/__hash",
+    "${target_dir}/ext/hash_map",
+    "${target_dir}/ext/hash_set",
+    "${target_dir}/float.h",
+    "${target_dir}/forward_list",
+    "${target_dir}/fstream",
+    "${target_dir}/functional",
+    "${target_dir}/future",
+    "${target_dir}/initializer_list",
+    "${target_dir}/inttypes.h",
+    "${target_dir}/iomanip",
+    "${target_dir}/ios",
+    "${target_dir}/iosfwd",
+    "${target_dir}/iostream",
+    "${target_dir}/istream",
+    "${target_dir}/iterator",
+    "${target_dir}/limits",
+    "${target_dir}/list",
+    "${target_dir}/locale",
+    "${target_dir}/map",
+    "${target_dir}/math.h",
+    "${target_dir}/memory",
+    "${target_dir}/module.modulemap",
+    "${target_dir}/mutex",
+    "${target_dir}/new",
+    "${target_dir}/numeric",
+    "${target_dir}/ostream",
+    "${target_dir}/queue",
+    "${target_dir}/random",
+    "${target_dir}/ratio",
+    "${target_dir}/regex",
+    "${target_dir}/scoped_allocator",
+    "${target_dir}/set",
+    "${target_dir}/setjmp.h",
+    "${target_dir}/shared_mutex",
+    "${target_dir}/sstream",
+    "${target_dir}/stack",
+    "${target_dir}/stddef.h",
+    "${target_dir}/stdexcept",
+    "${target_dir}/stdio.h",
+    "${target_dir}/stdlib.h",
+    "${target_dir}/streambuf",
+    "${target_dir}/string",
+    "${target_dir}/strstream",
+    "${target_dir}/support/android/locale_bionic.h",
+    "${target_dir}/support/ibm/limits.h",
+    "${target_dir}/support/ibm/support.h",
+    "${target_dir}/support/ibm/xlocale.h",
+    "${target_dir}/support/musl/xlocale.h",
+    "${target_dir}/support/newlib/xlocale.h",
+    "${target_dir}/support/solaris/floatingpoint.h",
+    "${target_dir}/support/solaris/wchar.h",
+    "${target_dir}/support/solaris/xlocale.h",
+    "${target_dir}/support/win32/limits_win32.h",
+    "${target_dir}/support/win32/locale_win32.h",
+    "${target_dir}/support/win32/math_win32.h",
+    "${target_dir}/support/win32/support.h",
+    "${target_dir}/support/xlocale/xlocale.h",
+    "${target_dir}/system_error",
+    "${target_dir}/tgmath.h",
+    "${target_dir}/thread",
+    "${target_dir}/tuple",
+    "${target_dir}/type_traits",
+    "${target_dir}/typeindex",
+    "${target_dir}/typeinfo",
+    "${target_dir}/unordered_map",
+    "${target_dir}/unordered_set",
+    "${target_dir}/utility",
+    "${target_dir}/valarray",
+    "${target_dir}/vector",
+    "${target_dir}/wchar.h",
+    "${target_dir}/wctype.h",
+  ]
+}
+
+config("fusl_sysroot_config") {
   rebased_sysroot = rebase_path(sysroot)
 
   cflags = [
@@ -162,15 +337,41 @@
     "-static",
   ]
 
+  cflags_c = [ "-std=c11" ]
+
+  cflags_cc = [
+    "-std=c++11",
+
+    # Make everyone using our libc++ headers use musl paths rather
+    # than glibc ones.
+    "-D_LIBCPP_HAS_MUSL_LIBC",
+
+    # This is necessary for clang to get the header search paths right.
+    "-stdlib=libc++",
+  ]
+
   ldflags = [
     "--sysroot=$rebased_sysroot",
     "-static",
+    "-stdlib=libc++",
+  ]
+}
+
+config("fusl_sysroot_config_c") {
+  ldflags = [
+    # Using clang++ as the linker driver is necessary for libc++
+    # resolution to work.
+    "-nodefaultlibs",
+    "-lc",
   ]
 }
 
 executable("empty_main") {
   configs = []
-  configs += [ ":sysroot_config" ]
+  configs += [
+    ":fusl_sysroot_config",
+    ":fusl_sysroot_config_c",
+  ]
 
   sources = [
     "test/empty_main.c",
@@ -181,10 +382,33 @@
   ]
 }
 
+executable("vector") {
+  configs = []
+  configs += [ ":fusl_sysroot_config" ]
+
+  sources = [
+    "test/vector.cc",
+  ]
+
+  deps = [
+    ":copy_libcxx",
+    ":copy_libcxx_headers",
+  ]
+}
+
+group("fusl_pre_toolchain") {
+  deps = [
+    ":copy_sysroot",
+    ":empty_main",
+    ":libc",
+    ":vector",
+    "crt",
+    "//third_party/libcxx:libcxx",
+  ]
+}
+
 group("fusl") {
   deps = [
-    ":empty_main(//build/toolchain/fusl:fusl_$current_cpu)",
-    ":libc(//build/toolchain/fusl:fusl_$current_cpu)",
-    "crt(//build/toolchain/fusl:fusl_$current_cpu)",
+    ":fusl_pre_toolchain(//build/toolchain/fusl:fusl_$current_cpu)",
   ]
 }
diff --git a/fusl/test/vector.cc b/fusl/test/vector.cc
new file mode 100644
index 0000000..77b04a3
--- /dev/null
+++ b/fusl/test/vector.cc
@@ -0,0 +1,9 @@
+// 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.
+
+#include <vector>
+
+int main(int argc, char** argv) {
+  std::vector<int> xs(10);
+}
diff --git a/fusl/tools/copy_libcxx_headers.py b/fusl/tools/copy_libcxx_headers.py
new file mode 100644
index 0000000..220c919
--- /dev/null
+++ b/fusl/tools/copy_libcxx_headers.py
@@ -0,0 +1,34 @@
+# 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
+import shutil
+import sys
+
+
+def copytree(source_dir, target_dir):
+  """Copy a tree.
+
+  This is needed because shutil.copytree requires that |target| not
+  exist yet.
+
+  """
+
+  for file in os.listdir(source_dir):
+    source = os.path.join(source_dir, file)
+    target = os.path.join(target_dir, file)
+    if os.path.isfile(source):
+      shutil.copy(source, target)
+    else:
+      copytree(source, target)
+
+
+def main():
+  source_path = sys.argv[1]
+  target_path = sys.argv[2]
+  copytree(source_path, target_path)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/libcxx/BUILD.gn b/third_party/libcxx/BUILD.gn
new file mode 100644
index 0000000..368608b
--- /dev/null
+++ b/third_party/libcxx/BUILD.gn
@@ -0,0 +1,169 @@
+# 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.
+
+config("libcxx_common_config") {
+  cflags = [
+    # Flags from upstream CMake builds.
+    "-D_DEBUG",
+    "-D__STDC_CONSTANT_MACROS",
+    "-D__STDC_FORMAT_MACROS",
+    "-D__STDC_LIMIT_MACROS",
+
+    "-fPIC",
+    "-fvisibility-inlines-hidden",
+
+    "-Werror=return-type",
+
+    "-Wall",
+
+    "-Wcast-qual",
+    "-Wcovered-switch-default",
+    "-Wdelete-non-virtual-dtor",
+    "-Wmissing-field-initializers",
+    "-Wnon-virtual-dtor",
+    "-Wwrite-strings",
+
+    "-Wno-error",
+    "-Wno-long-long",
+    "-Wno-unused-function",
+
+    "-std=c++11",
+    "-nostdinc++",
+
+    # Use our sysroot.
+    "--sysroot=fusl_${current_cpu}/sysroot",
+
+    # Use musl-based libc++ header paths.
+    "-D_LIBCPP_HAS_MUSL_LIBC",
+  ]
+
+  include_dirs = [
+    "libcxx/include",
+    "libcxxabi/include",
+  ]
+}
+
+config("libcxx_config") {
+  cflags = [
+    # Flags from upstream CMake build.
+    "-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER",
+    "-Dcxx_EXPORTS",
+    "-DLIBCXX_BUILDING_LIBCXXABI",
+
+    "-UNDEBUG",
+
+    "-Wno-unused-parameter",
+
+    # Build fix for musl.
+    "-Wno-invalid-constexpr",
+  ]
+}
+
+config("libcxxabi_config") {
+  cflags = [
+    # Flags from upstream CMake build.
+    "-fstrict-aliasing",
+
+    "-Wchar-subscripts",
+    "-Wconversion",
+    "-Wmismatched-tags",
+    "-Wmissing-braces",
+    "-Wnewline-eof",
+    "-Wshadow",
+    "-Wshorten-64-to-32",
+    "-Wsign-compare",
+    "-Wsign-conversion",
+    "-Wstrict-aliasing=2",
+    "-Wstrict-overflow=4",
+    "-Wundef",
+    "-Wunused-parameter",
+    "-Wunused-variable",
+
+    "-pedantic",
+  ]
+}
+
+source_set("libcxxabi_sources") {
+  configs = []
+  configs += [
+    ":libcxxabi_config",
+    ":libcxx_common_config",
+  ]
+
+  deps = [
+    "//fusl:copy_sysroot",
+  ]
+
+  sources = [
+    "libcxxabi/src/abort_message.cpp",
+    "libcxxabi/src/cxa_aux_runtime.cpp",
+    "libcxxabi/src/cxa_default_handlers.cpp",
+    "libcxxabi/src/cxa_demangle.cpp",
+    "libcxxabi/src/cxa_exception.cpp",
+    "libcxxabi/src/cxa_exception_storage.cpp",
+    "libcxxabi/src/cxa_guard.cpp",
+    "libcxxabi/src/cxa_handlers.cpp",
+    "libcxxabi/src/cxa_new_delete.cpp",
+    "libcxxabi/src/cxa_personality.cpp",
+    "libcxxabi/src/cxa_thread_atexit.cpp",
+    "libcxxabi/src/cxa_unexpected.cpp",
+    "libcxxabi/src/cxa_vector.cpp",
+    "libcxxabi/src/cxa_virtual.cpp",
+    "libcxxabi/src/exception.cpp",
+    "libcxxabi/src/private_typeinfo.cpp",
+    "libcxxabi/src/stdexcept.cpp",
+    "libcxxabi/src/typeinfo.cpp",
+  ]
+}
+
+source_set("libcxx_sources") {
+  configs = []
+  configs += [
+    ":libcxx_config",
+    ":libcxx_common_config",
+  ]
+
+  deps = [
+    "//fusl:copy_sysroot",
+  ]
+
+  sources = [
+    "libcxx/src/algorithm.cpp",
+    "libcxx/src/any.cpp",
+    "libcxx/src/bind.cpp",
+    "libcxx/src/chrono.cpp",
+    "libcxx/src/condition_variable.cpp",
+    "libcxx/src/debug.cpp",
+    "libcxx/src/exception.cpp",
+    "libcxx/src/future.cpp",
+    "libcxx/src/hash.cpp",
+    "libcxx/src/ios.cpp",
+    "libcxx/src/iostream.cpp",
+    "libcxx/src/locale.cpp",
+    "libcxx/src/memory.cpp",
+    "libcxx/src/mutex.cpp",
+    "libcxx/src/new.cpp",
+    "libcxx/src/optional.cpp",
+    "libcxx/src/random.cpp",
+    "libcxx/src/regex.cpp",
+    "libcxx/src/shared_mutex.cpp",
+    "libcxx/src/stdexcept.cpp",
+    "libcxx/src/string.cpp",
+    "libcxx/src/strstream.cpp",
+    "libcxx/src/system_error.cpp",
+    "libcxx/src/thread.cpp",
+    "libcxx/src/typeinfo.cpp",
+    "libcxx/src/utility.cpp",
+    "libcxx/src/valarray.cpp",
+  ]
+}
+
+static_library("libcxx") {
+  complete_static_lib = true
+
+  deps = [
+    ":libcxx_sources",
+    ":libcxxabi_sources",
+  ]
+}