10#include "llvm/ADT/StringSwitch.h"
11#include "llvm/Support/ErrorOr.h"
12#include "llvm/Support/JSON.h"
13#include "llvm/Support/MemoryBuffer.h"
14#include "llvm/Support/Path.h"
15#include "llvm/TargetParser/ARMTargetParser.h"
21 const VersionTuple &Key,
const VersionTuple &MinimumValue,
22 std::optional<VersionTuple> MaximumValue)
const {
23 if (Key < MinimumKeyVersion)
25 if (Key > MaximumKeyVersion)
27 auto KV = Mapping.find(Key.normalize());
28 if (KV != Mapping.end())
29 return KV->getSecond();
34 return map(VersionTuple(Key.getMajor()), MinimumValue, MaximumValue);
39std::optional<DarwinSDKInfo::RelatedTargetVersionMapping>
41 const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget) {
42 VersionTuple
Min = VersionTuple(std::numeric_limits<unsigned>::max());
43 VersionTuple
Max = VersionTuple(0);
44 VersionTuple MinValue =
Min;
45 llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
46 for (
const auto &KV : Obj) {
47 if (
auto Val = KV.getSecond().getAsString()) {
48 llvm::VersionTuple KeyVersion;
49 llvm::VersionTuple ValueVersion;
50 if (KeyVersion.tryParse(KV.getFirst()) || ValueVersion.tryParse(*Val))
52 Mapping[KeyVersion.normalize()] = ValueVersion;
57 if (ValueVersion < MinValue)
58 MinValue = ValueVersion;
64 Min,
Max, MinValue, MaximumDeploymentTarget, std::move(Mapping));
67static std::optional<StringRef>
71 auto CanonicalName = Obj.getString(
"CanonicalName");
74 size_t VersionStart = CanonicalName->find_first_of(
"0123456789");
75 return CanonicalName->slice(0, VersionStart);
78static std::pair<llvm::Triple::OSType, llvm::Triple::EnvironmentType>
81 return {llvm::Triple::UnknownOS, llvm::Triple::UnknownEnvironment};
83 llvm::Triple::OSType OS =
84 llvm::StringSwitch<llvm::Triple::OSType>(*XcodePlatform)
85 .Case(
"macosx", llvm::Triple::MacOSX)
86 .Cases({
"iphoneos",
"iphonesimulator"}, llvm::Triple::IOS)
87 .Cases({
"appletvos",
"appletvsimulator"}, llvm::Triple::TvOS)
88 .Cases({
"watchos",
"watchsimulator"}, llvm::Triple::WatchOS)
89 .Case(
"bridgeos", llvm::Triple::BridgeOS)
90 .Cases({
"xros",
"xrsimulator"}, llvm::Triple::XROS)
91 .Case(
"driverkit", llvm::Triple::DriverKit)
92 .Default(llvm::Triple::UnknownOS);
94 llvm::Triple::EnvironmentType Environment =
95 llvm::StringSwitch<llvm::Triple::EnvironmentType>(*XcodePlatform)
96 .Cases({
"iphonesimulator",
"appletvsimulator",
"watchsimulator",
98 llvm::Triple::Simulator)
99 .
Default(llvm::Triple::UnknownEnvironment);
101 return {OS, Environment};
106 llvm::Triple::EnvironmentType SDKEnvironment) {
115 case llvm::Triple::MacOSX:
116 PlatformInfos.push_back({{llvm::Triple(
"x86_64-apple-macosx")},
""});
120 case llvm::Triple::DriverKit:
123 PlatformInfos.push_back(
124 {{llvm::Triple(
"x86_64-apple-driverkit")},
"/System/DriverKit"});
126 case llvm::Triple::IOS:
127 switch (SDKEnvironment) {
128 case llvm::Triple::UnknownEnvironment:
129 PlatformInfos.push_back(
130 {{llvm::Triple(
"armv7-apple-ios"), llvm::Triple(
"armv7s-apple-ios"),
131 llvm::Triple(
"arm64-apple-ios")},
134 case llvm::Triple::Simulator:
135 PlatformInfos.push_back(
136 {{llvm::Triple(
"x86_64-apple-ios-simulator")},
""});
142 case llvm::Triple::TvOS:
143 switch (SDKEnvironment) {
144 case llvm::Triple::UnknownEnvironment:
145 PlatformInfos.push_back({{llvm::Triple(
"arm64-apple-tvos")},
""});
147 case llvm::Triple::Simulator:
148 PlatformInfos.push_back(
149 {{llvm::Triple(
"x86_64-apple-tvos-simulator")},
""});
155 case llvm::Triple::WatchOS:
156 switch (SDKEnvironment) {
157 case llvm::Triple::UnknownEnvironment:
158 PlatformInfos.push_back({{llvm::Triple(
"armv7k-apple-watchos"),
159 llvm::Triple(
"arm64_32-apple-watchos")},
162 case llvm::Triple::Simulator:
163 PlatformInfos.push_back(
164 {{llvm::Triple(
"x86_64-apple-watchos-simulator")},
""});
170 case llvm::Triple::BridgeOS:
171 PlatformInfos.push_back({{llvm::Triple(
"armv7-apple-bridgeos"),
172 llvm::Triple(
"armv7s-apple-bridgeos"),
173 llvm::Triple(
"arm64-apple-bridgeos")},
179 return PlatformInfos;
183 const llvm::json::Object &Obj, std::optional<StringRef> XcodePlatform,
184 llvm::Triple::OSType SDKOS, llvm::Triple::EnvironmentType SDKEnvironment,
185 VersionTuple Version) {
187 auto SupportedTargets = Obj.getObject(
"SupportedTargets");
188 if (!SupportedTargets)
191 for (
const auto &SupportedTargetPair : *SupportedTargets) {
192 const llvm::json::Object *SupportedTarget =
193 SupportedTargetPair.getSecond().getAsObject();
194 if (!SupportedTarget)
197 auto Archs = SupportedTarget->getArray(
"Archs");
198 auto Vendor = SupportedTarget->getString(
"LLVMTargetTripleVendor");
199 auto OS = SupportedTarget->getString(
"LLVMTargetTripleSys");
200 if (!Archs || !Vendor || !OS)
205 SupportedTarget->getString(
"LLVMTargetTripleEnvironment");
206 for (
const auto &ArchValue : *Archs) {
207 if (
auto Arch = ArchValue.getAsString()) {
208 if (Environment && !Environment->empty())
209 Triples.emplace_back(*
Arch, *Vendor, *OS, *Environment);
211 Triples.emplace_back(*
Arch, *Vendor, *OS);
219 StringRef PlatformOrVariant = SupportedTargetPair.getFirst();
221 StringRef EffectivePlatformPrefix;
223 if ((PlatformOrVariant !=
"iosmac") || (Version >= VersionTuple(99))) {
224 auto PlatformPrefix = SupportedTarget->getString(
"SystemPrefix");
225 if (PlatformPrefix) {
226 EffectivePlatformPrefix = *PlatformPrefix;
230 if ((Triples[0].
getOS() == llvm::Triple::DriverKit) &&
231 (Version < VersionTuple(22, 1)))
232 EffectivePlatformPrefix =
"/System/DriverKit";
236 if (PlatformOrVariant == XcodePlatform)
237 PlatformInfos.insert(PlatformInfos.begin(),
238 {std::move(Triples), EffectivePlatformPrefix});
240 PlatformInfos.emplace_back(std::move(Triples), EffectivePlatformPrefix);
242 return PlatformInfos;
245static std::optional<VersionTuple>
getVersionKey(
const llvm::json::Object &Obj,
247 auto Value = Obj.getString(Key);
250 VersionTuple Version;
251 if (Version.tryParse(*
Value))
256std::optional<DarwinSDKInfo>
258 const llvm::json::Object *Obj) {
262 auto MaximumDeploymentVersion =
264 if (!MaximumDeploymentVersion)
267 std::pair<llvm::Triple::OSType, llvm::Triple::EnvironmentType>
270 StringRef DisplayName =
271 Obj->getString(
"DisplayName")
272 .value_or(Obj->getString(
"CanonicalName").value_or(
"<unknown>"));
275 OSAndEnvironment.second, *Version);
276 if (PlatformInfos.empty())
279 std::optional<RelatedTargetVersionMapping>>
281 if (
const auto *VM = Obj->getObject(
"VersionMap")) {
284 for (
const auto &KV : *VM) {
285 auto Pair = StringRef(KV.getFirst()).split(
"_");
286 if (Pair.first.compare_insensitive(
"ios") == 0) {
287 llvm::Triple TT(llvm::Twine(
"--") + Pair.second.lower());
288 if (TT.getOS() != llvm::Triple::UnknownOS) {
290 *KV.getSecond().getAsObject(), *MaximumDeploymentVersion);
292 VersionMappings[
OSEnvPair(llvm::Triple::IOS,
293 llvm::Triple::UnknownEnvironment,
295 llvm::Triple::UnknownEnvironment)
296 .Value] = std::move(Mapping);
301 if (
const auto *Mapping = VM->getObject(
"macOS_iOSMac")) {
303 *Mapping, *MaximumDeploymentVersion);
307 std::move(VersionMap);
309 if (
const auto *Mapping = VM->getObject(
"iOSMac_macOS")) {
311 *Mapping, *MaximumDeploymentVersion);
315 std::move(VersionMap);
319 return DarwinSDKInfo(std::move(FilePath), OSAndEnvironment.first,
320 OSAndEnvironment.second, std::move(*Version),
321 DisplayName, std::move(*MaximumDeploymentVersion),
322 std::move(PlatformInfos), std::move(VersionMappings));
328 llvm::sys::path::append(Filepath,
"SDKSettings.json");
329 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
File =
330 VFS.getBufferForFile(Filepath);
336 llvm::json::parse(
File.get()->getBuffer());
338 return Result.takeError();
340 if (
const auto *Obj =
Result->getAsObject()) {
342 Filepath.str().str(), Obj))
343 return std::move(SDKInfo);
345 return llvm::make_error<llvm::StringError>(
"invalid SDKSettings.json",
346 llvm::inconvertibleErrorCode());
350 llvm::Triple::EnvironmentType Environment,
351 VersionTuple Version, StringRef DisplayName,
352 VersionTuple MaximumDeploymentTarget)
354 MaximumDeploymentTarget,
357static DarwinSDKInfo::PlatformInfoStorageType::const_iterator
359 const llvm::Triple &Triple) {
360 auto PlatformInfoIt = llvm::find_if(
363 const auto &Triples = PlatformInfo.
getTriples();
364 return llvm::find(Triples, Triple) != Triples.end();
375 if (PlatformInfoIt == PlatformInfos.end() &&
376 Triple.getArch() == llvm::Triple::thumb) {
377 StringRef ARMArch = llvm::Triple::getArchName(llvm::Triple::arm);
380 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Triple.getArchName());
381 StringRef SubArch = llvm::ARM::getSubArch(ArchKind);
383 llvm::Triple ARMTriple(Triple);
384 ARMTriple.setArchName((ARMArch + SubArch).str());
385 if (ARMTriple.getArch() != llvm::Triple::thumb) {
393 return PlatformInfoIt;
402 if (PlatformInfoIt != PlatformInfos.end())
403 return PlatformInfoIt->getPlatformPrefix();
407 StringRef PlatformPrefix = PlatformInfos[0].getPlatformPrefix();
408 for (PlatformInfoIt = std::next(PlatformInfos.begin());
409 PlatformInfoIt != PlatformInfos.end(); ++PlatformInfoIt) {
410 if (PlatformInfoIt->getPlatformPrefix() != PlatformPrefix) {
415 return PlatformPrefix;
static DarwinSDKInfo::PlatformInfoStorageType::const_iterator findPlatformInfo(const DarwinSDKInfo::PlatformInfoStorageType &PlatformInfos, const llvm::Triple &Triple)
static DarwinSDKInfo::PlatformInfoStorageType legacyPlatformInfos(llvm::Triple::OSType SDKOS, llvm::Triple::EnvironmentType SDKEnvironment)
static std::optional< StringRef > parseXcodePlatform(const llvm::json::Object &Obj)
static DarwinSDKInfo::PlatformInfoStorageType parsePlatformInfos(const llvm::json::Object &Obj, std::optional< StringRef > XcodePlatform, llvm::Triple::OSType SDKOS, llvm::Triple::EnvironmentType SDKEnvironment, VersionTuple Version)
static std::pair< llvm::Triple::OSType, llvm::Triple::EnvironmentType > parseOSAndEnvironment(std::optional< StringRef > XcodePlatform)
static std::optional< VersionTuple > getVersionKey(const llvm::json::Object &Obj, StringRef Key)
static std::optional< DarwinSDKInfo > parseDarwinSDKSettingsJSON(std::string FilePath, const llvm::json::Object *Obj)
SmallVector< SDKPlatformInfo, 2 > PlatformInfoStorageType
DarwinSDKInfo(std::string FilePath, llvm::Triple::OSType OS, llvm::Triple::EnvironmentType Environment, VersionTuple Version, StringRef DisplayName, VersionTuple MaximumDeploymentTarget, PlatformInfoStorageType PlatformInfos, llvm::DenseMap< OSEnvPair::StorageType, std::optional< RelatedTargetVersionMapping > > VersionMappings=llvm::DenseMap< OSEnvPair::StorageType, std::optional< RelatedTargetVersionMapping > >())
llvm::Triple::OSType getOS() const
StringRef getPlatformPrefix(const llvm::Triple &Triple) const
bool supportsTriple(const llvm::Triple &Triple) const
The JSON file list parser is used to communicate input to InstallAPI.
Expected< std::optional< DarwinSDKInfo > > parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath)
Parse the SDK information from the SDKSettings.json file.
@ Default
Set to the current date and time.
@ Result
The result type of a method or function.
A value that describes two os-environment pairs that can be used as a key to the version map in the S...
static constexpr OSEnvPair macCatalystToMacOSPair()
Returns the os-environment mapping pair that's used to represent the Mac Catalyst -> macOS version ma...
static constexpr OSEnvPair macOStoMacCatalystPair()
Returns the os-environment mapping pair that's used to represent the macOS -> Mac Catalyst version ma...