1*67e74705SXin Li //===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // Collect the dependencies of a set of modules.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "clang/Basic/CharInfo.h"
15*67e74705SXin Li #include "clang/Frontend/Utils.h"
16*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
17*67e74705SXin Li #include "clang/Serialization/ASTReader.h"
18*67e74705SXin Li #include "llvm/ADT/StringMap.h"
19*67e74705SXin Li #include "llvm/ADT/iterator_range.h"
20*67e74705SXin Li #include "llvm/Support/FileSystem.h"
21*67e74705SXin Li #include "llvm/Support/Path.h"
22*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
23*67e74705SXin Li
24*67e74705SXin Li using namespace clang;
25*67e74705SXin Li
26*67e74705SXin Li namespace {
27*67e74705SXin Li /// Private implementations for ModuleDependencyCollector
28*67e74705SXin Li class ModuleDependencyListener : public ASTReaderListener {
29*67e74705SXin Li ModuleDependencyCollector &Collector;
30*67e74705SXin Li public:
ModuleDependencyListener(ModuleDependencyCollector & Collector)31*67e74705SXin Li ModuleDependencyListener(ModuleDependencyCollector &Collector)
32*67e74705SXin Li : Collector(Collector) {}
needsInputFileVisitation()33*67e74705SXin Li bool needsInputFileVisitation() override { return true; }
needsSystemInputFileVisitation()34*67e74705SXin Li bool needsSystemInputFileVisitation() override { return true; }
visitInputFile(StringRef Filename,bool IsSystem,bool IsOverridden,bool IsExplicitModule)35*67e74705SXin Li bool visitInputFile(StringRef Filename, bool IsSystem, bool IsOverridden,
36*67e74705SXin Li bool IsExplicitModule) override {
37*67e74705SXin Li Collector.addFile(Filename);
38*67e74705SXin Li return true;
39*67e74705SXin Li }
40*67e74705SXin Li };
41*67e74705SXin Li
42*67e74705SXin Li struct ModuleDependencyMMCallbacks : public ModuleMapCallbacks {
43*67e74705SXin Li ModuleDependencyCollector &Collector;
ModuleDependencyMMCallbacks__anone6ea444d0111::ModuleDependencyMMCallbacks44*67e74705SXin Li ModuleDependencyMMCallbacks(ModuleDependencyCollector &Collector)
45*67e74705SXin Li : Collector(Collector) {}
46*67e74705SXin Li
moduleMapAddHeader__anone6ea444d0111::ModuleDependencyMMCallbacks47*67e74705SXin Li void moduleMapAddHeader(StringRef HeaderPath) override {
48*67e74705SXin Li if (llvm::sys::path::is_absolute(HeaderPath))
49*67e74705SXin Li Collector.addFile(HeaderPath);
50*67e74705SXin Li }
moduleMapAddUmbrellaHeader__anone6ea444d0111::ModuleDependencyMMCallbacks51*67e74705SXin Li void moduleMapAddUmbrellaHeader(FileManager *FileMgr,
52*67e74705SXin Li const FileEntry *Header) override {
53*67e74705SXin Li StringRef HeaderFilename = Header->getName();
54*67e74705SXin Li moduleMapAddHeader(HeaderFilename);
55*67e74705SXin Li // The FileManager can find and cache the symbolic link for a framework
56*67e74705SXin Li // header before its real path, this means a module can have some of its
57*67e74705SXin Li // headers to use other paths. Although this is usually not a problem, it's
58*67e74705SXin Li // inconsistent, and not collecting the original path header leads to
59*67e74705SXin Li // umbrella clashes while rebuilding modules in the crash reproducer. For
60*67e74705SXin Li // example:
61*67e74705SXin Li // ApplicationServices.framework/Frameworks/ImageIO.framework/ImageIO.h
62*67e74705SXin Li // instead of:
63*67e74705SXin Li // ImageIO.framework/ImageIO.h
64*67e74705SXin Li //
65*67e74705SXin Li // FIXME: this shouldn't be necessary once we have FileName instances
66*67e74705SXin Li // around instead of FileEntry ones. For now, make sure we collect all
67*67e74705SXin Li // that we need for the reproducer to work correctly.
68*67e74705SXin Li StringRef UmbreallDirFromHeader =
69*67e74705SXin Li llvm::sys::path::parent_path(HeaderFilename);
70*67e74705SXin Li StringRef UmbrellaDir = Header->getDir()->getName();
71*67e74705SXin Li if (!UmbrellaDir.equals(UmbreallDirFromHeader)) {
72*67e74705SXin Li SmallString<128> AltHeaderFilename;
73*67e74705SXin Li llvm::sys::path::append(AltHeaderFilename, UmbrellaDir,
74*67e74705SXin Li llvm::sys::path::filename(HeaderFilename));
75*67e74705SXin Li if (FileMgr->getFile(AltHeaderFilename))
76*67e74705SXin Li moduleMapAddHeader(AltHeaderFilename);
77*67e74705SXin Li }
78*67e74705SXin Li }
79*67e74705SXin Li };
80*67e74705SXin Li
81*67e74705SXin Li }
82*67e74705SXin Li
83*67e74705SXin Li // TODO: move this to Support/Path.h and check for HAVE_REALPATH?
real_path(StringRef SrcPath,SmallVectorImpl<char> & RealPath)84*67e74705SXin Li static bool real_path(StringRef SrcPath, SmallVectorImpl<char> &RealPath) {
85*67e74705SXin Li #ifdef LLVM_ON_UNIX
86*67e74705SXin Li char CanonicalPath[PATH_MAX];
87*67e74705SXin Li
88*67e74705SXin Li // TODO: emit a warning in case this fails...?
89*67e74705SXin Li if (!realpath(SrcPath.str().c_str(), CanonicalPath))
90*67e74705SXin Li return false;
91*67e74705SXin Li
92*67e74705SXin Li SmallString<256> RPath(CanonicalPath);
93*67e74705SXin Li RealPath.swap(RPath);
94*67e74705SXin Li return true;
95*67e74705SXin Li #else
96*67e74705SXin Li // FIXME: Add support for systems without realpath.
97*67e74705SXin Li return false;
98*67e74705SXin Li #endif
99*67e74705SXin Li }
100*67e74705SXin Li
attachToASTReader(ASTReader & R)101*67e74705SXin Li void ModuleDependencyCollector::attachToASTReader(ASTReader &R) {
102*67e74705SXin Li R.addListener(llvm::make_unique<ModuleDependencyListener>(*this));
103*67e74705SXin Li }
104*67e74705SXin Li
attachToPreprocessor(Preprocessor & PP)105*67e74705SXin Li void ModuleDependencyCollector::attachToPreprocessor(Preprocessor &PP) {
106*67e74705SXin Li PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
107*67e74705SXin Li llvm::make_unique<ModuleDependencyMMCallbacks>(*this));
108*67e74705SXin Li }
109*67e74705SXin Li
isCaseSensitivePath(StringRef Path)110*67e74705SXin Li static bool isCaseSensitivePath(StringRef Path) {
111*67e74705SXin Li SmallString<256> TmpDest = Path, UpperDest, RealDest;
112*67e74705SXin Li // Remove component traversals, links, etc.
113*67e74705SXin Li if (!real_path(Path, TmpDest))
114*67e74705SXin Li return true; // Current default value in vfs.yaml
115*67e74705SXin Li Path = TmpDest;
116*67e74705SXin Li
117*67e74705SXin Li // Change path to all upper case and ask for its real path, if the latter
118*67e74705SXin Li // exists and is equal to Path, it's not case sensitive. Default to case
119*67e74705SXin Li // sensitive in the absense of realpath, since this is what the VFSWriter
120*67e74705SXin Li // already expects when sensitivity isn't setup.
121*67e74705SXin Li for (auto &C : Path)
122*67e74705SXin Li UpperDest.push_back(toUppercase(C));
123*67e74705SXin Li if (real_path(UpperDest, RealDest) && Path.equals(RealDest))
124*67e74705SXin Li return false;
125*67e74705SXin Li return true;
126*67e74705SXin Li }
127*67e74705SXin Li
writeFileMap()128*67e74705SXin Li void ModuleDependencyCollector::writeFileMap() {
129*67e74705SXin Li if (Seen.empty())
130*67e74705SXin Li return;
131*67e74705SXin Li
132*67e74705SXin Li StringRef VFSDir = getDest();
133*67e74705SXin Li
134*67e74705SXin Li // Default to use relative overlay directories in the VFS yaml file. This
135*67e74705SXin Li // allows crash reproducer scripts to work across machines.
136*67e74705SXin Li VFSWriter.setOverlayDir(VFSDir);
137*67e74705SXin Li
138*67e74705SXin Li // Explicitly set case sensitivity for the YAML writer. For that, find out
139*67e74705SXin Li // the sensitivity at the path where the headers all collected to.
140*67e74705SXin Li VFSWriter.setCaseSensitivity(isCaseSensitivePath(VFSDir));
141*67e74705SXin Li
142*67e74705SXin Li // Do not rely on real path names when executing the crash reproducer scripts
143*67e74705SXin Li // since we only want to actually use the files we have on the VFS cache.
144*67e74705SXin Li VFSWriter.setUseExternalNames(false);
145*67e74705SXin Li
146*67e74705SXin Li std::error_code EC;
147*67e74705SXin Li SmallString<256> YAMLPath = VFSDir;
148*67e74705SXin Li llvm::sys::path::append(YAMLPath, "vfs.yaml");
149*67e74705SXin Li llvm::raw_fd_ostream OS(YAMLPath, EC, llvm::sys::fs::F_Text);
150*67e74705SXin Li if (EC) {
151*67e74705SXin Li HasErrors = true;
152*67e74705SXin Li return;
153*67e74705SXin Li }
154*67e74705SXin Li VFSWriter.write(OS);
155*67e74705SXin Li }
156*67e74705SXin Li
getRealPath(StringRef SrcPath,SmallVectorImpl<char> & Result)157*67e74705SXin Li bool ModuleDependencyCollector::getRealPath(StringRef SrcPath,
158*67e74705SXin Li SmallVectorImpl<char> &Result) {
159*67e74705SXin Li using namespace llvm::sys;
160*67e74705SXin Li SmallString<256> RealPath;
161*67e74705SXin Li StringRef FileName = path::filename(SrcPath);
162*67e74705SXin Li std::string Dir = path::parent_path(SrcPath).str();
163*67e74705SXin Li auto DirWithSymLink = SymLinkMap.find(Dir);
164*67e74705SXin Li
165*67e74705SXin Li // Use real_path to fix any symbolic link component present in a path.
166*67e74705SXin Li // Computing the real path is expensive, cache the search through the
167*67e74705SXin Li // parent path directory.
168*67e74705SXin Li if (DirWithSymLink == SymLinkMap.end()) {
169*67e74705SXin Li if (!real_path(Dir, RealPath))
170*67e74705SXin Li return false;
171*67e74705SXin Li SymLinkMap[Dir] = RealPath.str();
172*67e74705SXin Li } else {
173*67e74705SXin Li RealPath = DirWithSymLink->second;
174*67e74705SXin Li }
175*67e74705SXin Li
176*67e74705SXin Li path::append(RealPath, FileName);
177*67e74705SXin Li Result.swap(RealPath);
178*67e74705SXin Li return true;
179*67e74705SXin Li }
180*67e74705SXin Li
copyToRoot(StringRef Src)181*67e74705SXin Li std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src) {
182*67e74705SXin Li using namespace llvm::sys;
183*67e74705SXin Li
184*67e74705SXin Li // We need an absolute src path to append to the root.
185*67e74705SXin Li SmallString<256> AbsoluteSrc = Src;
186*67e74705SXin Li fs::make_absolute(AbsoluteSrc);
187*67e74705SXin Li // Canonicalize src to a native path to avoid mixed separator styles.
188*67e74705SXin Li path::native(AbsoluteSrc);
189*67e74705SXin Li // Remove redundant leading "./" pieces and consecutive separators.
190*67e74705SXin Li AbsoluteSrc = path::remove_leading_dotslash(AbsoluteSrc);
191*67e74705SXin Li
192*67e74705SXin Li // Canonicalize the source path by removing "..", "." components.
193*67e74705SXin Li SmallString<256> CanonicalPath = AbsoluteSrc;
194*67e74705SXin Li path::remove_dots(CanonicalPath, /*remove_dot_dot=*/true);
195*67e74705SXin Li
196*67e74705SXin Li // If a ".." component is present after a symlink component, remove_dots may
197*67e74705SXin Li // lead to the wrong real destination path. Let the source be canonicalized
198*67e74705SXin Li // like that but make sure we always use the real path for the destination.
199*67e74705SXin Li SmallString<256> RealPath;
200*67e74705SXin Li if (!getRealPath(AbsoluteSrc, RealPath))
201*67e74705SXin Li RealPath = CanonicalPath;
202*67e74705SXin Li SmallString<256> Dest = getDest();
203*67e74705SXin Li path::append(Dest, path::relative_path(RealPath));
204*67e74705SXin Li
205*67e74705SXin Li // Copy the file into place.
206*67e74705SXin Li if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
207*67e74705SXin Li /*IgnoreExisting=*/true))
208*67e74705SXin Li return EC;
209*67e74705SXin Li if (std::error_code EC = fs::copy_file(RealPath, Dest))
210*67e74705SXin Li return EC;
211*67e74705SXin Li
212*67e74705SXin Li // Always map a canonical src path to its real path into the YAML, by doing
213*67e74705SXin Li // this we map different virtual src paths to the same entry in the VFS
214*67e74705SXin Li // overlay, which is a way to emulate symlink inside the VFS; this is also
215*67e74705SXin Li // needed for correctness, not doing that can lead to module redifinition
216*67e74705SXin Li // errors.
217*67e74705SXin Li addFileMapping(CanonicalPath, Dest);
218*67e74705SXin Li return std::error_code();
219*67e74705SXin Li }
220*67e74705SXin Li
addFile(StringRef Filename)221*67e74705SXin Li void ModuleDependencyCollector::addFile(StringRef Filename) {
222*67e74705SXin Li if (insertSeen(Filename))
223*67e74705SXin Li if (copyToRoot(Filename))
224*67e74705SXin Li HasErrors = true;
225*67e74705SXin Li }
226