Path: blob/main/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
35294 views
//===- DependencyScanningTool.cpp - clang-scan-deps service ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h"9#include "clang/Frontend/Utils.h"10#include <optional>1112using namespace clang;13using namespace tooling;14using namespace dependencies;1516DependencyScanningTool::DependencyScanningTool(17DependencyScanningService &Service,18llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)19: Worker(Service, std::move(FS)) {}2021namespace {22/// Prints out all of the gathered dependencies into a string.23class MakeDependencyPrinterConsumer : public DependencyConsumer {24public:25void handleBuildCommand(Command) override {}2627void28handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {29this->Opts = std::make_unique<DependencyOutputOptions>(Opts);30}3132void handleFileDependency(StringRef File) override {33Dependencies.push_back(std::string(File));34}3536// These are ignored for the make format as it can't support the full37// set of deps, and handleFileDependency handles enough for implicitly38// built modules to work.39void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {}40void handleModuleDependency(ModuleDeps MD) override {}41void handleDirectModuleDependency(ModuleID ID) override {}42void handleContextHash(std::string Hash) override {}4344void printDependencies(std::string &S) {45assert(Opts && "Handled dependency output options.");4647class DependencyPrinter : public DependencyFileGenerator {48public:49DependencyPrinter(DependencyOutputOptions &Opts,50ArrayRef<std::string> Dependencies)51: DependencyFileGenerator(Opts) {52for (const auto &Dep : Dependencies)53addDependency(Dep);54}5556void printDependencies(std::string &S) {57llvm::raw_string_ostream OS(S);58outputDependencyFile(OS);59}60};6162DependencyPrinter Generator(*Opts, Dependencies);63Generator.printDependencies(S);64}6566protected:67std::unique_ptr<DependencyOutputOptions> Opts;68std::vector<std::string> Dependencies;69};70} // anonymous namespace7172llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(73const std::vector<std::string> &CommandLine, StringRef CWD) {74MakeDependencyPrinterConsumer Consumer;75CallbackActionController Controller(nullptr);76auto Result =77Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);78if (Result)79return std::move(Result);80std::string Output;81Consumer.printDependencies(Output);82return Output;83}8485llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(86const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,87std::string &MakeformatOutputPath) {88class P1689ModuleDependencyPrinterConsumer89: public MakeDependencyPrinterConsumer {90public:91P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,92const CompileCommand &Command)93: Filename(Command.Filename), Rule(Rule) {94Rule.PrimaryOutput = Command.Output;95}9697void handleProvidedAndRequiredStdCXXModules(98std::optional<P1689ModuleInfo> Provided,99std::vector<P1689ModuleInfo> Requires) override {100Rule.Provides = Provided;101if (Rule.Provides)102Rule.Provides->SourcePath = Filename.str();103Rule.Requires = Requires;104}105106StringRef getMakeFormatDependencyOutputPath() {107if (Opts->OutputFormat != DependencyOutputFormat::Make)108return {};109return Opts->OutputFile;110}111112private:113StringRef Filename;114P1689Rule &Rule;115};116117class P1689ActionController : public DependencyActionController {118public:119// The lookupModuleOutput is for clang modules. P1689 format don't need it.120std::string lookupModuleOutput(const ModuleID &,121ModuleOutputKind Kind) override {122return "";123}124};125126P1689Rule Rule;127P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);128P1689ActionController Controller;129auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,130Controller);131if (Result)132return std::move(Result);133134MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();135if (!MakeformatOutputPath.empty())136Consumer.printDependencies(MakeformatOutput);137return Rule;138}139140llvm::Expected<TranslationUnitDeps>141DependencyScanningTool::getTranslationUnitDependencies(142const std::vector<std::string> &CommandLine, StringRef CWD,143const llvm::DenseSet<ModuleID> &AlreadySeen,144LookupModuleOutputCallback LookupModuleOutput) {145FullDependencyConsumer Consumer(AlreadySeen);146CallbackActionController Controller(LookupModuleOutput);147llvm::Error Result =148Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);149if (Result)150return std::move(Result);151return Consumer.takeTranslationUnitDeps();152}153154llvm::Expected<ModuleDepsGraph> DependencyScanningTool::getModuleDependencies(155StringRef ModuleName, const std::vector<std::string> &CommandLine,156StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,157LookupModuleOutputCallback LookupModuleOutput) {158FullDependencyConsumer Consumer(AlreadySeen);159CallbackActionController Controller(LookupModuleOutput);160llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,161Controller, ModuleName);162if (Result)163return std::move(Result);164return Consumer.takeModuleGraphDeps();165}166167TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() {168TranslationUnitDeps TU;169170TU.ID.ContextHash = std::move(ContextHash);171TU.FileDeps = std::move(Dependencies);172TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);173TU.Commands = std::move(Commands);174175for (auto &&M : ClangModuleDeps) {176auto &MD = M.second;177// TODO: Avoid handleModuleDependency even being called for modules178// we've already seen.179if (AlreadySeen.count(M.first))180continue;181TU.ModuleGraph.push_back(std::move(MD));182}183TU.ClangModuleDeps = std::move(DirectModuleDeps);184185return TU;186}187188ModuleDepsGraph FullDependencyConsumer::takeModuleGraphDeps() {189ModuleDepsGraph ModuleGraph;190191for (auto &&M : ClangModuleDeps) {192auto &MD = M.second;193// TODO: Avoid handleModuleDependency even being called for modules194// we've already seen.195if (AlreadySeen.count(M.first))196continue;197ModuleGraph.push_back(std::move(MD));198}199200return ModuleGraph;201}202203CallbackActionController::~CallbackActionController() {}204205206