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 static std::optional<RelatedTargetVersionMapping>
109 parseJSON(const llvm::json::Object &Obj,
110 VersionTuple MaximumDeploymentTarget);
111
112 private:
113 VersionTuple MinimumKeyVersion;
114 VersionTuple MaximumKeyVersion;
115 VersionTuple MinimumValue;
116 VersionTuple MaximumValue;
117 llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
118 };
119
120 DarwinSDKInfo(
121 VersionTuple Version, VersionTuple MaximumDeploymentTarget,
122 llvm::DenseMap<OSEnvPair::StorageType,
123 std::optional<RelatedTargetVersionMapping>>
124 VersionMappings =
125 llvm::DenseMap<OSEnvPair::StorageType,
126 std::optional<RelatedTargetVersionMapping>>())
127 : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget),
128 VersionMappings(std::move(VersionMappings)) {}
129
130 const llvm::VersionTuple &getVersion() const { return Version; }
131
132 // Returns the optional, target-specific version mapping that maps from one
133 // target to another target.
134 //
135 // This mapping is constructed from an appropriate mapping in the SDKSettings,
136 // for instance, when building for Mac Catalyst, the mapping would contain the
137 // "macOS_iOSMac" mapping as it maps the macOS versions to the Mac Catalyst
138 // versions.
139 //
140 // This mapping does not exist when the target doesn't have an appropriate
141 // related version mapping, or when there was an error reading the mapping
142 // from the SDKSettings, or when it's missing in the SDKSettings.
143 const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const {
144 auto Mapping = VersionMappings.find(Val: Kind.Value);
145 if (Mapping == VersionMappings.end())
146 return nullptr;
147 return Mapping->getSecond() ? &*Mapping->getSecond() : nullptr;
148 }
149
150 static std::optional<DarwinSDKInfo>
151 parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj);
152
153private:
154 VersionTuple Version;
155 VersionTuple MaximumDeploymentTarget;
156 // Need to wrap the value in an optional here as the value has to be default
157 // constructible, and std::unique_ptr doesn't like DarwinSDKInfo being
158 // Optional as Optional is trying to copy it in emplace.
159 llvm::DenseMap<OSEnvPair::StorageType,
160 std::optional<RelatedTargetVersionMapping>>
161 VersionMappings;
162};
163
164/// Parse the SDK information from the SDKSettings.json file.
165///
166/// \returns an error if the SDKSettings.json file is invalid, std::nullopt if
167/// the SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise.
168Expected<std::optional<DarwinSDKInfo>>
169parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath);
170
171} // end namespace clang
172
173#endif // LLVM_CLANG_BASIC_DARWINSDKINFO_H
174

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