summaryrefslogtreecommitdiffstats
path: root/build/build-clang
diff options
context:
space:
mode:
Diffstat (limited to 'build/build-clang')
-rw-r--r--build/build-clang/README45
-rwxr-xr-xbuild/build-clang/build-clang.py425
-rw-r--r--build/build-clang/clang-static-analysis-linux64.json30
-rw-r--r--build/build-clang/clang-static-analysis-macosx64.json29
-rw-r--r--build/build-clang/clang-static-analysis-win32.json16
-rw-r--r--build/build-clang/clang-static-analysis-win64.json16
-rw-r--r--build/build-clang/disable-mac-tsan.patch11
-rw-r--r--build/build-clang/llvm-debug-frame.patch13
-rw-r--r--build/build-clang/query-selector-visibility.patch79
-rw-r--r--build/build-clang/return-empty-string-non-mangled.patch19
10 files changed, 683 insertions, 0 deletions
diff --git a/build/build-clang/README b/build/build-clang/README
new file mode 100644
index 000000000..8e93eeaa6
--- /dev/null
+++ b/build/build-clang/README
@@ -0,0 +1,45 @@
+build-clang.py
+==============
+
+A script to build clang from source.
+
+```
+usage: build-clang.py [-h] -c CONFIG [--clean]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -c CONFIG, --config CONFIG
+ Clang configuration file
+ --clean Clean the build directory
+```
+
+Pre-requisites
+--------------
+* Working build toolchain.
+* Subversion
+* CMake
+* Ninja
+* Python 2.7
+
+Please use the latest available CMake for your platform to avoid surprises.
+
+Config file format
+------------------
+
+build-clang.py accepts a JSON config format with the following fields:
+
+* llvm_revision: The LLVM SVN revision to build.
+* stages: Use 1, 2, or 3 to select different compiler stages. The default is 3.
+* llvm_repo: SVN path to the LLVM repo.
+* clang_repo: SVN path to the Clang repo.
+* compiler_repo: SVN path to the compiler-rt repo.
+* libcxx_repo: SVN path to the libcxx repo.
+* libcxxabi_repo: SVN path to the libcxxabi repo.
+* python_path: Path to the Python 2.7 installation on the machine building clang.
+* gcc_dir: Path to the gcc toolchain installation, only required on Linux.
+* cc: Path to the bootsraping C Compiler.
+* cxx: Path to the bootsraping C++ Compiler.
+* patches: Optional list of patches to apply per platform. Supported platforms: macosx64, linux32, linux64. The default is Release.
+* build_type: The type of build to make. Supported types: Release, Debug, RelWithDebInfo or MinSizeRel.
+* build_libcxx: Whether to build with libcxx. The default is false.
+* assertions: Whether to enable LLVM assertions. The default is false.
diff --git a/build/build-clang/build-clang.py b/build/build-clang/build-clang.py
new file mode 100755
index 000000000..697bbb9b8
--- /dev/null
+++ b/build/build-clang/build-clang.py
@@ -0,0 +1,425 @@
+#!/usr/bin/python2.7
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import os.path
+import shutil
+import subprocess
+import platform
+import json
+import argparse
+import tempfile
+import glob
+import errno
+import re
+from contextlib import contextmanager
+import sys
+import which
+
+DEBUG = os.getenv("DEBUG")
+
+
+def symlink(source, link_name):
+ os_symlink = getattr(os, "symlink", None)
+ if callable(os_symlink):
+ os_symlink(source, link_name)
+ else:
+ if os.path.isdir(source):
+ # Fall back to copying the directory :(
+ copy_dir_contents(source, link_name)
+
+
+def check_run(args):
+ global DEBUG
+ if DEBUG:
+ print >> sys.stderr, ' '.join(args)
+ r = subprocess.call(args)
+ assert r == 0
+
+
+def run_in(path, args):
+ d = os.getcwd()
+ global DEBUG
+ if DEBUG:
+ print >> sys.stderr, 'cd "%s"' % path
+ os.chdir(path)
+ check_run(args)
+ if DEBUG:
+ print >> sys.stderr, 'cd "%s"' % d
+ os.chdir(d)
+
+
+def patch(patch, srcdir):
+ patch = os.path.realpath(patch)
+ check_run(['patch', '-d', srcdir, '-p1', '-i', patch, '--fuzz=0',
+ '-s'])
+
+
+def build_package(package_build_dir, run_cmake, cmake_args):
+ if not os.path.exists(package_build_dir):
+ os.mkdir(package_build_dir)
+ if run_cmake:
+ run_in(package_build_dir, ["cmake"] + cmake_args)
+ run_in(package_build_dir, ["ninja", "install"])
+
+
+@contextmanager
+def updated_env(env):
+ old_env = os.environ.copy()
+ os.environ.update(env)
+ yield
+ os.environ.clear()
+ os.environ.update(old_env)
+
+
+def build_tar_package(tar, name, base, directory):
+ name = os.path.realpath(name)
+ # On Windows, we have to convert this into an msys path so that tar can
+ # understand it.
+ if is_windows():
+ name = name.replace('\\', '/')
+ def f(match):
+ return '/' + match.group(1).lower()
+ name = re.sub(r'^([A-Z]):', f, name)
+ run_in(base, [tar,
+ "-c",
+ "-%s" % ("J" if ".xz" in name else "j"),
+ "-f",
+ name, directory])
+
+
+def copy_dir_contents(src, dest):
+ for f in glob.glob("%s/*" % src):
+ try:
+ destname = "%s/%s" % (dest, os.path.basename(f))
+ if os.path.isdir(f):
+ shutil.copytree(f, destname)
+ else:
+ shutil.copy2(f, destname)
+ except OSError as e:
+ if e.errno == errno.ENOTDIR:
+ shutil.copy2(f, destname)
+ elif e.errno == errno.EEXIST:
+ if os.path.isdir(f):
+ copy_dir_contents(f, destname)
+ else:
+ os.remove(destname)
+ shutil.copy2(f, destname)
+ else:
+ raise Exception('Directory not copied. Error: %s' % e)
+
+
+def mkdir_p(path):
+ try:
+ os.makedirs(path)
+ except OSError as e:
+ if e.errno != errno.EEXIST or not os.path.isdir(path):
+ raise
+
+
+def install_libgcc(gcc_dir, clang_dir):
+ out = subprocess.check_output([os.path.join(gcc_dir, "bin", "gcc"),
+ '-print-libgcc-file-name'])
+
+ libgcc_dir = os.path.dirname(out.rstrip())
+ clang_lib_dir = os.path.join(clang_dir, "lib", "gcc",
+ "x86_64-unknown-linux-gnu",
+ os.path.basename(libgcc_dir))
+ mkdir_p(clang_lib_dir)
+ copy_dir_contents(libgcc_dir, clang_lib_dir)
+ libgcc_dir = os.path.join(gcc_dir, "lib64")
+ clang_lib_dir = os.path.join(clang_dir, "lib")
+ copy_dir_contents(libgcc_dir, clang_lib_dir)
+ include_dir = os.path.join(gcc_dir, "include")
+ clang_include_dir = os.path.join(clang_dir, "include")
+ copy_dir_contents(include_dir, clang_include_dir)
+
+
+def svn_co(source_dir, url, directory, revision):
+ run_in(source_dir, ["svn", "co", "-q", "-r", revision, url, directory])
+
+
+def svn_update(directory, revision):
+ run_in(directory, ["svn", "update", "-q", "-r", revision])
+
+
+def get_platform():
+ p = platform.system()
+ if p == "Darwin":
+ return "macosx64"
+ elif p == "Linux":
+ if platform.architecture() == "AMD64":
+ return "linux64"
+ else:
+ return "linux32"
+ elif p == "Windows":
+ if platform.architecture() == "AMD64":
+ return "win64"
+ else:
+ return "win32"
+ else:
+ raise NotImplementedError("Not supported platform")
+
+
+def is_darwin():
+ return platform.system() == "Darwin"
+
+
+def is_linux():
+ return platform.system() == "Linux"
+
+
+def is_windows():
+ return platform.system() == "Windows"
+
+
+def build_one_stage(cc, cxx, src_dir, stage_dir, build_libcxx,
+ build_type, assertions, python_path, gcc_dir):
+ if not os.path.exists(stage_dir):
+ os.mkdir(stage_dir)
+
+ build_dir = stage_dir + "/build"
+ inst_dir = stage_dir + "/clang"
+
+ run_cmake = True
+ if os.path.exists(build_dir + "/build.ninja"):
+ run_cmake = False
+
+ # cmake doesn't deal well with backslashes in paths.
+ def slashify_path(path):
+ return path.replace('\\', '/')
+
+ cmake_args = ["-GNinja",
+ "-DCMAKE_C_COMPILER=%s" % slashify_path(cc[0]),
+ "-DCMAKE_CXX_COMPILER=%s" % slashify_path(cxx[0]),
+ "-DCMAKE_ASM_COMPILER=%s" % slashify_path(cc[0]),
+ "-DCMAKE_C_FLAGS=%s" % ' '.join(cc[1:]),
+ "-DCMAKE_CXX_FLAGS=%s" % ' '.join(cxx[1:]),
+ "-DCMAKE_BUILD_TYPE=%s" % build_type,
+ "-DLLVM_TARGETS_TO_BUILD=X86;ARM",
+ "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions else "OFF"),
+ "-DPYTHON_EXECUTABLE=%s" % slashify_path(python_path),
+ "-DCMAKE_INSTALL_PREFIX=%s" % inst_dir,
+ "-DLLVM_TOOL_LIBCXX_BUILD=%s" % ("ON" if build_libcxx else "OFF"),
+ "-DLIBCXX_LIBCPPABI_VERSION=\"\"",
+ src_dir];
+ build_package(build_dir, run_cmake, cmake_args)
+
+ if is_linux():
+ install_libgcc(gcc_dir, inst_dir)
+
+
+def get_compiler(config, key):
+ if key not in config:
+ raise ValueError("Config file needs to set %s" % key)
+
+ f = config[key]
+ if os.path.isabs(f):
+ if not os.path.exists(f):
+ raise ValueError("%s must point to an existing path" % key)
+ return f
+
+ # Assume that we have the name of some program that should be on PATH.
+ try:
+ return which.which(f)
+ except which.WhichError:
+ raise ValueError("%s not found on PATH" % f)
+
+if __name__ == "__main__":
+ # The directories end up in the debug info, so the easy way of getting
+ # a reproducible build is to run it in a know absolute directory.
+ # We use a directory in /builds/slave because the mozilla infrastructure
+ # cleans it up automatically.
+ base_dir = "/builds/slave/moz-toolchain"
+ if is_windows():
+ # TODO: Because Windows taskcluster builds are run with distinct
+ # user IDs for each job, we can't store things in some globally
+ # accessible directory: one job will run, checkout LLVM to that
+ # directory, and then if another job runs, the new user won't be
+ # able to access the previously-checked out code--or be able to
+ # delete it. So on Windows, we build in the task-specific home
+ # directory; we will eventually add -fdebug-prefix-map options
+ # to the LLVM build to bring back reproducibility.
+ base_dir = os.path.join(os.getcwd(), 'llvm-sources')
+
+ source_dir = base_dir + "/src"
+ build_dir = base_dir + "/build"
+
+ llvm_source_dir = source_dir + "/llvm"
+ clang_source_dir = source_dir + "/clang"
+ compiler_rt_source_dir = source_dir + "/compiler-rt"
+ libcxx_source_dir = source_dir + "/libcxx"
+ libcxxabi_source_dir = source_dir + "/libcxxabi"
+
+ if is_darwin():
+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
+
+ exe_ext = ""
+ if is_windows():
+ exe_ext = ".exe"
+
+ cc_name = "clang"
+ cxx_name = "clang++"
+ if is_windows():
+ cc_name = "clang-cl"
+ cxx_name = "clang-cl"
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-c', '--config', required=True,
+ type=argparse.FileType('r'),
+ help="Clang configuration file")
+ parser.add_argument('--clean', required=False,
+ action='store_true',
+ help="Clean the build directory")
+
+ args = parser.parse_args()
+ config = json.load(args.config)
+
+ if args.clean:
+ shutil.rmtree(build_dir)
+ os.sys.exit(0)
+
+ llvm_revision = config["llvm_revision"]
+ llvm_repo = config["llvm_repo"]
+ clang_repo = config["clang_repo"]
+ compiler_repo = config["compiler_repo"]
+ libcxx_repo = config["libcxx_repo"]
+ libcxxabi_repo = config.get("libcxxabi_repo")
+ stages = 3
+ if "stages" in config:
+ stages = int(config["stages"])
+ if stages not in (1, 2, 3):
+ raise ValueError("We only know how to build 1, 2, or 3 stages")
+ build_type = "Release"
+ if "build_type" in config:
+ build_type = config["build_type"]
+ if build_type not in ("Release", "Debug", "RelWithDebInfo", "MinSizeRel"):
+ raise ValueError("We only know how to do Release, Debug, RelWithDebInfo or MinSizeRel builds")
+ build_libcxx = False
+ if "build_libcxx" in config:
+ build_libcxx = config["build_libcxx"]
+ if build_libcxx not in (True, False):
+ raise ValueError("Only boolean values are accepted for build_libcxx.")
+ assertions = False
+ if "assertions" in config:
+ assertions = config["assertions"]
+ if assertions not in (True, False):
+ raise ValueError("Only boolean values are accepted for assertions.")
+ python_path = None
+ if "python_path" not in config:
+ raise ValueError("Config file needs to set python_path")
+ python_path = config["python_path"]
+ gcc_dir = None
+ if "gcc_dir" in config:
+ gcc_dir = config["gcc_dir"]
+ if not os.path.exists(gcc_dir):
+ raise ValueError("gcc_dir must point to an existing path")
+ if is_linux() and gcc_dir is None:
+ raise ValueError("Config file needs to set gcc_dir")
+ cc = get_compiler(config, "cc")
+ cxx = get_compiler(config, "cxx")
+
+ if not os.path.exists(source_dir):
+ os.makedirs(source_dir)
+ svn_co(source_dir, llvm_repo, llvm_source_dir, llvm_revision)
+ svn_co(source_dir, clang_repo, clang_source_dir, llvm_revision)
+ svn_co(source_dir, compiler_repo, compiler_rt_source_dir, llvm_revision)
+ svn_co(source_dir, libcxx_repo, libcxx_source_dir, llvm_revision)
+ if libcxxabi_repo:
+ svn_co(source_dir, libcxxabi_repo, libcxxabi_source_dir, llvm_revision)
+ for p in config.get("patches", {}).get(get_platform(), []):
+ patch(p, source_dir)
+ else:
+ svn_update(llvm_source_dir, llvm_revision)
+ svn_update(clang_source_dir, llvm_revision)
+ svn_update(compiler_rt_source_dir, llvm_revision)
+ svn_update(libcxx_source_dir, llvm_revision)
+ if libcxxabi_repo:
+ svn_update(libcxxabi_source_dir, llvm_revision)
+
+ symlinks = [(source_dir + "/clang",
+ llvm_source_dir + "/tools/clang"),
+ (source_dir + "/compiler-rt",
+ llvm_source_dir + "/projects/compiler-rt"),
+ (source_dir + "/libcxx",
+ llvm_source_dir + "/projects/libcxx"),
+ (source_dir + "/libcxxabi",
+ llvm_source_dir + "/projects/libcxxabi")]
+ for l in symlinks:
+ # On Windows, we have to re-copy the whole directory every time.
+ if not is_windows() and os.path.islink(l[1]):
+ continue
+ if os.path.isdir(l[1]):
+ shutil.rmtree(l[1])
+ elif os.path.exists(l[1]):
+ os.unlink(l[1])
+ if os.path.exists(l[0]):
+ symlink(l[0], l[1])
+
+ if not os.path.exists(build_dir):
+ os.makedirs(build_dir)
+
+ stage1_dir = build_dir + '/stage1'
+ stage1_inst_dir = stage1_dir + '/clang'
+
+ final_stage_dir = stage1_dir
+
+ if is_darwin():
+ extra_cflags = []
+ extra_cxxflags = ["-stdlib=libc++"]
+ extra_cflags2 = []
+ extra_cxxflags2 = ["-stdlib=libc++"]
+ elif is_linux():
+ extra_cflags = ["-static-libgcc"]
+ extra_cxxflags = ["-static-libgcc", "-static-libstdc++"]
+ extra_cflags2 = ["-fPIC"]
+ extra_cxxflags2 = ["-fPIC", "-static-libstdc++"]
+
+ if os.environ.has_key('LD_LIBRARY_PATH'):
+ os.environ['LD_LIBRARY_PATH'] = '%s/lib64/:%s' % (gcc_dir, os.environ['LD_LIBRARY_PATH']);
+ else:
+ os.environ['LD_LIBRARY_PATH'] = '%s/lib64/' % gcc_dir
+ elif is_windows():
+ extra_cflags = []
+ extra_cxxflags = []
+ # clang-cl would like to figure out what it's supposed to be emulating
+ # by looking at an MSVC install, but we don't really have that here.
+ # Force things on.
+ extra_cflags2 = []
+ extra_cxxflags2 = ['-fms-compatibility-version=19.00.24213', '-Xclang', '-std=c++14']
+
+ build_one_stage(
+ [cc] + extra_cflags,
+ [cxx] + extra_cxxflags,
+ llvm_source_dir, stage1_dir, build_libcxx,
+ build_type, assertions, python_path, gcc_dir)
+
+ if stages > 1:
+ stage2_dir = build_dir + '/stage2'
+ stage2_inst_dir = stage2_dir + '/clang'
+ final_stage_dir = stage2_dir
+ build_one_stage(
+ [stage1_inst_dir + "/bin/%s%s" %
+ (cc_name, exe_ext)] + extra_cflags2,
+ [stage1_inst_dir + "/bin/%s%s" %
+ (cxx_name, exe_ext)] + extra_cxxflags2,
+ llvm_source_dir, stage2_dir, build_libcxx,
+ build_type, assertions, python_path, gcc_dir)
+
+ if stages > 2:
+ stage3_dir = build_dir + '/stage3'
+ final_stage_dir = stage3_dir
+ build_one_stage(
+ [stage2_inst_dir + "/bin/%s%s" %
+ (cc_name, exe_ext)] + extra_cflags2,
+ [stage2_inst_dir + "/bin/%s%s" %
+ (cxx_name, exe_ext)] + extra_cxxflags2,
+ llvm_source_dir, stage3_dir, build_libcxx,
+ build_type, assertions, python_path, gcc_dir)
+
+ if is_darwin() or is_windows():
+ build_tar_package("tar", "clang.tar.bz2", final_stage_dir, "clang")
+ else:
+ build_tar_package("tar", "clang.tar.xz", final_stage_dir, "clang")
diff --git a/build/build-clang/clang-static-analysis-linux64.json b/build/build-clang/clang-static-analysis-linux64.json
new file mode 100644
index 000000000..d3ae6c8ad
--- /dev/null
+++ b/build/build-clang/clang-static-analysis-linux64.json
@@ -0,0 +1,30 @@
+{
+ "llvm_revision": "262557",
+ "stages": "3",
+ "build_libcxx": true,
+ "build_type": "Release",
+ "assertions": false,
+ "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_380/final",
+ "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_380/final",
+ "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_380/final",
+ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_380/final",
+ "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_380/final",
+ "python_path": "/usr/bin/python2.7",
+ "gcc_dir": "/home/worker/workspace/build/src/gcc",
+ "cc": "/home/worker/workspace/build/src/gcc/bin/gcc",
+ "cxx": "/home/worker/workspace/build/src/gcc/bin/g++",
+ "patches": {
+ "macosx64": [
+ "llvm-debug-frame.patch",
+ "return-empty-string-non-mangled.patch"
+ ],
+ "linux64": [
+ "llvm-debug-frame.patch",
+ "return-empty-string-non-mangled.patch"
+ ],
+ "linux32": [
+ "llvm-debug-frame.patch",
+ "return-empty-string-non-mangled.patch"
+ ]
+ }
+}
diff --git a/build/build-clang/clang-static-analysis-macosx64.json b/build/build-clang/clang-static-analysis-macosx64.json
new file mode 100644
index 000000000..16818825b
--- /dev/null
+++ b/build/build-clang/clang-static-analysis-macosx64.json
@@ -0,0 +1,29 @@
+{
+ "llvm_revision": "262557",
+ "stages": "3",
+ "build_libcxx": true,
+ "build_type": "Release",
+ "assertions": false,
+ "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_380/final",
+ "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_380/final",
+ "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_380/final",
+ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_380/final",
+ "python_path": "/usr/local/bin/python2.7",
+ "cc": "/Users/cltbld/clang/bin/clang",
+ "cxx": "/Users/cltbld/clang/bin/clang++",
+ "patches": {
+ "macosx64": [
+ "disable-mac-tsan.patch",
+ "llvm-debug-frame.patch",
+ "return-empty-string-non-mangled.patch"
+ ],
+ "linux64": [
+ "llvm-debug-frame.patch",
+ "return-empty-string-non-mangled.patch"
+ ],
+ "linux32": [
+ "llvm-debug-frame.patch",
+ "return-empty-string-non-mangled.patch"
+ ]
+ }
+}
diff --git a/build/build-clang/clang-static-analysis-win32.json b/build/build-clang/clang-static-analysis-win32.json
new file mode 100644
index 000000000..01cddad85
--- /dev/null
+++ b/build/build-clang/clang-static-analysis-win32.json
@@ -0,0 +1,16 @@
+{
+ "llvm_revision": "283955",
+ "stages": "3",
+ "build_libcxx": false,
+ "build_type": "Release",
+ "assertions": false,
+ "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
+ "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
+ "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
+ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
+ "python_path": "c:/mozilla-build/python/python.exe",
+ "cc": "cl.exe",
+ "cxx": "cl.exe",
+ "patches": {
+ }
+}
diff --git a/build/build-clang/clang-static-analysis-win64.json b/build/build-clang/clang-static-analysis-win64.json
new file mode 100644
index 000000000..cf626f05e
--- /dev/null
+++ b/build/build-clang/clang-static-analysis-win64.json
@@ -0,0 +1,16 @@
+{
+ "llvm_revision": "262971",
+ "stages": "3",
+ "build_libcxx": false,
+ "build_type": "Release",
+ "assertions": false,
+ "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
+ "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
+ "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
+ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
+ "python_path": "c:/mozilla-build/python/python.exe",
+ "cc": "c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64/cl.exe",
+ "cxx": "c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64/cl.exe",
+ "patches": {
+ }
+}
diff --git a/build/build-clang/disable-mac-tsan.patch b/build/build-clang/disable-mac-tsan.patch
new file mode 100644
index 000000000..3bd0d3c60
--- /dev/null
+++ b/build/build-clang/disable-mac-tsan.patch
@@ -0,0 +1,11 @@
+--- a/compiler-rt/cmake/config-ix.cmake
++++ b/compiler-rt/cmake/config-ix.cmake
+@@ -617,7 +617,7 @@
+ endif()
+
+ if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
+- OS_NAME MATCHES "Darwin|Linux|FreeBSD")
++ OS_NAME MATCHES "Linux|FreeBSD")
+ set(COMPILER_RT_HAS_TSAN TRUE)
+ else()
+ set(COMPILER_RT_HAS_TSAN FALSE)
diff --git a/build/build-clang/llvm-debug-frame.patch b/build/build-clang/llvm-debug-frame.patch
new file mode 100644
index 000000000..a8c57ce6f
--- /dev/null
+++ b/build/build-clang/llvm-debug-frame.patch
@@ -0,0 +1,13 @@
+Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+===================================================================
+--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (revision 226419)
++++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (working copy)
+@@ -210,6 +210,8 @@
+ OutStreamer->EmitFileDirective(M.getModuleIdentifier());
+ }
+
++ OutStreamer->EmitCFISections(true, true);
++
+ GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
+ assert(MI && "AsmPrinter didn't require GCModuleInfo?");
+ for (auto &I : *MI)
diff --git a/build/build-clang/query-selector-visibility.patch b/build/build-clang/query-selector-visibility.patch
new file mode 100644
index 000000000..46a9642bd
--- /dev/null
+++ b/build/build-clang/query-selector-visibility.patch
@@ -0,0 +1,79 @@
+commit 865b9340996f9f9d04b73b187248737dc6fd845e
+Author: Michael Wu <mwu@mozilla.com>
+Date: Mon Sep 14 17:47:21 2015 -0400
+
+ Add support for querying the visibility of a cursor
+
+diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
+index fad9cfa..311bfcb 100644
+--- a/clang/include/clang-c/Index.h
++++ b/clang/include/clang-c/Index.h
+@@ -2440,6 +2440,24 @@ enum CXLinkageKind {
+ CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
+
+ /**
++ * \brief Describe the visibility of the entity referred to by a cursor.
++ */
++enum CXVisibilityKind {
++ /** \brief This value indicates that no visibility information is available
++ * for a provided CXCursor. */
++ CXVisibility_Invalid,
++
++ /** \brief Symbol not seen by the linker. */
++ CXVisibility_Hidden,
++ /** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
++ CXVisibility_Protected,
++ /** \brief Symbol seen by the linker and acts like a normal symbol. */
++ CXVisibility_Default,
++};
++
++CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
++
++/**
+ * \brief Determine the availability of the entity that this cursor refers to,
+ * taking the current target platform into account.
+ *
+diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
+index 8225a6c..9fa18d3 100644
+--- a/clang/tools/libclang/CIndex.cpp
++++ b/clang/tools/libclang/CIndex.cpp
+@@ -6361,6 +6361,27 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
+ } // end: extern "C"
+
+ //===----------------------------------------------------------------------===//
++// Operations for querying visibility of a cursor.
++//===----------------------------------------------------------------------===//
++
++extern "C" {
++CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
++ if (!clang_isDeclaration(cursor.kind))
++ return CXVisibility_Invalid;
++
++ const Decl *D = cxcursor::getCursorDecl(cursor);
++ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
++ switch (ND->getVisibility()) {
++ case HiddenVisibility: return CXVisibility_Hidden;
++ case ProtectedVisibility: return CXVisibility_Protected;
++ case DefaultVisibility: return CXVisibility_Default;
++ };
++
++ return CXVisibility_Invalid;
++}
++} // end: extern "C"
++
++//===----------------------------------------------------------------------===//
+ // Operations for querying language of a cursor.
+ //===----------------------------------------------------------------------===//
+
+diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
+index f6a7175..a919a8e 100644
+--- a/clang/tools/libclang/libclang.exports
++++ b/clang/tools/libclang/libclang.exports
+@@ -173,6 +173,7 @@ clang_getCursorSemanticParent
+ clang_getCursorSpelling
+ clang_getCursorType
+ clang_getCursorUSR
++clang_getCursorVisibility
+ clang_getDeclObjCTypeEncoding
+ clang_getDefinitionSpellingAndExtent
+ clang_getDiagnostic
diff --git a/build/build-clang/return-empty-string-non-mangled.patch b/build/build-clang/return-empty-string-non-mangled.patch
new file mode 100644
index 000000000..33a391703
--- /dev/null
+++ b/build/build-clang/return-empty-string-non-mangled.patch
@@ -0,0 +1,19 @@
+Author: Michael Wu <mwu@mozilla.com>
+Date: Thu Sep 24 11:36:08 2015 -0400
+
+ Return an empty string when a symbol isn't mangled
+
+diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
+--- a/clang/tools/libclang/CIndex.cpp
++++ b/clang/tools/libclang/CIndex.cpp
+@@ -3990,6 +3990,10 @@
+ ASTContext &Ctx = ND->getASTContext();
+ std::unique_ptr<MangleContext> MC(Ctx.createMangleContext());
+
++ // Don't mangle if we don't need to.
++ if (!MC->shouldMangleCXXName(ND))
++ return cxstring::createEmpty();
++
+ std::string FrontendBuf;
+ llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
+ if (MC->shouldMangleDeclName(ND)) {