10b57cec5SDimitry Andric //===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Collect the dependencies of a set of modules. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 140b57cec5SDimitry Andric #include "clang/Frontend/Utils.h" 150b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 160b57cec5SDimitry Andric #include "clang/Serialization/ASTReader.h" 170b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 180b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 190b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 200b57cec5SDimitry Andric #include "llvm/Support/Path.h" 210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace clang; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric namespace { 260b57cec5SDimitry Andric /// Private implementations for ModuleDependencyCollector 270b57cec5SDimitry Andric class ModuleDependencyListener : public ASTReaderListener { 280b57cec5SDimitry Andric ModuleDependencyCollector &Collector; 290b57cec5SDimitry Andric public: 300b57cec5SDimitry Andric ModuleDependencyListener(ModuleDependencyCollector &Collector) 310b57cec5SDimitry Andric : Collector(Collector) {} 320b57cec5SDimitry Andric bool needsInputFileVisitation() override { return true; } 330b57cec5SDimitry Andric bool needsSystemInputFileVisitation() override { return true; } 340b57cec5SDimitry Andric bool visitInputFile(StringRef Filename, bool IsSystem, bool IsOverridden, 350b57cec5SDimitry Andric bool IsExplicitModule) override { 360b57cec5SDimitry Andric Collector.addFile(Filename); 370b57cec5SDimitry Andric return true; 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric }; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric struct ModuleDependencyPPCallbacks : public PPCallbacks { 420b57cec5SDimitry Andric ModuleDependencyCollector &Collector; 430b57cec5SDimitry Andric SourceManager &SM; 440b57cec5SDimitry Andric ModuleDependencyPPCallbacks(ModuleDependencyCollector &Collector, 450b57cec5SDimitry Andric SourceManager &SM) 460b57cec5SDimitry Andric : Collector(Collector), SM(SM) {} 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 490b57cec5SDimitry Andric StringRef FileName, bool IsAngled, 500b57cec5SDimitry Andric CharSourceRange FilenameRange, const FileEntry *File, 510b57cec5SDimitry Andric StringRef SearchPath, StringRef RelativePath, 520b57cec5SDimitry Andric const Module *Imported, 530b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType) override { 540b57cec5SDimitry Andric if (!File) 550b57cec5SDimitry Andric return; 560b57cec5SDimitry Andric Collector.addFile(File->getName()); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric struct ModuleDependencyMMCallbacks : public ModuleMapCallbacks { 610b57cec5SDimitry Andric ModuleDependencyCollector &Collector; 620b57cec5SDimitry Andric ModuleDependencyMMCallbacks(ModuleDependencyCollector &Collector) 630b57cec5SDimitry Andric : Collector(Collector) {} 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric void moduleMapAddHeader(StringRef HeaderPath) override { 660b57cec5SDimitry Andric if (llvm::sys::path::is_absolute(HeaderPath)) 670b57cec5SDimitry Andric Collector.addFile(HeaderPath); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric void moduleMapAddUmbrellaHeader(FileManager *FileMgr, 700b57cec5SDimitry Andric const FileEntry *Header) override { 710b57cec5SDimitry Andric StringRef HeaderFilename = Header->getName(); 720b57cec5SDimitry Andric moduleMapAddHeader(HeaderFilename); 730b57cec5SDimitry Andric // The FileManager can find and cache the symbolic link for a framework 740b57cec5SDimitry Andric // header before its real path, this means a module can have some of its 750b57cec5SDimitry Andric // headers to use other paths. Although this is usually not a problem, it's 760b57cec5SDimitry Andric // inconsistent, and not collecting the original path header leads to 770b57cec5SDimitry Andric // umbrella clashes while rebuilding modules in the crash reproducer. For 780b57cec5SDimitry Andric // example: 790b57cec5SDimitry Andric // ApplicationServices.framework/Frameworks/ImageIO.framework/ImageIO.h 800b57cec5SDimitry Andric // instead of: 810b57cec5SDimitry Andric // ImageIO.framework/ImageIO.h 820b57cec5SDimitry Andric // 830b57cec5SDimitry Andric // FIXME: this shouldn't be necessary once we have FileName instances 840b57cec5SDimitry Andric // around instead of FileEntry ones. For now, make sure we collect all 850b57cec5SDimitry Andric // that we need for the reproducer to work correctly. 860b57cec5SDimitry Andric StringRef UmbreallDirFromHeader = 870b57cec5SDimitry Andric llvm::sys::path::parent_path(HeaderFilename); 880b57cec5SDimitry Andric StringRef UmbrellaDir = Header->getDir()->getName(); 890b57cec5SDimitry Andric if (!UmbrellaDir.equals(UmbreallDirFromHeader)) { 900b57cec5SDimitry Andric SmallString<128> AltHeaderFilename; 910b57cec5SDimitry Andric llvm::sys::path::append(AltHeaderFilename, UmbrellaDir, 920b57cec5SDimitry Andric llvm::sys::path::filename(HeaderFilename)); 930b57cec5SDimitry Andric if (FileMgr->getFile(AltHeaderFilename)) 940b57cec5SDimitry Andric moduleMapAddHeader(AltHeaderFilename); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric }; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void ModuleDependencyCollector::attachToASTReader(ASTReader &R) { 102a7dea167SDimitry Andric R.addListener(std::make_unique<ModuleDependencyListener>(*this)); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void ModuleDependencyCollector::attachToPreprocessor(Preprocessor &PP) { 106a7dea167SDimitry Andric PP.addPPCallbacks(std::make_unique<ModuleDependencyPPCallbacks>( 1070b57cec5SDimitry Andric *this, PP.getSourceManager())); 1080b57cec5SDimitry Andric PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( 109a7dea167SDimitry Andric std::make_unique<ModuleDependencyMMCallbacks>(*this)); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric static bool isCaseSensitivePath(StringRef Path) { 1130b57cec5SDimitry Andric SmallString<256> TmpDest = Path, UpperDest, RealDest; 1140b57cec5SDimitry Andric // Remove component traversals, links, etc. 1150b57cec5SDimitry Andric if (llvm::sys::fs::real_path(Path, TmpDest)) 1160b57cec5SDimitry Andric return true; // Current default value in vfs.yaml 1170b57cec5SDimitry Andric Path = TmpDest; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // Change path to all upper case and ask for its real path, if the latter 1200b57cec5SDimitry Andric // exists and is equal to Path, it's not case sensitive. Default to case 1210b57cec5SDimitry Andric // sensitive in the absence of realpath, since this is what the VFSWriter 1220b57cec5SDimitry Andric // already expects when sensitivity isn't setup. 1230b57cec5SDimitry Andric for (auto &C : Path) 1240b57cec5SDimitry Andric UpperDest.push_back(toUppercase(C)); 1250b57cec5SDimitry Andric if (!llvm::sys::fs::real_path(UpperDest, RealDest) && Path.equals(RealDest)) 1260b57cec5SDimitry Andric return false; 1270b57cec5SDimitry Andric return true; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric void ModuleDependencyCollector::writeFileMap() { 1310b57cec5SDimitry Andric if (Seen.empty()) 1320b57cec5SDimitry Andric return; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric StringRef VFSDir = getDest(); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric // Default to use relative overlay directories in the VFS yaml file. This 1370b57cec5SDimitry Andric // allows crash reproducer scripts to work across machines. 1380b57cec5SDimitry Andric VFSWriter.setOverlayDir(VFSDir); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Explicitly set case sensitivity for the YAML writer. For that, find out 1410b57cec5SDimitry Andric // the sensitivity at the path where the headers all collected to. 1420b57cec5SDimitry Andric VFSWriter.setCaseSensitivity(isCaseSensitivePath(VFSDir)); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // Do not rely on real path names when executing the crash reproducer scripts 1450b57cec5SDimitry Andric // since we only want to actually use the files we have on the VFS cache. 1460b57cec5SDimitry Andric VFSWriter.setUseExternalNames(false); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric std::error_code EC; 1490b57cec5SDimitry Andric SmallString<256> YAMLPath = VFSDir; 1500b57cec5SDimitry Andric llvm::sys::path::append(YAMLPath, "vfs.yaml"); 151a7dea167SDimitry Andric llvm::raw_fd_ostream OS(YAMLPath, EC, llvm::sys::fs::OF_Text); 1520b57cec5SDimitry Andric if (EC) { 1530b57cec5SDimitry Andric HasErrors = true; 1540b57cec5SDimitry Andric return; 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric VFSWriter.write(OS); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src, 1600b57cec5SDimitry Andric StringRef Dst) { 1610b57cec5SDimitry Andric using namespace llvm::sys; 162*e8d8bef9SDimitry Andric llvm::FileCollector::PathCanonicalizer::PathStorage Paths = 163*e8d8bef9SDimitry Andric Canonicalizer.canonicalize(Src); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric SmallString<256> CacheDst = getDest(); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric if (Dst.empty()) { 1680b57cec5SDimitry Andric // The common case is to map the virtual path to the same path inside the 1690b57cec5SDimitry Andric // cache. 170*e8d8bef9SDimitry Andric path::append(CacheDst, path::relative_path(Paths.CopyFrom)); 1710b57cec5SDimitry Andric } else { 1720b57cec5SDimitry Andric // When collecting entries from input vfsoverlays, copy the external 1730b57cec5SDimitry Andric // contents into the cache but still map from the source. 1740b57cec5SDimitry Andric if (!fs::exists(Dst)) 1750b57cec5SDimitry Andric return std::error_code(); 1760b57cec5SDimitry Andric path::append(CacheDst, Dst); 177*e8d8bef9SDimitry Andric Paths.CopyFrom = Dst; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // Copy the file into place. 1810b57cec5SDimitry Andric if (std::error_code EC = fs::create_directories(path::parent_path(CacheDst), 1820b57cec5SDimitry Andric /*IgnoreExisting=*/true)) 1830b57cec5SDimitry Andric return EC; 184*e8d8bef9SDimitry Andric if (std::error_code EC = fs::copy_file(Paths.CopyFrom, CacheDst)) 1850b57cec5SDimitry Andric return EC; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // Always map a canonical src path to its real path into the YAML, by doing 1880b57cec5SDimitry Andric // this we map different virtual src paths to the same entry in the VFS 1890b57cec5SDimitry Andric // overlay, which is a way to emulate symlink inside the VFS; this is also 1900b57cec5SDimitry Andric // needed for correctness, not doing that can lead to module redefinition 1910b57cec5SDimitry Andric // errors. 192*e8d8bef9SDimitry Andric addFileMapping(Paths.VirtualPath, CacheDst); 1930b57cec5SDimitry Andric return std::error_code(); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric void ModuleDependencyCollector::addFile(StringRef Filename, StringRef FileDst) { 1970b57cec5SDimitry Andric if (insertSeen(Filename)) 1980b57cec5SDimitry Andric if (copyToRoot(Filename, FileDst)) 1990b57cec5SDimitry Andric HasErrors = true; 2000b57cec5SDimitry Andric } 201