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