1//===--- DarwinSDKInfo.h - SDK Information parser for darwin ----*- C++ -*-===//
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
9#ifndef LLVM_CLANG_BASIC_DARWINSDKINFO_H
10#define LLVM_CLANG_BASIC_DARWINSDKINFO_H
11
12#include "clang/Basic/LLVM.h"
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/Support/Error.h"
15#include "llvm/Support/VersionTuple.h"
16#include "llvm/Support/VirtualFileSystem.h"
17#include "llvm/TargetParser/Triple.h"
18#include <optional>
19
20namespace llvm {
21namespace json {
22class Object;
23} // end namespace json
24} // end namespace llvm
25
26namespace clang {
27
28/// The information about the darwin SDK that was used during this compilation.
29class DarwinSDKInfo {
30public:
31 /// A value that describes two os-environment pairs that can be used as a key
32 /// to the version map in the SDK.
33 struct OSEnvPair {
34 public:
35 using StorageType = uint64_t;
36
37 constexpr OSEnvPair(llvm::Triple::OSType FromOS,
38 llvm::Triple::EnvironmentType FromEnv,
39 llvm::Triple::OSType ToOS,
40 llvm::Triple::EnvironmentType ToEnv)
41 : Value(((StorageType(FromOS) * StorageType(llvm::Triple::LastOSType) +
42 StorageType(FromEnv))
43 << 32ull) |
44 (StorageType(ToOS) * StorageType(llvm::Triple::LastOSType) +
45 StorageType(ToEnv))) {}
46
47 /// Returns the os-environment mapping pair that's used to represent the
48 /// macOS -> Mac Catalyst version mapping.
49 static inline constexpr OSEnvPair macOStoMacCatalystPair() {
50 return OSEnvPair(llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment,
51 llvm::Triple::IOS, llvm::Triple::MacABI);
52 }
53
54 /// Returns the os-environment mapping pair that's used to represent the
55 /// Mac Catalyst -> macOS version mapping.
56 static inline constexpr OSEnvPair macCatalystToMacOSPair() {
57 return OSEnvPair(llvm::Triple::IOS, llvm::Triple::MacABI,
58 llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment);
59 }
60
61 /// Returns the os-environment mapping pair that's used to represent the
62 /// iOS -> watchOS version mapping.
63 static inline constexpr OSEnvPair iOStoWatchOSPair() {
64 return OSEnvPair(llvm::Triple::IOS, llvm::Triple::UnknownEnvironment,
65 llvm::Triple::WatchOS, llvm::Triple::UnknownEnvironment);
66 }
67
68 /// Returns the os-environment mapping pair that's used to represent the
69 /// iOS -> tvOS version mapping.
70 static inline constexpr OSEnvPair iOStoTvOSPair() {
71 return OSEnvPair(llvm::Triple::IOS, llvm::Triple::UnknownEnvironment,
72 llvm::Triple::TvOS, llvm::Triple::UnknownEnvironment);
73 }
74
75 private:
76 StorageType Value;
77
78 friend class DarwinSDKInfo;
79 };
80
81 /// Represents a version mapping that maps from a version of one target to a
82 /// version of a related target.
83 ///
84 /// e.g. "macOS_iOSMac":{"10.15":"13.1"} is an example of a macOS -> Mac
85 /// Catalyst version map.
86 class RelatedTargetVersionMapping {
87 public:
88 RelatedTargetVersionMapping(
89 VersionTuple MinimumKeyVersion, VersionTuple MaximumKeyVersion,
90 VersionTuple MinimumValue, VersionTuple MaximumValue,
91 llvm::DenseMap<VersionTuple, VersionTuple> Mapping)
92 : MinimumKeyVersion(MinimumKeyVersion),
93 MaximumKeyVersion(MaximumKeyVersion), MinimumValue(MinimumValue),
94 MaximumValue(MaximumValue), Mapping(Mapping) {
95 assert(!this->Mapping.empty() && "unexpected empty mapping");
96 }
97
98 /// Returns the value with the lowest version in the mapping.
99 const VersionTuple &getMinimumValue() const { return MinimumValue; }
100
101 /// Returns the mapped key, or the appropriate Minimum / MaximumValue if
102 /// they key is outside of the mapping bounds. If they key isn't mapped, but
103 /// within the minimum and maximum bounds, std::nullopt is returned.
104 std::optional<VersionTuple>
105 map(const VersionTuple &Key, const VersionTuple &MinimumValue,
106 std::optional<VersionTuple> MaximumValue) const;
107
108 /// Remap the 'introduced' availability version.
109 /// If None is returned, the 'unavailable' availability should be used
110 /// instead.
111 std::optional<VersionTuple>
112 mapIntroducedAvailabilityVersion(const VersionTuple &Key) const {
113 // API_TO_BE_DEPRECATED is 100000.
114 if (Key.getMajor() == 100000)
115 return VersionTuple(100000);
116 // Use None for maximum to force unavailable behavior for
117 return map(Key, MinimumValue, MaximumValue: std::nullopt);
118 }
119
120 /// Remap the 'deprecated' and 'obsoleted' availability version.
121 /// If None is returned for 'obsoleted', the 'unavailable' availability
122 /// should be used instead. If None is returned for 'deprecated', the
123 /// 'deprecated' version should be dropped.
124 std::optional<VersionTuple>
125 mapDeprecatedObsoletedAvailabilityVersion(const VersionTuple &Key) const {
126 // API_TO_BE_DEPRECATED is 100000.
127 if (Key.getMajor() == 100000)
128 return VersionTuple(100000);
129 return map(Key, MinimumValue, MaximumValue);
130 }
131
132 static std::optional<RelatedTargetVersionMapping>
133 parseJSON(const llvm::json::Object &Obj,
134 VersionTuple MaximumDeploymentTarget);
135
136 private:
137 VersionTuple MinimumKeyVersion;
138 VersionTuple MaximumKeyVersion;
139 VersionTuple MinimumValue;
140 VersionTuple MaximumValue;
141 llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
142 };
143
144 DarwinSDKInfo(
145 VersionTuple Version, VersionTuple MaximumDeploymentTarget,
146 llvm::DenseMap<OSEnvPair::StorageType,
147 std::optional<RelatedTargetVersionMapping>>
148 VersionMappings =
149 llvm::DenseMap<OSEnvPair::StorageType,
150 std::optional<RelatedTargetVersionMapping>>())
151 : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget),
152 VersionMappings(std::move(VersionMappings)) {}
153
154 const llvm::VersionTuple &getVersion() const { return Version; }
155
156 // Returns the optional, target-specific version mapping that maps from one
157 // target to another target.
158 //
159 // This mapping is constructed from an appropriate mapping in the SDKSettings,
160 // for instance, when building for Mac Catalyst, the mapping would contain the
161 // "macOS_iOSMac" mapping as it maps the macOS versions to the Mac Catalyst
162 // versions.
163 //
164 // This mapping does not exist when the target doesn't have an appropriate
165 // related version mapping, or when there was an error reading the mapping
166 // from the SDKSettings, or when it's missing in the SDKSettings.
167 const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const {
168 auto Mapping = VersionMappings.find(Val: Kind.Value);
169 if (Mapping == VersionMappings.end())
170 return nullptr;
171 return Mapping->getSecond() ? &*Mapping->getSecond() : nullptr;
172 }
173
174 static std::optional<DarwinSDKInfo>
175 parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj);
176
177private:
178 VersionTuple Version;
179 VersionTuple MaximumDeploymentTarget;
180 // Need to wrap the value in an optional here as the value has to be default
181 // constructible, and std::unique_ptr doesn't like DarwinSDKInfo being
182 // Optional as Optional is trying to copy it in emplace.
183 llvm::DenseMap<OSEnvPair::StorageType,
184 std::optional<RelatedTargetVersionMapping>>
185 VersionMappings;
186};
187
188/// Parse the SDK information from the SDKSettings.json file.
189///
190/// \returns an error if the SDKSettings.json file is invalid, std::nullopt if
191/// the SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise.
192Expected<std::optional<DarwinSDKInfo>>
193parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath);
194
195} // end namespace clang
196
197#endif // LLVM_CLANG_BASIC_DARWINSDKINFO_H
198

source code of clang/include/clang/Basic/DarwinSDKInfo.h