clang  19.0.0git
DarwinSDKInfo.cpp
Go to the documentation of this file.
1 //===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/Support/ErrorOr.h"
11 #include "llvm/Support/JSON.h"
12 #include "llvm/Support/MemoryBuffer.h"
13 #include "llvm/Support/Path.h"
14 #include <optional>
15 
16 using namespace clang;
17 
19  const VersionTuple &Key, const VersionTuple &MinimumValue,
20  std::optional<VersionTuple> MaximumValue) const {
21  if (Key < MinimumKeyVersion)
22  return MinimumValue;
23  if (Key > MaximumKeyVersion)
24  return MaximumValue;
25  auto KV = Mapping.find(Key.normalize());
26  if (KV != Mapping.end())
27  return KV->getSecond();
28  // If no exact entry found, try just the major key version. Only do so when
29  // a minor version number is present, to avoid recursing indefinitely into
30  // the major-only check.
31  if (Key.getMinor())
32  return map(VersionTuple(Key.getMajor()), MinimumValue, MaximumValue);
33  // If this a major only key, return std::nullopt for a missing entry.
34  return std::nullopt;
35 }
36 
37 std::optional<DarwinSDKInfo::RelatedTargetVersionMapping>
39  const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget) {
40  VersionTuple Min = VersionTuple(std::numeric_limits<unsigned>::max());
41  VersionTuple Max = VersionTuple(0);
42  VersionTuple MinValue = Min;
43  llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
44  for (const auto &KV : Obj) {
45  if (auto Val = KV.getSecond().getAsString()) {
46  llvm::VersionTuple KeyVersion;
47  llvm::VersionTuple ValueVersion;
48  if (KeyVersion.tryParse(KV.getFirst()) || ValueVersion.tryParse(*Val))
49  return std::nullopt;
50  Mapping[KeyVersion.normalize()] = ValueVersion;
51  if (KeyVersion < Min)
52  Min = KeyVersion;
53  if (KeyVersion > Max)
54  Max = KeyVersion;
55  if (ValueVersion < MinValue)
56  MinValue = ValueVersion;
57  }
58  }
59  if (Mapping.empty())
60  return std::nullopt;
62  Min, Max, MinValue, MaximumDeploymentTarget, std::move(Mapping));
63 }
64 
65 static std::optional<VersionTuple> getVersionKey(const llvm::json::Object &Obj,
66  StringRef Key) {
67  auto Value = Obj.getString(Key);
68  if (!Value)
69  return std::nullopt;
70  VersionTuple Version;
71  if (Version.tryParse(*Value))
72  return std::nullopt;
73  return Version;
74 }
75 
76 std::optional<DarwinSDKInfo>
77 DarwinSDKInfo::parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj) {
78  auto Version = getVersionKey(*Obj, "Version");
79  if (!Version)
80  return std::nullopt;
81  auto MaximumDeploymentVersion =
82  getVersionKey(*Obj, "MaximumDeploymentTarget");
83  if (!MaximumDeploymentVersion)
84  return std::nullopt;
85  llvm::DenseMap<OSEnvPair::StorageType,
86  std::optional<RelatedTargetVersionMapping>>
87  VersionMappings;
88  if (const auto *VM = Obj->getObject("VersionMap")) {
89  // FIXME: Generalize this out beyond iOS-deriving targets.
90  // Look for ios_<targetos> version mapping for targets that derive from ios.
91  for (const auto &KV : *VM) {
92  auto Pair = StringRef(KV.getFirst()).split("_");
93  if (Pair.first.compare_insensitive("ios") == 0) {
94  llvm::Triple TT(llvm::Twine("--") + Pair.second.lower());
95  if (TT.getOS() != llvm::Triple::UnknownOS) {
97  *KV.getSecond().getAsObject(), *MaximumDeploymentVersion);
98  if (Mapping)
99  VersionMappings[OSEnvPair(llvm::Triple::IOS,
100  llvm::Triple::UnknownEnvironment,
101  TT.getOS(),
102  llvm::Triple::UnknownEnvironment)
103  .Value] = std::move(Mapping);
104  }
105  }
106  }
107 
108  if (const auto *Mapping = VM->getObject("macOS_iOSMac")) {
109  auto VersionMap = RelatedTargetVersionMapping::parseJSON(
110  *Mapping, *MaximumDeploymentVersion);
111  if (!VersionMap)
112  return std::nullopt;
113  VersionMappings[OSEnvPair::macOStoMacCatalystPair().Value] =
114  std::move(VersionMap);
115  }
116  if (const auto *Mapping = VM->getObject("iOSMac_macOS")) {
117  auto VersionMap = RelatedTargetVersionMapping::parseJSON(
118  *Mapping, *MaximumDeploymentVersion);
119  if (!VersionMap)
120  return std::nullopt;
121  VersionMappings[OSEnvPair::macCatalystToMacOSPair().Value] =
122  std::move(VersionMap);
123  }
124  }
125 
126  return DarwinSDKInfo(std::move(*Version),
127  std::move(*MaximumDeploymentVersion),
128  std::move(VersionMappings));
129 }
130 
132 clang::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
133  llvm::SmallString<256> Filepath = SDKRootPath;
134  llvm::sys::path::append(Filepath, "SDKSettings.json");
135  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
136  VFS.getBufferForFile(Filepath);
137  if (!File) {
138  // If the file couldn't be read, assume it just doesn't exist.
139  return std::nullopt;
140  }
142  llvm::json::parse(File.get()->getBuffer());
143  if (!Result)
144  return Result.takeError();
145 
146  if (const auto *Obj = Result->getAsObject()) {
147  if (auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(Obj))
148  return std::move(SDKInfo);
149  }
150  return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
151  llvm::inconvertibleErrorCode());
152 }
static std::optional< VersionTuple > getVersionKey(const llvm::json::Object &Obj, StringRef Key)
__DEVICE__ int max(int __a, int __b)
Represents a version mapping that maps from a version of one target to a version of a related target.
Definition: DarwinSDKInfo.h:86
std::optional< VersionTuple > map(const VersionTuple &Key, const VersionTuple &MinimumValue, std::optional< VersionTuple > MaximumValue) const
Returns the mapped key, or the appropriate Minimum / MaximumValue if they key is outside of the mappi...
static std::optional< RelatedTargetVersionMapping > parseJSON(const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget)
DarwinSDKInfo(VersionTuple Version, VersionTuple MaximumDeploymentTarget, llvm::DenseMap< OSEnvPair::StorageType, std::optional< RelatedTargetVersionMapping >> VersionMappings=llvm::DenseMap< OSEnvPair::StorageType, std::optional< RelatedTargetVersionMapping >>())
static std::optional< DarwinSDKInfo > parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj)
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.
A value that describes two os-environment pairs that can be used as a key to the version map in the S...
Definition: DarwinSDKInfo.h:33
static constexpr OSEnvPair macCatalystToMacOSPair()
Returns the os-environment mapping pair that's used to represent the Mac Catalyst -> macOS version ma...
Definition: DarwinSDKInfo.h:56
static constexpr OSEnvPair macOStoMacCatalystPair()
Returns the os-environment mapping pair that's used to represent the macOS -> Mac Catalyst version ma...
Definition: DarwinSDKInfo.h:49