7#include <QVersionNumber>
26inline QString selectClangResourceDir(
27 const QString& clangDir,
int major,
const QString& fullVersion)
29 const QStringList entries
30 = QDir(clangDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
31 const QString majorName = QString::number(major);
32 if(entries.contains(majorName))
34 if(!fullVersion.isEmpty() && entries.contains(fullVersion))
39 QVersionNumber bestVersion;
40 for(
const QString& e : entries)
42 if(!e.startsWith(majorName +
'.'))
44 const auto v = QVersionNumber::fromString(e);
45 if(best.isEmpty() || v > bestVersion)
56inline QString newestClangResourceDir(
const QString& clangDir)
59 QVersionNumber bestVersion;
60 for(
const QString& e :
61 QDir(clangDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
63 const auto v = QVersionNumber::fromString(e);
66 if(best.isEmpty() || v > bestVersion)
80inline QString findClangRuntimeArchive(
81 const QStringList& roots,
int major,
const QString& fullVersion,
82 const QString& filter,
const QStringList& preferred = {})
84 for(
const QString& root : roots)
86 const QString clangDir = root +
"/lib/clang";
87 const QString version = selectClangResourceDir(clangDir, major, fullVersion);
94 clangDir +
"/" + version, {filter}, QDir::Files,
95 QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
97 found.push_back(it.next());
102 for(
const QString& p : preferred)
103 for(const QString& f : found)
104 if(QString(f).replace(
'\\',
'/').contains(p))
106 return found.front();
113inline QString withoutVendor(
const QString& triple)
115 const QStringList parts = triple.split(
'-');
116 if(parts.size() == 4)
117 return parts[0] +
'-' + parts[2] +
'-' + parts[3];
126inline QString selectMultiarchDir(
127 const QString& includeRoot,
const QString& marker,
128 const std::vector<QString>& triples)
131 for(
const QString& d :
132 QDir(includeRoot).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
133 if(QFileInfo::exists(includeRoot +
"/" + d +
"/" + marker))
136 for(
const QString& t : triples)
138 if(found.contains(t))
140 if(
const QString v = withoutVendor(t); found.contains(v))
143 if(found.size() == 1)
144 return found.front();
154inline std::vector<std::string> buildTreeIncludeArgs(
155 const std::vector<std::string_view>& dirs, std::string_view sourceTree,
156 std::string_view binaryTree,
const std::string& sdkInclude)
158 std::vector<std::string> args;
159 const QString cleanSdkInclude = QDir::cleanPath(QString::fromStdString(sdkInclude));
160 auto add = [&](std::string arg) {
161 if(std::find(args.begin(), args.end(), arg) == args.end())
162 args.push_back(std::move(arg));
165 for(std::string_view dir : dirs)
170 = QDir::cleanPath(QString::fromUtf8(dir.data(), qsizetype(dir.size())));
171 if(clean == cleanSdkInclude)
174 if(clean.endsWith(
".framework"))
176 add(
"-iframework" + QFileInfo(clean).path().toStdString());
180 std::string path(dir);
181 if(path.starts_with(sourceTree) || path.starts_with(binaryTree))
184 add(
"-isystem" + path);
193inline void removeRepeatedDefinitions(std::vector<std::string>& args)
196 std::map<std::string, std::string, std::less<>> defined;
197 std::vector<std::string> out;
198 out.reserve(args.size());
199 for(
auto& arg : args)
201 if(arg.size() > 2 && arg.starts_with(
"-D"))
203 std::string_view def = std::string_view(arg).substr(2);
204 const auto eq = def.find(
'=');
205 std::string name(def.substr(0, eq));
206 std::string value(eq == def.npos ?
"1" : def.substr(eq + 1));
207 if(
auto it = defined.find(name); it != defined.end() && it->second == value)
209 defined[std::move(name)] = std::move(value);
211 else if(arg.size() > 2 && arg.starts_with(
"-U"))
213 defined.erase(arg.substr(2));
215 out.push_back(std::move(arg));
217 args = std::move(out);