xref: /freebsd/contrib/llvm-project/clang/include/clang/Basic/DarwinSDKInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
20 namespace llvm {
21 namespace json {
22 class Object;
23 } // end namespace json
24 } // end namespace llvm
25 
26 namespace clang {
27 
28 /// The information about the darwin SDK that was used during this compilation.
29 class DarwinSDKInfo {
30 public:
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 
OSEnvPairOSEnvPair37     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.
macOStoMacCatalystPairOSEnvPair49     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.
macCatalystToMacOSPairOSEnvPair56     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.
iOStoWatchOSPairOSEnvPair63     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.
iOStoTvOSPairOSEnvPair70     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:
RelatedTargetVersionMapping(VersionTuple MinimumKeyVersion,VersionTuple MaximumKeyVersion,VersionTuple MinimumValue,VersionTuple MaximumValue,llvm::DenseMap<VersionTuple,VersionTuple> Mapping)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.
getMinimumValue()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>
mapIntroducedAvailabilityVersion(const VersionTuple & Key)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, 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>
mapDeprecatedObsoletedAvailabilityVersion(const VersionTuple & Key)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>>())
Version(Version)151       : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget),
152         VersionMappings(std::move(VersionMappings)) {}
153 
getVersion()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.
getVersionMapping(OSEnvPair Kind)167   const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const {
168     auto Mapping = VersionMappings.find(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 
177 private:
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.
192 Expected<std::optional<DarwinSDKInfo>>
193 parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath);
194 
195 } // end namespace clang
196 
197 #endif // LLVM_CLANG_BASIC_DARWINSDKINFO_H
198