Path: blob/main/contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp
35233 views
//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Basic/DarwinSDKInfo.h"9#include "llvm/Support/ErrorOr.h"10#include "llvm/Support/JSON.h"11#include "llvm/Support/MemoryBuffer.h"12#include "llvm/Support/Path.h"13#include <optional>1415using namespace clang;1617std::optional<VersionTuple> DarwinSDKInfo::RelatedTargetVersionMapping::map(18const VersionTuple &Key, const VersionTuple &MinimumValue,19std::optional<VersionTuple> MaximumValue) const {20if (Key < MinimumKeyVersion)21return MinimumValue;22if (Key > MaximumKeyVersion)23return MaximumValue;24auto KV = Mapping.find(Key.normalize());25if (KV != Mapping.end())26return KV->getSecond();27// If no exact entry found, try just the major key version. Only do so when28// a minor version number is present, to avoid recursing indefinitely into29// the major-only check.30if (Key.getMinor())31return map(VersionTuple(Key.getMajor()), MinimumValue, MaximumValue);32// If this a major only key, return std::nullopt for a missing entry.33return std::nullopt;34}3536std::optional<DarwinSDKInfo::RelatedTargetVersionMapping>37DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(38const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget) {39VersionTuple Min = VersionTuple(std::numeric_limits<unsigned>::max());40VersionTuple Max = VersionTuple(0);41VersionTuple MinValue = Min;42llvm::DenseMap<VersionTuple, VersionTuple> Mapping;43for (const auto &KV : Obj) {44if (auto Val = KV.getSecond().getAsString()) {45llvm::VersionTuple KeyVersion;46llvm::VersionTuple ValueVersion;47if (KeyVersion.tryParse(KV.getFirst()) || ValueVersion.tryParse(*Val))48return std::nullopt;49Mapping[KeyVersion.normalize()] = ValueVersion;50if (KeyVersion < Min)51Min = KeyVersion;52if (KeyVersion > Max)53Max = KeyVersion;54if (ValueVersion < MinValue)55MinValue = ValueVersion;56}57}58if (Mapping.empty())59return std::nullopt;60return RelatedTargetVersionMapping(61Min, Max, MinValue, MaximumDeploymentTarget, std::move(Mapping));62}6364static std::optional<VersionTuple> getVersionKey(const llvm::json::Object &Obj,65StringRef Key) {66auto Value = Obj.getString(Key);67if (!Value)68return std::nullopt;69VersionTuple Version;70if (Version.tryParse(*Value))71return std::nullopt;72return Version;73}7475std::optional<DarwinSDKInfo>76DarwinSDKInfo::parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj) {77auto Version = getVersionKey(*Obj, "Version");78if (!Version)79return std::nullopt;80auto MaximumDeploymentVersion =81getVersionKey(*Obj, "MaximumDeploymentTarget");82if (!MaximumDeploymentVersion)83return std::nullopt;84llvm::DenseMap<OSEnvPair::StorageType,85std::optional<RelatedTargetVersionMapping>>86VersionMappings;87if (const auto *VM = Obj->getObject("VersionMap")) {88// FIXME: Generalize this out beyond iOS-deriving targets.89// Look for ios_<targetos> version mapping for targets that derive from ios.90for (const auto &KV : *VM) {91auto Pair = StringRef(KV.getFirst()).split("_");92if (Pair.first.compare_insensitive("ios") == 0) {93llvm::Triple TT(llvm::Twine("--") + Pair.second.lower());94if (TT.getOS() != llvm::Triple::UnknownOS) {95auto Mapping = RelatedTargetVersionMapping::parseJSON(96*KV.getSecond().getAsObject(), *MaximumDeploymentVersion);97if (Mapping)98VersionMappings[OSEnvPair(llvm::Triple::IOS,99llvm::Triple::UnknownEnvironment,100TT.getOS(),101llvm::Triple::UnknownEnvironment)102.Value] = std::move(Mapping);103}104}105}106107if (const auto *Mapping = VM->getObject("macOS_iOSMac")) {108auto VersionMap = RelatedTargetVersionMapping::parseJSON(109*Mapping, *MaximumDeploymentVersion);110if (!VersionMap)111return std::nullopt;112VersionMappings[OSEnvPair::macOStoMacCatalystPair().Value] =113std::move(VersionMap);114}115if (const auto *Mapping = VM->getObject("iOSMac_macOS")) {116auto VersionMap = RelatedTargetVersionMapping::parseJSON(117*Mapping, *MaximumDeploymentVersion);118if (!VersionMap)119return std::nullopt;120VersionMappings[OSEnvPair::macCatalystToMacOSPair().Value] =121std::move(VersionMap);122}123}124125return DarwinSDKInfo(std::move(*Version),126std::move(*MaximumDeploymentVersion),127std::move(VersionMappings));128}129130Expected<std::optional<DarwinSDKInfo>>131clang::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {132llvm::SmallString<256> Filepath = SDKRootPath;133llvm::sys::path::append(Filepath, "SDKSettings.json");134llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =135VFS.getBufferForFile(Filepath);136if (!File) {137// If the file couldn't be read, assume it just doesn't exist.138return std::nullopt;139}140Expected<llvm::json::Value> Result =141llvm::json::parse(File.get()->getBuffer());142if (!Result)143return Result.takeError();144145if (const auto *Obj = Result->getAsObject()) {146if (auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(Obj))147return std::move(SDKInfo);148}149return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",150llvm::inconvertibleErrorCode());151}152153154