Bug 1451104 - part 3 - inform stage2/3 clang about gcc binutils; r=glandium
authorNathan Froyd <froydnj@gmail.com>
Fri, 15 Mar 2019 01:29:04 +0000
changeset 524992 f3290e95b38d23973b31b5bcb8d811fe253cedbc
parent 524991 961ac7318786c56eeb21975fb77eb97ef790c51b
child 524993 292ed1bb9143e7853110e9a7574c168ae3780932
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1451104 - part 3 - inform stage2/3 clang about gcc binutils; r=glandium We do this to encourage clang to find an new-enough linker instead of the system one. Differential Revision: https://phabricator.services.mozilla.com/D22881
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -115,18 +115,33 @@ def delete(path):
         except Exception:
-def install_libgcc(gcc_dir, clang_dir):
-    out = subprocess.check_output([os.path.join(gcc_dir, "bin", "gcc"),
+def install_libgcc(gcc_dir, clang_dir, is_final_stage):
+    gcc_bin_dir = os.path.join(gcc_dir, 'bin')
+    # Copy over gcc toolchain bits that clang looks for, to ensure that
+    # clang is using a consistent version of ld, since the system ld may
+    # be incompatible with the output clang produces.  But copy it to a
+    # target-specific directory so a cross-compiler to Mac doesn't pick
+    # up the (Linux-specific) ld with disastrous results.
+    #
+    # Only install this for the bootstrap process; we expect any consumers of
+    # the newly-built toolchain to provide an appropriate ld themselves.
+    if not is_final_stage:
+        x64_bin_dir = os.path.join(clang_dir, 'x86_64-unknown-linux-gnu', 'bin')
+        mkdir_p(x64_bin_dir)
+        shutil.copy2(os.path.join(gcc_bin_dir, 'ld'), x64_bin_dir)
+    out = subprocess.check_output([os.path.join(gcc_bin_dir, "gcc"),
     libgcc_dir = os.path.dirname(out.rstrip())
     clang_lib_dir = os.path.join(clang_dir, "lib", "gcc",
     copy_tree(libgcc_dir, clang_lib_dir)
@@ -304,17 +319,17 @@ def build_one_stage(cc, cxx, asm, ld, ar
     cmake_args += cmake_base_args(
         cc, cxx, asm, ld, ar, ranlib, libtool, inst_dir)
     cmake_args += [
     build_package(build_dir, cmake_args)
     if is_linux():
-        install_libgcc(gcc_dir, inst_dir)
+        install_libgcc(gcc_dir, inst_dir, is_final_stage)
     # For some reasons the import library clang.lib of clang.exe is not
     # installed, so we copy it by ourselves.
     if is_windows():
         # The compiler-rt cmake scripts don't allow to build it for multiple
         # targets at once on Windows, so manually build the 32-bits compiler-rt
         # during the final stage.
         build_32_bit = False
         if is_final_stage:
@@ -400,33 +415,39 @@ def get_tool(config, key):
 #           * (nothing will be deleted here)
 #   share/
 #     clang/
 #       clang-format-diff.py
 #       clang-tidy-diff.py
 #       run-clang-tidy.py
 def prune_final_dir_for_clang_tidy(final_dir, osx_cross_compile):
     # Make sure we only have what we expect.
-    dirs = ("bin", "include", "lib", "lib32", "libexec", "msbuild-bin", "share", "tools")
+    dirs = ["bin", "include", "lib", "lib32", "libexec", "msbuild-bin", "share", "tools"]
+    if is_linux():
+        dirs.append("x86_64-unknown-linux-gnu")
     for f in glob.glob("%s/*" % final_dir):
         if os.path.basename(f) not in dirs:
             raise Exception("Found unknown file %s in the final directory" % f)
         if not os.path.isdir(f):
             raise Exception("Expected %s to be a directory" % f)
     # In bin/, only keep clang-tidy and clang-apply-replacements. The last one
     # is used to auto-fix some of the issues detected by clang-tidy.
     re_clang_tidy = re.compile(
         r"^clang-(apply-replacements|format|tidy)(\.exe)?$", re.I)
     for f in glob.glob("%s/bin/*" % final_dir):
         if re_clang_tidy.search(os.path.basename(f)) is None:
     # Keep include/ intact.
+    # Remove the target-specific files.
+    if is_linux():
+        shutil.rmtree(os.path.join(final_dir, "x86_64-unknown-linux-gnu"))
     # In lib/, only keep lib/clang/N.M.O/include and the LLVM shared library.
     re_ver_num = re.compile(r"^\d+\.\d+\.\d+$", re.I)
     for f in glob.glob("%s/lib/*" % final_dir):
         name = os.path.basename(f)
         if name == "clang":
         if osx_cross_compile and name == 'libLLVM.dylib':