xref: /minix3/external/bsd/llvm/dist/clang/lib/Frontend/ModuleDependencyCollector.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // Collect the dependencies of a set of modules.
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
13*0a6a1f1dSLionel Sambuc 
14*0a6a1f1dSLionel Sambuc #include "clang/Frontend/Utils.h"
15*0a6a1f1dSLionel Sambuc #include "clang/Serialization/ASTReader.h"
16*0a6a1f1dSLionel Sambuc #include "llvm/ADT/StringSet.h"
17*0a6a1f1dSLionel Sambuc #include "llvm/ADT/iterator_range.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/Support/FileSystem.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/Support/Path.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/Support/raw_ostream.h"
21*0a6a1f1dSLionel Sambuc 
22*0a6a1f1dSLionel Sambuc using namespace clang;
23*0a6a1f1dSLionel Sambuc 
24*0a6a1f1dSLionel Sambuc namespace {
25*0a6a1f1dSLionel Sambuc /// Private implementation for ModuleDependencyCollector
26*0a6a1f1dSLionel Sambuc class ModuleDependencyListener : public ASTReaderListener {
27*0a6a1f1dSLionel Sambuc   ModuleDependencyCollector &Collector;
28*0a6a1f1dSLionel Sambuc 
29*0a6a1f1dSLionel Sambuc   std::error_code copyToRoot(StringRef Src);
30*0a6a1f1dSLionel Sambuc public:
ModuleDependencyListener(ModuleDependencyCollector & Collector)31*0a6a1f1dSLionel Sambuc   ModuleDependencyListener(ModuleDependencyCollector &Collector)
32*0a6a1f1dSLionel Sambuc       : Collector(Collector) {}
needsInputFileVisitation()33*0a6a1f1dSLionel Sambuc   bool needsInputFileVisitation() override { return true; }
needsSystemInputFileVisitation()34*0a6a1f1dSLionel Sambuc   bool needsSystemInputFileVisitation() override { return true; }
35*0a6a1f1dSLionel Sambuc   bool visitInputFile(StringRef Filename, bool IsSystem,
36*0a6a1f1dSLionel Sambuc                       bool IsOverridden) override;
37*0a6a1f1dSLionel Sambuc };
38*0a6a1f1dSLionel Sambuc }
39*0a6a1f1dSLionel Sambuc 
attachToASTReader(ASTReader & R)40*0a6a1f1dSLionel Sambuc void ModuleDependencyCollector::attachToASTReader(ASTReader &R) {
41*0a6a1f1dSLionel Sambuc   R.addListener(llvm::make_unique<ModuleDependencyListener>(*this));
42*0a6a1f1dSLionel Sambuc }
43*0a6a1f1dSLionel Sambuc 
writeFileMap()44*0a6a1f1dSLionel Sambuc void ModuleDependencyCollector::writeFileMap() {
45*0a6a1f1dSLionel Sambuc   if (Seen.empty())
46*0a6a1f1dSLionel Sambuc     return;
47*0a6a1f1dSLionel Sambuc 
48*0a6a1f1dSLionel Sambuc   SmallString<256> Dest = getDest();
49*0a6a1f1dSLionel Sambuc   llvm::sys::path::append(Dest, "vfs.yaml");
50*0a6a1f1dSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc   std::error_code EC;
52*0a6a1f1dSLionel Sambuc   llvm::raw_fd_ostream OS(Dest, EC, llvm::sys::fs::F_Text);
53*0a6a1f1dSLionel Sambuc   if (EC) {
54*0a6a1f1dSLionel Sambuc     setHasErrors();
55*0a6a1f1dSLionel Sambuc     return;
56*0a6a1f1dSLionel Sambuc   }
57*0a6a1f1dSLionel Sambuc   VFSWriter.write(OS);
58*0a6a1f1dSLionel Sambuc }
59*0a6a1f1dSLionel Sambuc 
copyToRoot(StringRef Src)60*0a6a1f1dSLionel Sambuc std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
61*0a6a1f1dSLionel Sambuc   using namespace llvm::sys;
62*0a6a1f1dSLionel Sambuc 
63*0a6a1f1dSLionel Sambuc   // We need an absolute path to append to the root.
64*0a6a1f1dSLionel Sambuc   SmallString<256> AbsoluteSrc = Src;
65*0a6a1f1dSLionel Sambuc   fs::make_absolute(AbsoluteSrc);
66*0a6a1f1dSLionel Sambuc   // Canonicalize to a native path to avoid mixed separator styles.
67*0a6a1f1dSLionel Sambuc   path::native(AbsoluteSrc);
68*0a6a1f1dSLionel Sambuc   // TODO: We probably need to handle .. as well as . in order to have valid
69*0a6a1f1dSLionel Sambuc   // input to the YAMLVFSWriter.
70*0a6a1f1dSLionel Sambuc   FileManager::removeDotPaths(AbsoluteSrc);
71*0a6a1f1dSLionel Sambuc 
72*0a6a1f1dSLionel Sambuc   // Build the destination path.
73*0a6a1f1dSLionel Sambuc   SmallString<256> Dest = Collector.getDest();
74*0a6a1f1dSLionel Sambuc   path::append(Dest, path::relative_path(AbsoluteSrc));
75*0a6a1f1dSLionel Sambuc 
76*0a6a1f1dSLionel Sambuc   // Copy the file into place.
77*0a6a1f1dSLionel Sambuc   if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
78*0a6a1f1dSLionel Sambuc                                                    /*IgnoreExisting=*/true))
79*0a6a1f1dSLionel Sambuc     return EC;
80*0a6a1f1dSLionel Sambuc   if (std::error_code EC = fs::copy_file(AbsoluteSrc.str(), Dest.str()))
81*0a6a1f1dSLionel Sambuc     return EC;
82*0a6a1f1dSLionel Sambuc   // Use the absolute path under the root for the file mapping.
83*0a6a1f1dSLionel Sambuc   Collector.addFileMapping(AbsoluteSrc.str(), Dest.str());
84*0a6a1f1dSLionel Sambuc   return std::error_code();
85*0a6a1f1dSLionel Sambuc }
86*0a6a1f1dSLionel Sambuc 
visitInputFile(StringRef Filename,bool IsSystem,bool IsOverridden)87*0a6a1f1dSLionel Sambuc bool ModuleDependencyListener::visitInputFile(StringRef Filename, bool IsSystem,
88*0a6a1f1dSLionel Sambuc                                               bool IsOverridden) {
89*0a6a1f1dSLionel Sambuc   if (Collector.insertSeen(Filename))
90*0a6a1f1dSLionel Sambuc     if (copyToRoot(Filename))
91*0a6a1f1dSLionel Sambuc       Collector.setHasErrors();
92*0a6a1f1dSLionel Sambuc   return true;
93*0a6a1f1dSLionel Sambuc }
94