1 //===--- Multilib.h ---------------------------------------------*- C++ -*-===// 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 #ifndef LLVM_CLANG_DRIVER_MULTILIB_H 11 #define LLVM_CLANG_DRIVER_MULTILIB_H 12 13 #include "clang/Basic/LLVM.h" 14 #include "llvm/ADT/STLExtras.h" 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/Option/Option.h" 17 #include <functional> 18 #include <string> 19 #include <vector> 20 21 namespace clang { 22 namespace driver { 23 24 /// This corresponds to a single GCC Multilib, or a segment of one controlled 25 /// by a command line flag 26 class Multilib { 27 public: 28 typedef std::vector<std::string> flags_list; 29 30 private: 31 std::string GCCSuffix; 32 std::string OSSuffix; 33 std::string IncludeSuffix; 34 flags_list Flags; 35 36 public: 37 Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "", 38 StringRef IncludeSuffix = ""); 39 40 /// \brief Get the detected GCC installation path suffix for the multi-arch 41 /// target variant. Always starts with a '/', unless empty gccSuffix()42 const std::string &gccSuffix() const { 43 assert(GCCSuffix.empty() || 44 (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); 45 return GCCSuffix; 46 } 47 /// Set the GCC installation path suffix. 48 Multilib &gccSuffix(StringRef S); 49 50 /// \brief Get the detected os path suffix for the multi-arch 51 /// target variant. Always starts with a '/', unless empty osSuffix()52 const std::string &osSuffix() const { 53 assert(OSSuffix.empty() || 54 (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); 55 return OSSuffix; 56 } 57 /// Set the os path suffix. 58 Multilib &osSuffix(StringRef S); 59 60 /// \brief Get the include directory suffix. Always starts with a '/', unless 61 /// empty includeSuffix()62 const std::string &includeSuffix() const { 63 assert(IncludeSuffix.empty() || 64 (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1)); 65 return IncludeSuffix; 66 } 67 /// Set the include directory suffix 68 Multilib &includeSuffix(StringRef S); 69 70 /// \brief Get the flags that indicate or contraindicate this multilib's use 71 /// All elements begin with either '+' or '-' flags()72 const flags_list &flags() const { return Flags; } flags()73 flags_list &flags() { return Flags; } 74 /// Add a flag to the flags list flag(StringRef F)75 Multilib &flag(StringRef F) { 76 assert(F.front() == '+' || F.front() == '-'); 77 Flags.push_back(F); 78 return *this; 79 } 80 81 /// \brief print summary of the Multilib 82 void print(raw_ostream &OS) const; 83 84 /// Check whether any of the 'against' flags contradict the 'for' flags. 85 bool isValid() const; 86 87 /// Check whether the default is selected isDefault()88 bool isDefault() const 89 { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); } 90 91 bool operator==(const Multilib &Other) const; 92 }; 93 94 raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); 95 96 class MultilibSet { 97 public: 98 typedef std::vector<Multilib> multilib_list; 99 typedef multilib_list::iterator iterator; 100 typedef multilib_list::const_iterator const_iterator; 101 102 typedef std::function<std::vector<std::string>( 103 StringRef InstallDir, StringRef Triple, const Multilib &M)> 104 IncludeDirsFunc; 105 106 typedef llvm::function_ref<bool(const Multilib &)> FilterCallback; 107 108 private: 109 multilib_list Multilibs; 110 IncludeDirsFunc IncludeCallback; 111 112 public: MultilibSet()113 MultilibSet() {} 114 115 /// Add an optional Multilib segment 116 MultilibSet &Maybe(const Multilib &M); 117 118 /// Add a set of mutually incompatible Multilib segments 119 MultilibSet &Either(const Multilib &M1, const Multilib &M2); 120 MultilibSet &Either(const Multilib &M1, const Multilib &M2, 121 const Multilib &M3); 122 MultilibSet &Either(const Multilib &M1, const Multilib &M2, 123 const Multilib &M3, const Multilib &M4); 124 MultilibSet &Either(const Multilib &M1, const Multilib &M2, 125 const Multilib &M3, const Multilib &M4, 126 const Multilib &M5); 127 MultilibSet &Either(ArrayRef<Multilib> Ms); 128 129 /// Filter out some subset of the Multilibs using a user defined callback 130 MultilibSet &FilterOut(FilterCallback F); 131 /// Filter out those Multilibs whose gccSuffix matches the given expression 132 MultilibSet &FilterOut(const char *Regex); 133 134 /// Add a completed Multilib to the set 135 void push_back(const Multilib &M); 136 137 /// Union this set of multilibs with another 138 void combineWith(const MultilibSet &MS); 139 140 /// Remove all of thie multilibs from the set clear()141 void clear() { Multilibs.clear(); } 142 begin()143 iterator begin() { return Multilibs.begin(); } begin()144 const_iterator begin() const { return Multilibs.begin(); } 145 end()146 iterator end() { return Multilibs.end(); } end()147 const_iterator end() const { return Multilibs.end(); } 148 149 /// Pick the best multilib in the set, \returns false if none are compatible 150 bool select(const Multilib::flags_list &Flags, Multilib &M) const; 151 size()152 unsigned size() const { return Multilibs.size(); } 153 154 void print(raw_ostream &OS) const; 155 setIncludeDirsCallback(IncludeDirsFunc F)156 MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) { 157 IncludeCallback = std::move(F); 158 return *this; 159 } includeDirsCallback()160 const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; } 161 162 private: 163 /// Apply the filter to Multilibs and return the subset that remains 164 static multilib_list filterCopy(FilterCallback F, const multilib_list &Ms); 165 166 /// Apply the filter to the multilib_list, removing those that don't match 167 static void filterInPlace(FilterCallback F, multilib_list &Ms); 168 }; 169 170 raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); 171 } 172 } 173 174 #endif 175 176