1 | //===- Multilib.h -----------------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_CLANG_DRIVER_MULTILIB_H |
10 | #define LLVM_CLANG_DRIVER_MULTILIB_H |
11 | |
12 | #include "clang/Basic/LLVM.h" |
13 | #include "llvm/ADT/ArrayRef.h" |
14 | #include "llvm/ADT/STLExtras.h" |
15 | #include "llvm/ADT/StringRef.h" |
16 | #include "llvm/ADT/StringSet.h" |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/SourceMgr.h" |
19 | #include <cassert> |
20 | #include <functional> |
21 | #include <string> |
22 | #include <utility> |
23 | #include <vector> |
24 | |
25 | namespace clang { |
26 | namespace driver { |
27 | |
28 | /// This corresponds to a single GCC Multilib, or a segment of one controlled |
29 | /// by a command line flag. |
30 | /// See also MultilibBuilder for building a multilib by mutating it |
31 | /// incrementally. |
32 | class Multilib { |
33 | public: |
34 | using flags_list = std::vector<std::string>; |
35 | |
36 | private: |
37 | std::string GCCSuffix; |
38 | std::string OSSuffix; |
39 | std::string IncludeSuffix; |
40 | flags_list Flags; |
41 | |
42 | // Optionally, a multilib can be assigned a string tag indicating that it's |
43 | // part of a group of mutually exclusive possibilities. If two or more |
44 | // multilibs have the same non-empty value of ExclusiveGroup, then only the |
45 | // last matching one of them will be selected. |
46 | // |
47 | // Setting this to the empty string is a special case, indicating that the |
48 | // directory is not mutually exclusive with anything else. |
49 | std::string ExclusiveGroup; |
50 | |
51 | public: |
52 | /// GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the |
53 | /// sysroot string so they must either be empty or begin with a '/' character. |
54 | /// This is enforced with an assert in the constructor. |
55 | Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {}, |
56 | StringRef IncludeSuffix = {}, const flags_list &Flags = flags_list(), |
57 | StringRef ExclusiveGroup = {}); |
58 | |
59 | /// Get the detected GCC installation path suffix for the multi-arch |
60 | /// target variant. Always starts with a '/', unless empty |
61 | const std::string &gccSuffix() const { return GCCSuffix; } |
62 | |
63 | /// Get the detected os path suffix for the multi-arch |
64 | /// target variant. Always starts with a '/', unless empty |
65 | const std::string &osSuffix() const { return OSSuffix; } |
66 | |
67 | /// Get the include directory suffix. Always starts with a '/', unless |
68 | /// empty |
69 | const std::string &includeSuffix() const { return IncludeSuffix; } |
70 | |
71 | /// Get the flags that indicate or contraindicate this multilib's use |
72 | /// All elements begin with either '-' or '!' |
73 | const flags_list &flags() const { return Flags; } |
74 | |
75 | /// Get the exclusive group label. |
76 | const std::string &exclusiveGroup() const { return ExclusiveGroup; } |
77 | |
78 | LLVM_DUMP_METHOD void dump() const; |
79 | /// print summary of the Multilib |
80 | void print(raw_ostream &OS) const; |
81 | |
82 | /// Check whether the default is selected |
83 | bool isDefault() const |
84 | { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); } |
85 | |
86 | bool operator==(const Multilib &Other) const; |
87 | }; |
88 | |
89 | raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); |
90 | |
91 | /// See also MultilibSetBuilder for combining multilibs into a set. |
92 | class MultilibSet { |
93 | public: |
94 | using multilib_list = std::vector<Multilib>; |
95 | using const_iterator = multilib_list::const_iterator; |
96 | using IncludeDirsFunc = |
97 | std::function<std::vector<std::string>(const Multilib &M)>; |
98 | using FilterCallback = llvm::function_ref<bool(const Multilib &)>; |
99 | |
100 | /// Uses regular expressions to simplify flags used for multilib selection. |
101 | /// For example, we may wish both -mfloat-abi=soft and -mfloat-abi=softfp to |
102 | /// be treated as -mfloat-abi=soft. |
103 | struct FlagMatcher { |
104 | std::string Match; |
105 | std::vector<std::string> Flags; |
106 | }; |
107 | |
108 | private: |
109 | multilib_list Multilibs; |
110 | std::vector<FlagMatcher> FlagMatchers; |
111 | IncludeDirsFunc IncludeCallback; |
112 | IncludeDirsFunc FilePathsCallback; |
113 | |
114 | public: |
115 | MultilibSet() = default; |
116 | MultilibSet(multilib_list &&Multilibs, |
117 | std::vector<FlagMatcher> &&FlagMatchers = {}) |
118 | : Multilibs(Multilibs), FlagMatchers(FlagMatchers) {} |
119 | |
120 | const multilib_list &getMultilibs() { return Multilibs; } |
121 | |
122 | /// Filter out some subset of the Multilibs using a user defined callback |
123 | MultilibSet &FilterOut(FilterCallback F); |
124 | |
125 | /// Add a completed Multilib to the set |
126 | void push_back(const Multilib &M); |
127 | |
128 | const_iterator begin() const { return Multilibs.begin(); } |
129 | const_iterator end() const { return Multilibs.end(); } |
130 | |
131 | /// Select compatible variants, \returns false if none are compatible |
132 | bool select(const Multilib::flags_list &Flags, |
133 | llvm::SmallVectorImpl<Multilib> &) const; |
134 | |
135 | unsigned size() const { return Multilibs.size(); } |
136 | |
137 | /// Get the given flags plus flags found by matching them against the |
138 | /// FlagMatchers and choosing the Flags of each accordingly. The select method |
139 | /// calls this method so in most cases it's not necessary to call it directly. |
140 | llvm::StringSet<> expandFlags(const Multilib::flags_list &) const; |
141 | |
142 | LLVM_DUMP_METHOD void dump() const; |
143 | void print(raw_ostream &OS) const; |
144 | |
145 | MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) { |
146 | IncludeCallback = std::move(F); |
147 | return *this; |
148 | } |
149 | |
150 | const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; } |
151 | |
152 | MultilibSet &setFilePathsCallback(IncludeDirsFunc F) { |
153 | FilePathsCallback = std::move(F); |
154 | return *this; |
155 | } |
156 | |
157 | const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; } |
158 | |
159 | static llvm::ErrorOr<MultilibSet> |
160 | parseYaml(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy = nullptr, |
161 | void *DiagHandlerCtxt = nullptr); |
162 | }; |
163 | |
164 | raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); |
165 | |
166 | } // namespace driver |
167 | } // namespace clang |
168 | |
169 | #endif // LLVM_CLANG_DRIVER_MULTILIB_H |
170 | |