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
25namespace clang {
26namespace 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.
32class Multilib {
33public:
34 using flags_list = std::vector<std::string>;
35
36private:
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
51public:
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
89raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
90
91/// See also MultilibSetBuilder for combining multilibs into a set.
92class MultilibSet {
93public:
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
108private:
109 multilib_list Multilibs;
110 std::vector<FlagMatcher> FlagMatchers;
111 IncludeDirsFunc IncludeCallback;
112 IncludeDirsFunc FilePathsCallback;
113
114public:
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
164raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
165
166} // namespace driver
167} // namespace clang
168
169#endif // LLVM_CLANG_DRIVER_MULTILIB_H
170

source code of clang/include/clang/Driver/Multilib.h