brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.8 KiB · a1f2db7 Raw
229 lines · cpp
1//===- DependencyScanningTool.cpp - clang-scan-deps service ---------------===//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 "clang/Tooling/DependencyScanning/DependencyScanningTool.h"10#include "clang/Frontend/Utils.h"11#include <optional>12 13using namespace clang;14using namespace tooling;15using namespace dependencies;16 17DependencyScanningTool::DependencyScanningTool(18    DependencyScanningService &Service,19    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)20    : Worker(Service, std::move(FS)) {}21 22namespace {23/// Prints out all of the gathered dependencies into a string.24class MakeDependencyPrinterConsumer : public DependencyConsumer {25public:26  void handleBuildCommand(Command) override {}27 28  void29  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {30    this->Opts = std::make_unique<DependencyOutputOptions>(Opts);31  }32 33  void handleFileDependency(StringRef File) override {34    Dependencies.push_back(std::string(File));35  }36 37  // These are ignored for the make format as it can't support the full38  // set of deps, and handleFileDependency handles enough for implicitly39  // built modules to work.40  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {}41  void handleModuleDependency(ModuleDeps MD) override {}42  void handleDirectModuleDependency(ModuleID ID) override {}43  void handleVisibleModule(std::string ModuleName) override {}44  void handleContextHash(std::string Hash) override {}45 46  void printDependencies(std::string &S) {47    assert(Opts && "Handled dependency output options.");48 49    class DependencyPrinter : public DependencyFileGenerator {50    public:51      DependencyPrinter(DependencyOutputOptions &Opts,52                        ArrayRef<std::string> Dependencies)53          : DependencyFileGenerator(Opts) {54        for (const auto &Dep : Dependencies)55          addDependency(Dep);56      }57 58      void printDependencies(std::string &S) {59        llvm::raw_string_ostream OS(S);60        outputDependencyFile(OS);61      }62    };63 64    DependencyPrinter Generator(*Opts, Dependencies);65    Generator.printDependencies(S);66  }67 68protected:69  std::unique_ptr<DependencyOutputOptions> Opts;70  std::vector<std::string> Dependencies;71};72} // anonymous namespace73 74llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(75    const std::vector<std::string> &CommandLine, StringRef CWD) {76  MakeDependencyPrinterConsumer Consumer;77  CallbackActionController Controller(nullptr);78  auto Result =79      Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);80  if (Result)81    return std::move(Result);82  std::string Output;83  Consumer.printDependencies(Output);84  return Output;85}86 87llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(88    const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,89    std::string &MakeformatOutputPath) {90  class P1689ModuleDependencyPrinterConsumer91      : public MakeDependencyPrinterConsumer {92  public:93    P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,94                                         const CompileCommand &Command)95        : Filename(Command.Filename), Rule(Rule) {96      Rule.PrimaryOutput = Command.Output;97    }98 99    void handleProvidedAndRequiredStdCXXModules(100        std::optional<P1689ModuleInfo> Provided,101        std::vector<P1689ModuleInfo> Requires) override {102      Rule.Provides = Provided;103      if (Rule.Provides)104        Rule.Provides->SourcePath = Filename.str();105      Rule.Requires = Requires;106    }107 108    StringRef getMakeFormatDependencyOutputPath() {109      if (Opts->OutputFormat != DependencyOutputFormat::Make)110        return {};111      return Opts->OutputFile;112    }113 114  private:115    StringRef Filename;116    P1689Rule &Rule;117  };118 119  class P1689ActionController : public DependencyActionController {120  public:121    // The lookupModuleOutput is for clang modules. P1689 format don't need it.122    std::string lookupModuleOutput(const ModuleDeps &,123                                   ModuleOutputKind Kind) override {124      return "";125    }126  };127 128  P1689Rule Rule;129  P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);130  P1689ActionController Controller;131  auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,132                                           Controller);133  if (Result)134    return std::move(Result);135 136  MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();137  if (!MakeformatOutputPath.empty())138    Consumer.printDependencies(MakeformatOutput);139  return Rule;140}141 142llvm::Expected<TranslationUnitDeps>143DependencyScanningTool::getTranslationUnitDependencies(144    const std::vector<std::string> &CommandLine, StringRef CWD,145    const llvm::DenseSet<ModuleID> &AlreadySeen,146    LookupModuleOutputCallback LookupModuleOutput,147    std::optional<llvm::MemoryBufferRef> TUBuffer) {148  FullDependencyConsumer Consumer(AlreadySeen);149  CallbackActionController Controller(LookupModuleOutput);150  llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,151                                                  Controller, TUBuffer);152 153  if (Result)154    return std::move(Result);155  return Consumer.takeTranslationUnitDeps();156}157 158llvm::Expected<TranslationUnitDeps>159DependencyScanningTool::getModuleDependencies(160    StringRef ModuleName, const std::vector<std::string> &CommandLine,161    StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,162    LookupModuleOutputCallback LookupModuleOutput) {163  FullDependencyConsumer Consumer(AlreadySeen);164  CallbackActionController Controller(LookupModuleOutput);165  if (auto Error =166          Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine))167    return std::move(Error);168 169  auto Result = Worker.computeDependenciesByNameWithContextOrError(170      ModuleName, Consumer, Controller);171 172  if (auto Error = Worker.finalizeCompilerInstanceWithContextOrError())173    return std::move(Error);174 175  if (Result)176    return std::move(Result);177 178  return Consumer.takeTranslationUnitDeps();179}180 181llvm::Error DependencyScanningTool::initializeCompilerInstanceWithContext(182    StringRef CWD, const std::vector<std::string> &CommandLine) {183  return Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine);184}185 186llvm::Expected<TranslationUnitDeps>187DependencyScanningTool::computeDependenciesByNameWithContext(188    StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen,189    LookupModuleOutputCallback LookupModuleOutput) {190  FullDependencyConsumer Consumer(AlreadySeen);191  CallbackActionController Controller(LookupModuleOutput);192  llvm::Error Result = Worker.computeDependenciesByNameWithContextOrError(193      ModuleName, Consumer, Controller);194  if (Result)195    return std::move(Result);196 197  return Consumer.takeTranslationUnitDeps();198}199 200llvm::Error DependencyScanningTool::finalizeCompilerInstanceWithContext() {201  return Worker.finalizeCompilerInstanceWithContextOrError();202}203 204TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() {205  TranslationUnitDeps TU;206 207  TU.ID.ContextHash = std::move(ContextHash);208  TU.ID.ModuleName = std::move(ModuleName);209  TU.NamedModuleDeps = std::move(NamedModuleDeps);210  TU.FileDeps = std::move(Dependencies);211  TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);212  TU.VisibleModules = std::move(VisibleModules);213  TU.Commands = std::move(Commands);214 215  for (auto &&M : ClangModuleDeps) {216    auto &MD = M.second;217    // TODO: Avoid handleModuleDependency even being called for modules218    //   we've already seen.219    if (AlreadySeen.count(M.first))220      continue;221    TU.ModuleGraph.push_back(std::move(MD));222  }223  TU.ClangModuleDeps = std::move(DirectModuleDeps);224 225  return TU;226}227 228CallbackActionController::~CallbackActionController() {}229