1 //===- MultilibBuilder.cpp - MultilibBuilder Implementation -===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Driver/MultilibBuilder.h"
10 #include "ToolChains/CommonArgs.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/Support/Path.h"
14 #include "llvm/Support/Regex.h"
15 #include "llvm/Support/raw_ostream.h"
17 using namespace clang
;
18 using namespace driver
;
20 /// normalize Segment to "/foo/bar" or "".
21 static void normalizePathSegment(std::string
&Segment
) {
22 StringRef seg
= Segment
;
24 // Prune trailing "/" or "./"
26 StringRef last
= llvm::sys::path::filename(seg
);
29 seg
= llvm::sys::path::parent_path(seg
);
32 if (seg
.empty() || seg
== "/") {
38 if (seg
.front() != '/') {
39 Segment
= "/" + seg
.str();
41 Segment
= std::string(seg
);
45 MultilibBuilder::MultilibBuilder(StringRef GCC
, StringRef OS
, StringRef Include
)
46 : GCCSuffix(GCC
), OSSuffix(OS
), IncludeSuffix(Include
) {
47 normalizePathSegment(GCCSuffix
);
48 normalizePathSegment(OSSuffix
);
49 normalizePathSegment(IncludeSuffix
);
52 MultilibBuilder::MultilibBuilder(StringRef Suffix
)
53 : MultilibBuilder(Suffix
, Suffix
, Suffix
) {}
55 MultilibBuilder
&MultilibBuilder::gccSuffix(StringRef S
) {
56 GCCSuffix
= std::string(S
);
57 normalizePathSegment(GCCSuffix
);
61 MultilibBuilder
&MultilibBuilder::osSuffix(StringRef S
) {
62 OSSuffix
= std::string(S
);
63 normalizePathSegment(OSSuffix
);
67 MultilibBuilder
&MultilibBuilder::includeSuffix(StringRef S
) {
68 IncludeSuffix
= std::string(S
);
69 normalizePathSegment(IncludeSuffix
);
73 bool MultilibBuilder::isValid() const {
74 llvm::StringMap
<int> FlagSet
;
75 for (unsigned I
= 0, N
= Flags
.size(); I
!= N
; ++I
) {
76 StringRef
Flag(Flags
[I
]);
77 llvm::StringMap
<int>::iterator SI
= FlagSet
.find(Flag
.substr(1));
79 assert(StringRef(Flag
).front() == '-' || StringRef(Flag
).front() == '!');
81 if (SI
== FlagSet
.end())
82 FlagSet
[Flag
.substr(1)] = I
;
83 else if (Flags
[I
] != Flags
[SI
->getValue()])
89 MultilibBuilder
&MultilibBuilder::flag(StringRef Flag
, bool Disallow
) {
90 tools::addMultilibFlag(!Disallow
, Flag
, Flags
);
94 Multilib
MultilibBuilder::makeMultilib() const {
95 return Multilib(GCCSuffix
, OSSuffix
, IncludeSuffix
, Flags
);
98 MultilibSetBuilder
&MultilibSetBuilder::Maybe(const MultilibBuilder
&M
) {
99 MultilibBuilder Opposite
;
100 // Negate positive flags
101 for (StringRef Flag
: M
.flags()) {
102 if (Flag
.front() == '-')
103 Opposite
.flag(Flag
, /*Disallow=*/true);
105 return Either(M
, Opposite
);
108 MultilibSetBuilder
&MultilibSetBuilder::Either(const MultilibBuilder
&M1
,
109 const MultilibBuilder
&M2
) {
110 return Either({M1
, M2
});
113 MultilibSetBuilder
&MultilibSetBuilder::Either(const MultilibBuilder
&M1
,
114 const MultilibBuilder
&M2
,
115 const MultilibBuilder
&M3
) {
116 return Either({M1
, M2
, M3
});
119 MultilibSetBuilder
&MultilibSetBuilder::Either(const MultilibBuilder
&M1
,
120 const MultilibBuilder
&M2
,
121 const MultilibBuilder
&M3
,
122 const MultilibBuilder
&M4
) {
123 return Either({M1
, M2
, M3
, M4
});
126 MultilibSetBuilder
&MultilibSetBuilder::Either(const MultilibBuilder
&M1
,
127 const MultilibBuilder
&M2
,
128 const MultilibBuilder
&M3
,
129 const MultilibBuilder
&M4
,
130 const MultilibBuilder
&M5
) {
131 return Either({M1
, M2
, M3
, M4
, M5
});
134 static MultilibBuilder
compose(const MultilibBuilder
&Base
,
135 const MultilibBuilder
&New
) {
136 SmallString
<128> GCCSuffix
;
137 llvm::sys::path::append(GCCSuffix
, "/", Base
.gccSuffix(), New
.gccSuffix());
138 SmallString
<128> OSSuffix
;
139 llvm::sys::path::append(OSSuffix
, "/", Base
.osSuffix(), New
.osSuffix());
140 SmallString
<128> IncludeSuffix
;
141 llvm::sys::path::append(IncludeSuffix
, "/", Base
.includeSuffix(),
142 New
.includeSuffix());
144 MultilibBuilder
Composed(GCCSuffix
, OSSuffix
, IncludeSuffix
);
146 MultilibBuilder::flags_list
&Flags
= Composed
.flags();
148 Flags
.insert(Flags
.end(), Base
.flags().begin(), Base
.flags().end());
149 Flags
.insert(Flags
.end(), New
.flags().begin(), New
.flags().end());
155 MultilibSetBuilder::Either(ArrayRef
<MultilibBuilder
> MultilibSegments
) {
156 multilib_list Composed
;
158 if (Multilibs
.empty())
159 Multilibs
.insert(Multilibs
.end(), MultilibSegments
.begin(),
160 MultilibSegments
.end());
162 for (const auto &New
: MultilibSegments
) {
163 for (const auto &Base
: Multilibs
) {
164 MultilibBuilder MO
= compose(Base
, New
);
166 Composed
.push_back(MO
);
170 Multilibs
= Composed
;
176 MultilibSetBuilder
&MultilibSetBuilder::FilterOut(const char *Regex
) {
177 llvm::Regex
R(Regex
);
180 if (!R
.isValid(Error
)) {
181 llvm::errs() << Error
;
182 llvm_unreachable("Invalid regex!");
185 llvm::erase_if(Multilibs
, [&R
](const MultilibBuilder
&M
) {
186 return R
.match(M
.gccSuffix());
191 MultilibSet
MultilibSetBuilder::makeMultilibSet() const {
193 for (const auto &M
: Multilibs
) {
194 Result
.push_back(M
.makeMultilib());