123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- //===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // Collect the dependencies of a set of modules.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Frontend/Utils.h"
- #include "clang/Serialization/ASTReader.h"
- #include "llvm/ADT/iterator_range.h"
- #include "llvm/ADT/StringSet.h"
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/raw_ostream.h"
- using namespace clang;
- namespace {
- /// Private implementation for ModuleDependencyCollector
- class ModuleDependencyListener : public ASTReaderListener {
- ModuleDependencyCollector &Collector;
- std::error_code copyToRoot(StringRef Src);
- public:
- ModuleDependencyListener(ModuleDependencyCollector &Collector)
- : Collector(Collector) {}
- bool needsInputFileVisitation() override { return true; }
- bool needsSystemInputFileVisitation() override { return true; }
- bool visitInputFile(StringRef Filename, bool IsSystem,
- bool IsOverridden) override;
- };
- }
- void ModuleDependencyCollector::attachToASTReader(ASTReader &R) {
- R.addListener(llvm::make_unique<ModuleDependencyListener>(*this));
- }
- void ModuleDependencyCollector::writeFileMap() {
- if (Seen.empty())
- return;
- SmallString<256> Dest = getDest();
- llvm::sys::path::append(Dest, "vfs.yaml");
- std::error_code EC;
- llvm::raw_fd_ostream OS(Dest, EC, llvm::sys::fs::F_Text);
- if (EC) {
- setHasErrors();
- return;
- }
- VFSWriter.write(OS);
- }
- /// Remove traversal (ie, . or ..) from the given absolute path.
- static void removePathTraversal(SmallVectorImpl<char> &Path) {
- using namespace llvm::sys;
- SmallVector<StringRef, 16> ComponentStack;
- StringRef P(Path.data(), Path.size());
- // Skip the root path, then look for traversal in the components.
- StringRef Rel = path::relative_path(P);
- for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) {
- if (C == ".")
- continue;
- if (C == "..") {
- assert(ComponentStack.size() && "Path traverses out of parent");
- ComponentStack.pop_back();
- } else
- ComponentStack.push_back(C);
- }
- // The stack is now the path without any directory traversal.
- SmallString<256> Buffer = path::root_path(P);
- for (StringRef C : ComponentStack)
- path::append(Buffer, C);
- // Put the result in Path.
- Path.swap(Buffer);
- }
- std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
- using namespace llvm::sys;
- // We need an absolute path to append to the root.
- SmallString<256> AbsoluteSrc = Src;
- fs::make_absolute(AbsoluteSrc);
- removePathTraversal(AbsoluteSrc);
- // Build the destination path.
- SmallString<256> Dest = Collector.getDest();
- path::append(Dest, path::relative_path(AbsoluteSrc));
- // Copy the file into place.
- if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
- /*IgnoreExisting=*/true))
- return EC;
- if (std::error_code EC = fs::copy_file(AbsoluteSrc.str(), Dest.str()))
- return EC;
- // Use the absolute path under the root for the file mapping.
- Collector.addFileMapping(AbsoluteSrc.str(), Dest.str());
- return std::error_code();
- }
- bool ModuleDependencyListener::visitInputFile(StringRef Filename, bool IsSystem,
- bool IsOverridden) {
- if (Collector.insertSeen(Filename))
- if (copyToRoot(Filename))
- Collector.setHasErrors();
- return true;
- }
|