brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 660a21e Raw
172 lines · cpp
1//===-- ClangHost.cpp -----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ClangHost.h"10 11#include "clang/Basic/Version.h"12#include "clang/Config/config.h"13#include "clang/Options/OptionUtils.h"14 15#include "llvm/ADT/StringRef.h"16#include "llvm/ADT/Twine.h"17#include "llvm/Support/FileSystem.h"18#include "llvm/Support/Threading.h"19 20#include "lldb/Host/Config.h"21#include "lldb/Host/FileSystem.h"22#include "lldb/Host/HostInfo.h"23#include "lldb/Utility/FileSpec.h"24#include "lldb/Utility/LLDBLog.h"25#include "lldb/Utility/Log.h"26 27#include <string>28 29using namespace lldb_private;30 31static bool VerifyClangPath(const llvm::Twine &clang_path) {32  if (FileSystem::Instance().IsDirectory(clang_path))33    return true;34  Log *log = GetLog(LLDBLog::Host);35  LLDB_LOGF(log,36            "VerifyClangPath(): "37            "failed to stat clang resource directory at \"%s\"",38            clang_path.str().c_str());39  return false;40}41 42///43/// This will compute the clang resource directory assuming that clang was44/// installed with the same prefix as lldb.45///46/// If verify is true, the first candidate resource directory will be returned.47/// This mode is only used for testing.48///49static bool DefaultComputeClangResourceDirectory(FileSpec &lldb_shlib_spec,50                                                 FileSpec &file_spec,51                                                 bool verify) {52  Log *log = GetLog(LLDBLog::Host);53  std::string raw_path = lldb_shlib_spec.GetPath();54  llvm::StringRef parent_dir = llvm::sys::path::parent_path(raw_path);55  static const std::string clang_resource_path =56      clang::GetResourcesPath("bin/lldb");57 58  static const llvm::StringRef kResourceDirSuffixes[] = {59      // LLVM.org's build of LLDB uses the clang resource directory placed60      // in $install_dir/lib{,64}/clang/$clang_version or61      // $install_dir/bin/$CLANG_RESOURCE_DIR62      clang_resource_path,63      // swift-lldb uses the clang resource directory copied from swift, which64      // by default is placed in $install_dir/lib{,64}/lldb/clang. LLDB places65      // it there, so we use LLDB_INSTALL_LIBDIR_BASENAME.66      LLDB_INSTALL_LIBDIR_BASENAME "/lldb/clang",67  };68 69  for (const auto &Suffix : kResourceDirSuffixes) {70    llvm::SmallString<256> clang_dir(parent_dir);71    llvm::SmallString<32> relative_path(Suffix);72    llvm::sys::path::native(relative_path);73    llvm::sys::path::append(clang_dir, relative_path);74    if (!verify || VerifyClangPath(clang_dir)) {75      LLDB_LOG(log,76               "DefaultComputeClangResourceDir: Setting ClangResourceDir "77               "to \"{0}\", verify = {1}",78               clang_dir.str(), verify ? "true" : "false");79      file_spec.SetDirectory(clang_dir);80      FileSystem::Instance().Resolve(file_spec);81      return true;82    }83  }84 85  return false;86}87 88bool lldb_private::ComputeClangResourceDirectory(FileSpec &lldb_shlib_spec,89                                                 FileSpec &file_spec,90                                                 bool verify) {91#if !defined(__APPLE__)92  return DefaultComputeClangResourceDirectory(lldb_shlib_spec, file_spec,93                                              verify);94#else95  std::string raw_path = lldb_shlib_spec.GetPath();96 97  auto rev_it = llvm::sys::path::rbegin(raw_path);98  auto r_end = llvm::sys::path::rend(raw_path);99 100  // Check for a Posix-style build of LLDB.101  while (rev_it != r_end) {102    if (*rev_it == "LLDB.framework")103      break;104    ++rev_it;105  }106 107  // We found a non-framework build of LLDB108  if (rev_it == r_end)109    return DefaultComputeClangResourceDirectory(lldb_shlib_spec, file_spec,110                                                verify);111 112  // Inside Xcode and in Xcode toolchains LLDB is always in lockstep113  // with the Swift compiler, so it can reuse its Clang resource114  // directory. This allows LLDB and the Swift compiler to share the115  // same Clang module cache.116  llvm::SmallString<256> clang_path;117  const char *swift_clang_resource_dir = "usr/lib/swift/clang";118  auto parent = std::next(rev_it);119  if (parent != r_end && *parent == "SharedFrameworks") {120    // This is the top-level LLDB in the Xcode.app bundle.121    // E.g., "Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A"122    raw_path.resize(parent - r_end);123    llvm::sys::path::append(clang_path, raw_path,124                            "Developer/Toolchains/XcodeDefault.xctoolchain",125                            swift_clang_resource_dir);126    if (!verify || VerifyClangPath(clang_path)) {127      file_spec.SetDirectory(clang_path);128      FileSystem::Instance().Resolve(file_spec);129      return true;130    }131  } else if (parent != r_end && *parent == "PrivateFrameworks" &&132             std::distance(parent, r_end) > 2) {133    ++parent;134    ++parent;135    if (*parent == "System") {136      // This is LLDB inside an Xcode toolchain.137      // E.g., "Xcode.app/Contents/Developer/Toolchains/"               \138      //       "My.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework"139      raw_path.resize(parent - r_end);140      llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir);141      if (!verify || VerifyClangPath(clang_path)) {142        file_spec.SetDirectory(clang_path);143        FileSystem::Instance().Resolve(file_spec);144        return true;145      }146    }147  }148 149  // Fall back to the Clang resource directory inside the framework.150  raw_path = lldb_shlib_spec.GetPath();151  raw_path.resize(rev_it - r_end);152  raw_path.append("LLDB.framework/Resources/Clang");153  file_spec.SetDirectory(raw_path);154  FileSystem::Instance().Resolve(file_spec);155  return true;156#endif // __APPLE__157}158 159FileSpec lldb_private::GetClangResourceDir() {160  static FileSpec g_cached_resource_dir;161  static llvm::once_flag g_once_flag;162  llvm::call_once(g_once_flag, []() {163    if (FileSpec lldb_file_spec = HostInfo::GetShlibDir())164      ComputeClangResourceDirectory(lldb_file_spec, g_cached_resource_dir,165                                    true);166    Log *log = GetLog(LLDBLog::Host);167    LLDB_LOGF(log, "GetClangResourceDir() => '%s'",168              g_cached_resource_dir.GetPath().c_str());169  });170  return g_cached_resource_dir;171}172