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