Skip to content

Unwrap clang using clang version #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions refresh.template.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ def _get_files(compile_args: typing.List[str]):
}
_get_files.extensions_to_language_args = {ext : flag for exts, flag in _get_files.extensions_to_language_args.items() for ext in exts} # Flatten map for easier use

@functools.lru_cache(maxsize=None)
def _get_underlying_clang(compiler_command):
"""Get install path from clang version."""
workspace_root = pathlib.Path(os.environ["BUILD_WORKSPACE_DIRECTORY"]) # Set by `bazel run`
# The final line of the clang version contains the install directory for the underlying clang.
install_dir = pathlib.Path(subprocess.check_output((workspace_root/compiler_command, '-v'), stderr=subprocess.STDOUT, encoding='utf-8').rstrip().split("\n")[-1].split(" ", 1)[-1])
return str(install_dir/"clang")

@functools.lru_cache(maxsize=None)
def _get_apple_SDKROOT(SDK_name: str):
Expand Down Expand Up @@ -187,27 +194,19 @@ def _get_apple_DEVELOPER_DIR():
# Unless xcode-select has been invoked (like for a beta) we'd expect '/Applications/Xcode.app/Contents/Developer' from xcode-select -p
# Traditionally stored in DEVELOPER_DIR environment variable, but not provided.


@functools.lru_cache(maxsize=None)
def _get_apple_active_clang():
"""Get path to xcode-select'd clang version."""
return subprocess.check_output(('xcrun', '--find', 'clang'), encoding='utf-8').rstrip()
# Unless xcode-select has been invoked (like for a beta) we'd expect '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang' from xcrun -f clang


def _apple_platform_patch(compile_args: typing.List[str]):
"""De-Bazel the command into something clangd can parse.

This function has fixes specific to Apple platforms, but you should call it on all platforms. It'll determine whether the fixes should be applied or not.
"""
compile_args = list(compile_args)
# Bazel internal environment variable fragment that distinguishes Apple platforms that need unwrapping.
# Note that this occurs in the Xcode-installed wrapper, but not the CommandLineTools wrapper, which works fine as is.
# Note that this occurs in the Xcode-installed wrapper, but not the CommandLineTools wrapper, which works fine as is.
if any('__BAZEL_XCODE_' in arg for arg in compile_args):
# Undo Bazel's Apple platform compiler wrapping.
# Bazel wraps the compiler as `external/local_config_cc/wrapped_clang` and exports that wrapped compiler in the proto. However, we need a clang call that clangd can introspect. (See notes in "how clangd uses compile_commands.json" in ImplementationReadme.md for more.)
# Removing the wrapper is also important because Bazel's Xcode (but not CommandLineTools) wrapper crashes if you don't specify particular environment variables (replaced below). We'd need the wrapper to be invokable by clangd's --query-driver if we didn't remove the wrapper.
compile_args[0] = _get_apple_active_clang()
compile_args[0] = _get_underlying_clang(compile_args[0])

# We have to manually substitute out Bazel's macros so clang can parse the command
# Code this mirrors is in https://github.com/bazelbuild/bazel/blob/master/tools/osx/crosstool/wrapped_clang.cc
Expand All @@ -222,9 +221,9 @@ def _apple_platform_patch(compile_args: typing.List[str]):

return compile_args


def _all_platform_patch(compile_args: typing.List[str]):
"""Apply de-Bazeling fixes to the compile command that are shared across target platforms."""

# clangd writes module cache files to the wrong place
# Without this fix, you get tons of module caches dumped into the VSCode root folder.
# Filed clangd issue at: https://github.com/clangd/clangd/issues/655
Expand All @@ -236,9 +235,15 @@ def _all_platform_patch(compile_args: typing.List[str]):
# For more context see: https://github.com/hedronvision/bazel-compile-commands-extractor/issues/21
compile_args = (arg for arg in compile_args if not arg == '-fno-canonical-system-headers')

# Some toolchains including wrap the compiler in a script and export that wrapped compiler in the proto. However, we need a clang call that clangd can introspect. (See notes in "how clangd uses compile_commands.json" in ImplementationReadme.md for more.)
# We'd need the wrapper to be invokable by clangd's --query-driver if we didn't remove the wrapper.
compile_args = list(compile_args)
if compile_args[0].endswith(".sh"):
compile_args[0] = _get_underlying_clang(compile_args[0])

# Any other general fixes would go here...

return list(compile_args)
return compile_args


def _get_cpp_command_for_files(compile_action):
Expand Down