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