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/ADT/Triple.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/VersionTuple.h" 17 #include "llvm/Support/VirtualFileSystem.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 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>>()) Version(Version)127 : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget), 128 VersionMappings(std::move(VersionMappings)) {} 129 getVersion()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. getVersionMapping(OSEnvPair Kind)143 const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const { 144 auto Mapping = VersionMappings.find(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 153 private: 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. 168 Expected<std::optional<DarwinSDKInfo>> 169 parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath); 170 171 } // end namespace clang 172 173 #endif // LLVM_CLANG_BASIC_DARWINSDKINFO_H 174