Fix wrapper shell scripts and symlinks for invoking clang++
In a typical installation, clang++ symlinks to clang, which symlinks to the
elf executable. The executable distinguishes between clang and clang++ based
on argv[0].
When invoked through the LdsoWrapper, argv[0] always contains the path to the
executable elf file, making clang/clang++ invocations indistinguishable.
This CL adjusts the symlinks and wrappers so clang++ invocation works correctly.
BUG=chromium:628524
TEST='cros_setup_toolchains --create-packages -t x86_64-cros-linux-gnu'
TEST=Used x86_64-cros-linux-gnu.tar.xz to successfully build chrome for panther (simple-chrome).
TEST='cros_setup_toolchains --create-packages -t i686-pc-linux-gnu'
TEST=Used i686-pc-linux-gnu.tar.xz to successfully build chrome for x86-zgb (simple-chrome).
TEST='cros_setup_toolchains --create-packages -t armv7a-cros-linux-gnueabi'
TEST=Used armv7a-cros-linux-gnueabi.tar.xz to successfully build chrome for daisy (simple-chrome).
Change-Id: Id2ecb65b99226b65a3da4197c09eda28c5fdefca
Reviewed-on: https://chromium-review.googlesource.com/362682
Commit-Ready: Luis Lozano <llozano@chromium.org>
Tested-by: Luis Lozano <llozano@chromium.org>
Reviewed-by: Luis Lozano <llozano@chromium.org>
diff --git a/scripts/cros_setup_toolchains.py b/scripts/cros_setup_toolchains.py
index 4590831..2bbf21c 100644
--- a/scripts/cros_setup_toolchains.py
+++ b/scripts/cros_setup_toolchains.py
@@ -10,6 +10,7 @@
import glob
import json
import os
+import re
from chromite.cbuildbot import constants
from chromite.lib import commandline
@@ -700,6 +701,48 @@
os.chmod(root_wrapper, 0o755)
+def FixClangXXWrapper(root, path):
+ """Fix wrapper shell scripts and symlinks for invoking clang++
+
+ In a typical installation, clang++ symlinks to clang, which symlinks to the
+ elf executable. The executable distinguishes between clang and clang++ based
+ on argv[0].
+
+ When invoked through the LdsoWrapper, argv[0] always contains the path to the
+ executable elf file, making clang/clang++ invocations indistinguishable.
+
+ This function detects if the elf executable being wrapped is clang-X.Y, and
+ fixes wrappers/symlinks as necessary so that clang++ will work correctly.
+
+ The calling sequence now becomes:
+ -) clang++ invocation turns into clang++-3.9 (which is a copy of clang-3.9,
+ the Ldsowrapper).
+ -) clang++-3.9 uses the Ldso to invoke clang++-3.9.elf, which is a symlink
+ to the original clang-3.9 elf.
+ -) The difference this time is that inside the elf file execution, $0 is
+ set as .../usr/bin/clang++-3.9.elf, which contains 'clang++' in the name.
+
+ Args:
+ root: The root tree to generate scripts / symlinks inside of
+ path: The target elf for which LdsoWrapper was created
+ """
+ if re.match(r'/usr/bin/clang-\d+\.\d+$', path):
+ logging.info('fixing clang++ invocation for %s', path)
+ clangdir = os.path.dirname(root + path)
+ clang = os.path.basename(path)
+ clangxx = clang.replace('clang', 'clang++')
+
+ # Create a symlink clang++-X.Y.elf to point to clang-X.Y.elf
+ os.symlink(clang + '.elf', os.path.join(clangdir, clangxx + '.elf'))
+
+ # Create a hardlink clang++-X.Y pointing to clang-X.Y
+ os.link(os.path.join(clangdir, clang), os.path.join(clangdir, clangxx))
+
+ # Adjust the clang++ symlink to point to clang++-X.Y
+ os.unlink(os.path.join(clangdir, 'clang++'))
+ os.symlink(clangxx, os.path.join(clangdir, 'clang++'))
+
+
def FileIsCrosSdkElf(elf):
"""Determine if |elf| is an ELF that we execute in the cros_sdk
@@ -877,6 +920,7 @@
interp = os.path.join('/lib', os.path.basename(interp))
lddtree.GenerateLdsoWrapper(output_dir, path_rewrite_func(elf), interp,
libpaths=e['rpath'] + e['runpath'])
+ FixClangXXWrapper(output_dir, path_rewrite_func(elf))
for lib, lib_data in e['libs'].iteritems():
if lib in donelibs: