1 //===--- extra/modularize/ModularizeUtilities.cpp -------------------===// 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 // This file implements a class for loading and validating a module map or 11 // header list by checking that all headers in the corresponding directories 12 // are accounted for. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "ModularizeUtilities.h" 17 #include "llvm/ADT/SmallString.h" 18 #include "llvm/Support/FileUtilities.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 #include "llvm/Support/Path.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 using namespace llvm; 24 using namespace Modularize; 25 26 // ModularizeUtilities class implementation. 27 28 // Constructor. 29 ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths, 30 llvm::StringRef Prefix) 31 : InputFilePaths(InputPaths), 32 HeaderPrefix(Prefix) {} 33 34 // Create instance of ModularizeUtilities, to simplify setting up 35 // subordinate objects. 36 ModularizeUtilities *ModularizeUtilities::createModularizeUtilities( 37 std::vector<std::string> &InputPaths, llvm::StringRef Prefix) { 38 39 return new ModularizeUtilities(InputPaths, Prefix); 40 } 41 42 // Load all header lists and dependencies. 43 std::error_code ModularizeUtilities::loadAllHeaderListsAndDependencies() { 44 typedef std::vector<std::string>::iterator Iter; 45 for (Iter I = InputFilePaths.begin(), E = InputFilePaths.end(); I != E; ++I) { 46 if (std::error_code EC = loadSingleHeaderListsAndDependencies(*I)) { 47 errs() << "modularize: error: Unable to get header list '" << *I 48 << "': " << EC.message() << '\n'; 49 return EC; 50 } 51 } 52 return std::error_code(); 53 } 54 55 // Load single header list and dependencies. 56 std::error_code ModularizeUtilities::loadSingleHeaderListsAndDependencies( 57 llvm::StringRef InputPath) { 58 59 // By default, use the path component of the list file name. 60 SmallString<256> HeaderDirectory(InputPath); 61 llvm::sys::path::remove_filename(HeaderDirectory); 62 SmallString<256> CurrentDirectory; 63 llvm::sys::fs::current_path(CurrentDirectory); 64 65 // Get the prefix if we have one. 66 if (HeaderPrefix.size() != 0) 67 HeaderDirectory = HeaderPrefix; 68 69 // Read the header list file into a buffer. 70 ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer = 71 MemoryBuffer::getFile(InputPath); 72 if (std::error_code EC = listBuffer.getError()) 73 return EC; 74 75 // Parse the header list into strings. 76 SmallVector<StringRef, 32> Strings; 77 listBuffer.get()->getBuffer().split(Strings, "\n", -1, false); 78 79 // Collect the header file names from the string list. 80 for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(), 81 E = Strings.end(); 82 I != E; ++I) { 83 StringRef Line = I->trim(); 84 // Ignore comments and empty lines. 85 if (Line.empty() || (Line[0] == '#')) 86 continue; 87 std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':'); 88 SmallString<256> HeaderFileName; 89 // Prepend header file name prefix if it's not absolute. 90 if (llvm::sys::path::is_absolute(TargetAndDependents.first)) 91 llvm::sys::path::native(TargetAndDependents.first, HeaderFileName); 92 else { 93 if (HeaderDirectory.size() != 0) 94 HeaderFileName = HeaderDirectory; 95 else 96 HeaderFileName = CurrentDirectory; 97 llvm::sys::path::append(HeaderFileName, TargetAndDependents.first); 98 llvm::sys::path::native(HeaderFileName); 99 } 100 // Handle optional dependencies. 101 DependentsVector Dependents; 102 SmallVector<StringRef, 4> DependentsList; 103 TargetAndDependents.second.split(DependentsList, " ", -1, false); 104 int Count = DependentsList.size(); 105 for (int Index = 0; Index < Count; ++Index) { 106 SmallString<256> Dependent; 107 if (llvm::sys::path::is_absolute(DependentsList[Index])) 108 Dependent = DependentsList[Index]; 109 else { 110 if (HeaderDirectory.size() != 0) 111 Dependent = HeaderDirectory; 112 else 113 Dependent = CurrentDirectory; 114 llvm::sys::path::append(Dependent, DependentsList[Index]); 115 } 116 llvm::sys::path::native(Dependent); 117 Dependents.push_back(Dependent.str()); 118 } 119 // Save the resulting header file path and dependencies. 120 HeaderFileNames.push_back(HeaderFileName.str()); 121 Dependencies[HeaderFileName.str()] = Dependents; 122 } 123 return std::error_code(); 124 } 125