CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
352 lines
14 KiB
C++
352 lines
14 KiB
C++
//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Basic/DarwinSDKInfo.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
#include "llvm/Support/ErrorOr.h"
|
|
#include "llvm/Support/JSON.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include <optional>
|
|
|
|
using namespace clang;
|
|
|
|
std::optional<VersionTuple> DarwinSDKInfo::RelatedTargetVersionMapping::map(
|
|
const VersionTuple &Key, const VersionTuple &MinimumValue,
|
|
std::optional<VersionTuple> MaximumValue) const {
|
|
if (Key < MinimumKeyVersion)
|
|
return MinimumValue;
|
|
if (Key > MaximumKeyVersion)
|
|
return MaximumValue;
|
|
auto KV = Mapping.find(Key.normalize());
|
|
if (KV != Mapping.end())
|
|
return KV->getSecond();
|
|
// If no exact entry found, try just the major key version. Only do so when
|
|
// a minor version number is present, to avoid recursing indefinitely into
|
|
// the major-only check.
|
|
if (Key.getMinor())
|
|
return map(VersionTuple(Key.getMajor()), MinimumValue, MaximumValue);
|
|
// If this a major only key, return std::nullopt for a missing entry.
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<DarwinSDKInfo::RelatedTargetVersionMapping>
|
|
DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(
|
|
const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget) {
|
|
VersionTuple Min = VersionTuple(std::numeric_limits<unsigned>::max());
|
|
VersionTuple Max = VersionTuple(0);
|
|
VersionTuple MinValue = Min;
|
|
llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
|
|
for (const auto &KV : Obj) {
|
|
if (auto Val = KV.getSecond().getAsString()) {
|
|
llvm::VersionTuple KeyVersion;
|
|
llvm::VersionTuple ValueVersion;
|
|
if (KeyVersion.tryParse(KV.getFirst()) || ValueVersion.tryParse(*Val))
|
|
return std::nullopt;
|
|
Mapping[KeyVersion.normalize()] = ValueVersion;
|
|
if (KeyVersion < Min)
|
|
Min = KeyVersion;
|
|
if (KeyVersion > Max)
|
|
Max = KeyVersion;
|
|
if (ValueVersion < MinValue)
|
|
MinValue = ValueVersion;
|
|
}
|
|
}
|
|
if (Mapping.empty())
|
|
return std::nullopt;
|
|
return RelatedTargetVersionMapping(
|
|
Min, Max, MinValue, MaximumDeploymentTarget, std::move(Mapping));
|
|
}
|
|
|
|
static std::optional<StringRef>
|
|
parseXcodePlatform(const llvm::json::Object &Obj) {
|
|
// The CanonicalName is the Xcode platform followed by a version, e.g.
|
|
// macosx15.0.
|
|
auto CanonicalName = Obj.getString("CanonicalName");
|
|
if (!CanonicalName)
|
|
return std::nullopt;
|
|
size_t VersionStart = CanonicalName->find_first_of("0123456789");
|
|
return CanonicalName->slice(0, VersionStart);
|
|
}
|
|
|
|
static std::pair<llvm::Triple::OSType, llvm::Triple::EnvironmentType>
|
|
parseOSAndEnvironment(std::optional<StringRef> XcodePlatform) {
|
|
if (!XcodePlatform)
|
|
return {llvm::Triple::UnknownOS, llvm::Triple::UnknownEnvironment};
|
|
|
|
llvm::Triple::OSType OS =
|
|
llvm::StringSwitch<llvm::Triple::OSType>(*XcodePlatform)
|
|
.Case("macosx", llvm::Triple::MacOSX)
|
|
.Cases({"iphoneos", "iphonesimulator"}, llvm::Triple::IOS)
|
|
.Cases({"appletvos", "appletvsimulator"}, llvm::Triple::TvOS)
|
|
.Cases({"watchos", "watchsimulator"}, llvm::Triple::WatchOS)
|
|
.Case("bridgeos", llvm::Triple::BridgeOS)
|
|
.Cases({"xros", "xrsimulator"}, llvm::Triple::XROS)
|
|
.Case("driverkit", llvm::Triple::DriverKit)
|
|
.Default(llvm::Triple::UnknownOS);
|
|
|
|
llvm::Triple::EnvironmentType Environment =
|
|
llvm::StringSwitch<llvm::Triple::EnvironmentType>(*XcodePlatform)
|
|
.Cases({"iphonesimulator", "appletvsimulator", "watchsimulator",
|
|
"xrsimulator"},
|
|
llvm::Triple::Simulator)
|
|
.Default(llvm::Triple::UnknownEnvironment);
|
|
|
|
return {OS, Environment};
|
|
}
|
|
|
|
static DarwinSDKInfo::PlatformInfoStorageType
|
|
legacyPlatformInfos(llvm::Triple::OSType SDKOS,
|
|
llvm::Triple::EnvironmentType SDKEnvironment) {
|
|
DarwinSDKInfo::PlatformInfoStorageType PlatformInfos;
|
|
// Synthesize platform infos for older SDKs from the first SDKs with
|
|
// SupportedTargets: macOS 10.15 (DriverKit 19.0), iOS 13.0, tvOS 13.0,
|
|
// watchOS 6.0. Older SDKs (especially iOS) most likely supported armv6 and
|
|
// armv7 architectures that aren't listed here and are difficult to identify
|
|
// from the SDK.
|
|
switch (SDKOS) {
|
|
case llvm::Triple::MacOSX:
|
|
PlatformInfos.push_back({{llvm::Triple("x86_64-apple-macosx")}, ""});
|
|
// macOS 10.15 also has a Mac Catalyst supported target, but Mac Catalyst
|
|
// was new in that version so omit it for older versions.
|
|
break;
|
|
case llvm::Triple::DriverKit:
|
|
// DriverKit 19.0 only had SDKSettings.plist, which isn't used. So this code
|
|
// path is used in 19.x as well, not just earlier versions.
|
|
PlatformInfos.push_back(
|
|
{{llvm::Triple("x86_64-apple-driverkit")}, "/System/DriverKit"});
|
|
break;
|
|
case llvm::Triple::IOS:
|
|
switch (SDKEnvironment) {
|
|
case llvm::Triple::UnknownEnvironment:
|
|
PlatformInfos.push_back(
|
|
{{llvm::Triple("armv7-apple-ios"), llvm::Triple("armv7s-apple-ios"),
|
|
llvm::Triple("arm64-apple-ios")},
|
|
""});
|
|
break;
|
|
case llvm::Triple::Simulator:
|
|
PlatformInfos.push_back(
|
|
{{llvm::Triple("x86_64-apple-ios-simulator")}, ""});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case llvm::Triple::TvOS:
|
|
switch (SDKEnvironment) {
|
|
case llvm::Triple::UnknownEnvironment:
|
|
PlatformInfos.push_back({{llvm::Triple("arm64-apple-tvos")}, ""});
|
|
break;
|
|
case llvm::Triple::Simulator:
|
|
PlatformInfos.push_back(
|
|
{{llvm::Triple("x86_64-apple-tvos-simulator")}, ""});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case llvm::Triple::WatchOS:
|
|
switch (SDKEnvironment) {
|
|
case llvm::Triple::UnknownEnvironment:
|
|
PlatformInfos.push_back({{llvm::Triple("armv7k-apple-watchos"),
|
|
llvm::Triple("arm64_32-apple-watchos")},
|
|
""});
|
|
break;
|
|
case llvm::Triple::Simulator:
|
|
PlatformInfos.push_back(
|
|
{{llvm::Triple("x86_64-apple-watchos-simulator")}, ""});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case llvm::Triple::BridgeOS:
|
|
PlatformInfos.push_back({{llvm::Triple("armv7-apple-bridgeos"),
|
|
llvm::Triple("armv7s-apple-bridgeos"),
|
|
llvm::Triple("arm64-apple-bridgeos")},
|
|
""});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return PlatformInfos;
|
|
}
|
|
|
|
static DarwinSDKInfo::PlatformInfoStorageType parsePlatformInfos(
|
|
const llvm::json::Object &Obj, std::optional<StringRef> XcodePlatform,
|
|
llvm::Triple::OSType SDKOS, llvm::Triple::EnvironmentType SDKEnvironment,
|
|
VersionTuple Version) {
|
|
DarwinSDKInfo::PlatformInfoStorageType PlatformInfos;
|
|
auto SupportedTargets = Obj.getObject("SupportedTargets");
|
|
if (!SupportedTargets)
|
|
return legacyPlatformInfos(SDKOS, SDKEnvironment);
|
|
|
|
for (const auto &SupportedTargetPair : *SupportedTargets) {
|
|
const llvm::json::Object *SupportedTarget =
|
|
SupportedTargetPair.getSecond().getAsObject();
|
|
if (!SupportedTarget)
|
|
continue;
|
|
|
|
auto Archs = SupportedTarget->getArray("Archs");
|
|
auto Vendor = SupportedTarget->getString("LLVMTargetTripleVendor");
|
|
auto OS = SupportedTarget->getString("LLVMTargetTripleSys");
|
|
if (!Archs || !Vendor || !OS)
|
|
continue;
|
|
|
|
DarwinSDKInfo::SDKPlatformInfo::TripleStorageType Triples;
|
|
auto Environment =
|
|
SupportedTarget->getString("LLVMTargetTripleEnvironment");
|
|
for (const auto &ArchValue : *Archs) {
|
|
if (auto Arch = ArchValue.getAsString()) {
|
|
if (Environment)
|
|
Triples.emplace_back(*Arch, *Vendor, *OS, *Environment);
|
|
else
|
|
Triples.emplace_back(*Arch, *Vendor, *OS);
|
|
}
|
|
}
|
|
if (Triples.empty())
|
|
continue;
|
|
|
|
// The key is either the Xcode platform, or a variant. The platform must be
|
|
// the first entry in the returned PlatformInfoStorageType.
|
|
StringRef PlatformOrVariant = SupportedTargetPair.getFirst();
|
|
|
|
StringRef EffectivePlatformPrefix;
|
|
// Ignore iosmac value if it exists.
|
|
if ((PlatformOrVariant != "iosmac") || (Version >= VersionTuple(99))) {
|
|
auto PlatformPrefix = SupportedTarget->getString("SystemPrefix");
|
|
if (PlatformPrefix) {
|
|
EffectivePlatformPrefix = *PlatformPrefix;
|
|
} else {
|
|
// Older SDKs don't have SystemPrefix in SupportedTargets, manually add
|
|
// their prefixes.
|
|
if ((Triples[0].getOS() == llvm::Triple::DriverKit) &&
|
|
(Version < VersionTuple(22, 1)))
|
|
EffectivePlatformPrefix = "/System/DriverKit";
|
|
}
|
|
}
|
|
|
|
if (PlatformOrVariant == XcodePlatform)
|
|
PlatformInfos.insert(PlatformInfos.begin(),
|
|
{std::move(Triples), EffectivePlatformPrefix});
|
|
else
|
|
PlatformInfos.emplace_back(std::move(Triples), EffectivePlatformPrefix);
|
|
}
|
|
return PlatformInfos;
|
|
}
|
|
|
|
static std::optional<VersionTuple> getVersionKey(const llvm::json::Object &Obj,
|
|
StringRef Key) {
|
|
auto Value = Obj.getString(Key);
|
|
if (!Value)
|
|
return std::nullopt;
|
|
VersionTuple Version;
|
|
if (Version.tryParse(*Value))
|
|
return std::nullopt;
|
|
return Version;
|
|
}
|
|
|
|
std::optional<DarwinSDKInfo>
|
|
DarwinSDKInfo::parseDarwinSDKSettingsJSON(std::string FilePath,
|
|
const llvm::json::Object *Obj) {
|
|
auto Version = getVersionKey(*Obj, "Version");
|
|
if (!Version)
|
|
return std::nullopt;
|
|
auto MaximumDeploymentVersion =
|
|
getVersionKey(*Obj, "MaximumDeploymentTarget");
|
|
if (!MaximumDeploymentVersion)
|
|
return std::nullopt;
|
|
std::optional<StringRef> XcodePlatform = parseXcodePlatform(*Obj);
|
|
std::pair<llvm::Triple::OSType, llvm::Triple::EnvironmentType>
|
|
OSAndEnvironment = parseOSAndEnvironment(XcodePlatform);
|
|
// DisplayName should always be present, but don't require it.
|
|
StringRef DisplayName =
|
|
Obj->getString("DisplayName")
|
|
.value_or(Obj->getString("CanonicalName").value_or("<unknown>"));
|
|
PlatformInfoStorageType PlatformInfos =
|
|
parsePlatformInfos(*Obj, XcodePlatform, OSAndEnvironment.first,
|
|
OSAndEnvironment.second, *Version);
|
|
llvm::DenseMap<OSEnvPair::StorageType,
|
|
std::optional<RelatedTargetVersionMapping>>
|
|
VersionMappings;
|
|
if (const auto *VM = Obj->getObject("VersionMap")) {
|
|
// FIXME: Generalize this out beyond iOS-deriving targets.
|
|
// Look for ios_<targetos> version mapping for targets that derive from ios.
|
|
for (const auto &KV : *VM) {
|
|
auto Pair = StringRef(KV.getFirst()).split("_");
|
|
if (Pair.first.compare_insensitive("ios") == 0) {
|
|
llvm::Triple TT(llvm::Twine("--") + Pair.second.lower());
|
|
if (TT.getOS() != llvm::Triple::UnknownOS) {
|
|
auto Mapping = RelatedTargetVersionMapping::parseJSON(
|
|
*KV.getSecond().getAsObject(), *MaximumDeploymentVersion);
|
|
if (Mapping)
|
|
VersionMappings[OSEnvPair(llvm::Triple::IOS,
|
|
llvm::Triple::UnknownEnvironment,
|
|
TT.getOS(),
|
|
llvm::Triple::UnknownEnvironment)
|
|
.Value] = std::move(Mapping);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (const auto *Mapping = VM->getObject("macOS_iOSMac")) {
|
|
auto VersionMap = RelatedTargetVersionMapping::parseJSON(
|
|
*Mapping, *MaximumDeploymentVersion);
|
|
if (!VersionMap)
|
|
return std::nullopt;
|
|
VersionMappings[OSEnvPair::macOStoMacCatalystPair().Value] =
|
|
std::move(VersionMap);
|
|
}
|
|
if (const auto *Mapping = VM->getObject("iOSMac_macOS")) {
|
|
auto VersionMap = RelatedTargetVersionMapping::parseJSON(
|
|
*Mapping, *MaximumDeploymentVersion);
|
|
if (!VersionMap)
|
|
return std::nullopt;
|
|
VersionMappings[OSEnvPair::macCatalystToMacOSPair().Value] =
|
|
std::move(VersionMap);
|
|
}
|
|
}
|
|
|
|
return DarwinSDKInfo(std::move(FilePath), OSAndEnvironment.first,
|
|
OSAndEnvironment.second, std::move(*Version),
|
|
DisplayName, std::move(*MaximumDeploymentVersion),
|
|
std::move(PlatformInfos), std::move(VersionMappings));
|
|
}
|
|
|
|
Expected<std::optional<DarwinSDKInfo>>
|
|
clang::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
|
|
llvm::SmallString<256> Filepath = SDKRootPath;
|
|
llvm::sys::path::append(Filepath, "SDKSettings.json");
|
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
|
|
VFS.getBufferForFile(Filepath);
|
|
if (!File) {
|
|
// If the file couldn't be read, assume it just doesn't exist.
|
|
return std::nullopt;
|
|
}
|
|
Expected<llvm::json::Value> Result =
|
|
llvm::json::parse(File.get()->getBuffer());
|
|
if (!Result)
|
|
return Result.takeError();
|
|
|
|
if (const auto *Obj = Result->getAsObject()) {
|
|
if (auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(
|
|
Filepath.str().str(), Obj))
|
|
return std::move(SDKInfo);
|
|
}
|
|
return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
|
|
llvm::inconvertibleErrorCode());
|
|
}
|
|
|
|
DarwinSDKInfo::DarwinSDKInfo(llvm::Triple::OSType OS,
|
|
llvm::Triple::EnvironmentType Environment,
|
|
VersionTuple Version, StringRef DisplayName,
|
|
VersionTuple MaximumDeploymentTarget)
|
|
: DarwinSDKInfo("", OS, Environment, Version, DisplayName,
|
|
MaximumDeploymentTarget,
|
|
legacyPlatformInfos(OS, Environment)) {}
|