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