1ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===// 2ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 3ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// The LLVM Compiler Infrastructure 4ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 5ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// This file is distributed under the University of Illinois Open Source 6ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// License. See LICENSE.TXT for details. 7ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 8ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//===----------------------------------------------------------------------===// 9ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 10ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Collect the dependencies of a set of modules. 11ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 12ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//===----------------------------------------------------------------------===// 13ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 14ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "clang/Frontend/Utils.h" 15ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "clang/Serialization/ASTReader.h" 16ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "llvm/ADT/iterator_range.h" 17ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "llvm/ADT/StringSet.h" 18ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "llvm/Support/FileSystem.h" 19ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "llvm/Support/Path.h" 20ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "llvm/Support/raw_ostream.h" 21ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 22ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesusing namespace clang; 23ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 24ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesnamespace { 25ef8225444452a1486bd721f3285301fe84643b00Stephen Hines/// Private implementation for ModuleDependencyCollector 26ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass ModuleDependencyListener : public ASTReaderListener { 27ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ModuleDependencyCollector &Collector; 28ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 29ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::error_code copyToRoot(StringRef Src); 30ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic: 31ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ModuleDependencyListener(ModuleDependencyCollector &Collector) 32ef8225444452a1486bd721f3285301fe84643b00Stephen Hines : Collector(Collector) {} 33ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool needsInputFileVisitation() override { return true; } 34ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool needsSystemInputFileVisitation() override { return true; } 35ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool visitInputFile(StringRef Filename, bool IsSystem, 36ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool IsOverridden) override; 37ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}; 38ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 39ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 40ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid ModuleDependencyCollector::attachToASTReader(ASTReader &R) { 41ef8225444452a1486bd721f3285301fe84643b00Stephen Hines R.addListener(new ModuleDependencyListener(*this)); 42ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 43ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 44ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid ModuleDependencyCollector::writeFileMap() { 45ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Seen.empty()) 46ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return; 47ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 48ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SmallString<256> Dest = getDest(); 49ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::sys::path::append(Dest, "vfs.yaml"); 50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 51ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::string ErrorInfo; 52ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::raw_fd_ostream OS(Dest.c_str(), ErrorInfo, llvm::sys::fs::F_Text); 53ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!ErrorInfo.empty()) { 54ef8225444452a1486bd721f3285301fe84643b00Stephen Hines setHasErrors(); 55ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return; 56ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 57ef8225444452a1486bd721f3285301fe84643b00Stephen Hines VFSWriter.write(OS); 58ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 59ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 60ef8225444452a1486bd721f3285301fe84643b00Stephen Hines/// Remove traversal (ie, . or ..) from the given absolute path. 61ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstatic void removePathTraversal(SmallVectorImpl<char> &Path) { 62ef8225444452a1486bd721f3285301fe84643b00Stephen Hines using namespace llvm::sys; 63ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SmallVector<StringRef, 16> ComponentStack; 64ef8225444452a1486bd721f3285301fe84643b00Stephen Hines StringRef P(Path.data(), Path.size()); 65ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 66ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Skip the root path, then look for traversal in the components. 67ef8225444452a1486bd721f3285301fe84643b00Stephen Hines StringRef Rel = path::relative_path(P); 68ef8225444452a1486bd721f3285301fe84643b00Stephen Hines for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) { 69ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (C == ".") 70ef8225444452a1486bd721f3285301fe84643b00Stephen Hines continue; 71ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (C == "..") { 72ef8225444452a1486bd721f3285301fe84643b00Stephen Hines assert(ComponentStack.size() && "Path traverses out of parent"); 73ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ComponentStack.pop_back(); 74ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } else 75ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ComponentStack.push_back(C); 76ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 77ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 78ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // The stack is now the path without any directory traversal. 79ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SmallString<256> Buffer = path::root_path(P); 80ef8225444452a1486bd721f3285301fe84643b00Stephen Hines for (StringRef C : ComponentStack) 81ef8225444452a1486bd721f3285301fe84643b00Stephen Hines path::append(Buffer, C); 82ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 83ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Put the result in Path. 84ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Path.swap(Buffer); 85ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 86ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 87ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstd::error_code ModuleDependencyListener::copyToRoot(StringRef Src) { 88ef8225444452a1486bd721f3285301fe84643b00Stephen Hines using namespace llvm::sys; 89ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 90ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // We need an absolute path to append to the root. 91ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SmallString<256> AbsoluteSrc = Src; 92ef8225444452a1486bd721f3285301fe84643b00Stephen Hines fs::make_absolute(AbsoluteSrc); 93ef8225444452a1486bd721f3285301fe84643b00Stephen Hines removePathTraversal(AbsoluteSrc); 94ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 95ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Build the destination path. 96ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SmallString<256> Dest = Collector.getDest(); 97ef8225444452a1486bd721f3285301fe84643b00Stephen Hines path::append(Dest, path::relative_path(AbsoluteSrc)); 98ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 99ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Copy the file into place. 100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (std::error_code EC = fs::create_directories(path::parent_path(Dest), 101ef8225444452a1486bd721f3285301fe84643b00Stephen Hines /*IgnoreExisting=*/true)) 102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return EC; 103ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (std::error_code EC = fs::copy_file(AbsoluteSrc.str(), Dest.str())) 104ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return EC; 105ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Use the absolute path under the root for the file mapping. 106ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Collector.addFileMapping(AbsoluteSrc.str(), Dest.str()); 107ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return std::error_code(); 108ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 110ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesbool ModuleDependencyListener::visitInputFile(StringRef Filename, bool IsSystem, 111ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool IsOverridden) { 112ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Collector.insertSeen(Filename)) 113ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (copyToRoot(Filename)) 114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Collector.setHasErrors(); 115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return true; 116ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 117