Multilib.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Multilib.h -----------------------------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_DRIVER_MULTILIB_H
  14. #define LLVM_CLANG_DRIVER_MULTILIB_H
  15. #include "clang/Basic/LLVM.h"
  16. #include "llvm/ADT/ArrayRef.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/Support/Compiler.h"
  20. #include <cassert>
  21. #include <functional>
  22. #include <string>
  23. #include <utility>
  24. #include <vector>
  25. namespace clang {
  26. namespace driver {
  27. /// This corresponds to a single GCC Multilib, or a segment of one controlled
  28. /// by a command line flag
  29. class Multilib {
  30. public:
  31. using flags_list = std::vector<std::string>;
  32. private:
  33. std::string GCCSuffix;
  34. std::string OSSuffix;
  35. std::string IncludeSuffix;
  36. flags_list Flags;
  37. int Priority;
  38. public:
  39. Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
  40. StringRef IncludeSuffix = {}, int Priority = 0);
  41. /// Get the detected GCC installation path suffix for the multi-arch
  42. /// target variant. Always starts with a '/', unless empty
  43. const std::string &gccSuffix() const {
  44. assert(GCCSuffix.empty() ||
  45. (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
  46. return GCCSuffix;
  47. }
  48. /// Set the GCC installation path suffix.
  49. Multilib &gccSuffix(StringRef S);
  50. /// Get the detected os path suffix for the multi-arch
  51. /// target variant. Always starts with a '/', unless empty
  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. /// Get the include directory suffix. Always starts with a '/', unless
  60. /// empty
  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. /// 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. /// Returns the multilib priority. When more than one multilib matches flags,
  73. /// the one with the highest priority is selected, with 0 being the default.
  74. int priority() const { return Priority; }
  75. /// Add a flag to the flags list
  76. /// \p Flag must be a flag accepted by the driver with its leading '-' removed,
  77. /// and replaced with either:
  78. /// '-' which contraindicates using this multilib with that flag
  79. /// or:
  80. /// '+' which promotes using this multilib in the presence of that flag
  81. /// otherwise '-print-multi-lib' will not emit them correctly.
  82. Multilib &flag(StringRef F) {
  83. assert(F.front() == '+' || F.front() == '-');
  84. Flags.push_back(std::string(F));
  85. return *this;
  86. }
  87. LLVM_DUMP_METHOD void dump() const;
  88. /// print summary of the Multilib
  89. void print(raw_ostream &OS) const;
  90. /// Check whether any of the 'against' flags contradict the 'for' flags.
  91. bool isValid() const;
  92. /// Check whether the default is selected
  93. bool isDefault() const
  94. { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); }
  95. bool operator==(const Multilib &Other) const;
  96. };
  97. raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
  98. class MultilibSet {
  99. public:
  100. using multilib_list = std::vector<Multilib>;
  101. using iterator = multilib_list::iterator;
  102. using const_iterator = multilib_list::const_iterator;
  103. using IncludeDirsFunc =
  104. std::function<std::vector<std::string>(const Multilib &M)>;
  105. using FilterCallback = llvm::function_ref<bool(const Multilib &)>;
  106. private:
  107. multilib_list Multilibs;
  108. IncludeDirsFunc IncludeCallback;
  109. IncludeDirsFunc FilePathsCallback;
  110. public:
  111. MultilibSet() = default;
  112. /// Add an optional Multilib segment
  113. MultilibSet &Maybe(const Multilib &M);
  114. /// Add a set of mutually incompatible Multilib segments
  115. MultilibSet &Either(const Multilib &M1, const Multilib &M2);
  116. MultilibSet &Either(const Multilib &M1, const Multilib &M2,
  117. const Multilib &M3);
  118. MultilibSet &Either(const Multilib &M1, const Multilib &M2,
  119. const Multilib &M3, const Multilib &M4);
  120. MultilibSet &Either(const Multilib &M1, const Multilib &M2,
  121. const Multilib &M3, const Multilib &M4,
  122. const Multilib &M5);
  123. MultilibSet &Either(ArrayRef<Multilib> Ms);
  124. /// Filter out some subset of the Multilibs using a user defined callback
  125. MultilibSet &FilterOut(FilterCallback F);
  126. /// Filter out those Multilibs whose gccSuffix matches the given expression
  127. MultilibSet &FilterOut(const char *Regex);
  128. /// Add a completed Multilib to the set
  129. void push_back(const Multilib &M);
  130. /// Union this set of multilibs with another
  131. void combineWith(const MultilibSet &MS);
  132. /// Remove all of the multilibs from the set
  133. void clear() { Multilibs.clear(); }
  134. iterator begin() { return Multilibs.begin(); }
  135. const_iterator begin() const { return Multilibs.begin(); }
  136. iterator end() { return Multilibs.end(); }
  137. const_iterator end() const { return Multilibs.end(); }
  138. /// Pick the best multilib in the set, \returns false if none are compatible
  139. bool select(const Multilib::flags_list &Flags, Multilib &M) const;
  140. unsigned size() const { return Multilibs.size(); }
  141. LLVM_DUMP_METHOD void dump() const;
  142. void print(raw_ostream &OS) const;
  143. MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) {
  144. IncludeCallback = std::move(F);
  145. return *this;
  146. }
  147. const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; }
  148. MultilibSet &setFilePathsCallback(IncludeDirsFunc F) {
  149. FilePathsCallback = std::move(F);
  150. return *this;
  151. }
  152. const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; }
  153. private:
  154. /// Apply the filter to Multilibs and return the subset that remains
  155. static multilib_list filterCopy(FilterCallback F, const multilib_list &Ms);
  156. /// Apply the filter to the multilib_list, removing those that don't match
  157. static void filterInPlace(FilterCallback F, multilib_list &Ms);
  158. };
  159. raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
  160. } // namespace driver
  161. } // namespace clang
  162. #endif // LLVM_CLANG_DRIVER_MULTILIB_H
  163. #ifdef __GNUC__
  164. #pragma GCC diagnostic pop
  165. #endif