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_DARWIN_SDK_INFO_H 10 #define LLVM_CLANG_BASIC_DARWIN_SDK_INFO_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 OSEnvPairOSEnvPair36 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. macOStoMacCatalystPairOSEnvPair48 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. macCatalystToMacOSPairOSEnvPair55 static inline constexpr OSEnvPair macCatalystToMacOSPair() { 56 return OSEnvPair(llvm::Triple::IOS, llvm::Triple::MacABI, 57 llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment); 58 } 59 60 private: 61 StorageType Value; 62 63 friend class DarwinSDKInfo; 64 }; 65 66 /// Represents a version mapping that maps from a version of one target to a 67 /// version of a related target. 68 /// 69 /// e.g. "macOS_iOSMac":{"10.15":"13.1"} is an example of a macOS -> Mac 70 /// Catalyst version map. 71 class RelatedTargetVersionMapping { 72 public: RelatedTargetVersionMapping(VersionTuple MinimumKeyVersion,VersionTuple MaximumKeyVersion,VersionTuple MinimumValue,VersionTuple MaximumValue,llvm::DenseMap<VersionTuple,VersionTuple> Mapping)73 RelatedTargetVersionMapping( 74 VersionTuple MinimumKeyVersion, VersionTuple MaximumKeyVersion, 75 VersionTuple MinimumValue, VersionTuple MaximumValue, 76 llvm::DenseMap<VersionTuple, VersionTuple> Mapping) 77 : MinimumKeyVersion(MinimumKeyVersion), 78 MaximumKeyVersion(MaximumKeyVersion), MinimumValue(MinimumValue), 79 MaximumValue(MaximumValue), Mapping(Mapping) { 80 assert(!this->Mapping.empty() && "unexpected empty mapping"); 81 } 82 83 /// Returns the value with the lowest version in the mapping. getMinimumValue()84 const VersionTuple &getMinimumValue() const { return MinimumValue; } 85 86 /// Returns the mapped key, or the appropriate Minimum / MaximumValue if 87 /// they key is outside of the mapping bounds. If they key isn't mapped, but 88 /// within the minimum and maximum bounds, None is returned. 89 Optional<VersionTuple> map(const VersionTuple &Key, 90 const VersionTuple &MinimumValue, 91 Optional<VersionTuple> MaximumValue) const; 92 93 static Optional<RelatedTargetVersionMapping> 94 parseJSON(const llvm::json::Object &Obj, 95 VersionTuple MaximumDeploymentTarget); 96 97 private: 98 VersionTuple MinimumKeyVersion; 99 VersionTuple MaximumKeyVersion; 100 VersionTuple MinimumValue; 101 VersionTuple MaximumValue; 102 llvm::DenseMap<VersionTuple, VersionTuple> Mapping; 103 }; 104 105 DarwinSDKInfo(VersionTuple Version, VersionTuple MaximumDeploymentTarget, 106 llvm::DenseMap<OSEnvPair::StorageType, 107 Optional<RelatedTargetVersionMapping>> 108 VersionMappings = 109 llvm::DenseMap<OSEnvPair::StorageType, 110 Optional<RelatedTargetVersionMapping>>()) Version(Version)111 : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget), 112 VersionMappings(std::move(VersionMappings)) {} 113 getVersion()114 const llvm::VersionTuple &getVersion() const { return Version; } 115 116 // Returns the optional, target-specific version mapping that maps from one 117 // target to another target. 118 // 119 // This mapping is constructed from an appropriate mapping in the SDKSettings, 120 // for instance, when building for Mac Catalyst, the mapping would contain the 121 // "macOS_iOSMac" mapping as it maps the macOS versions to the Mac Catalyst 122 // versions. 123 // 124 // This mapping does not exist when the target doesn't have an appropriate 125 // related version mapping, or when there was an error reading the mapping 126 // from the SDKSettings, or when it's missing in the SDKSettings. getVersionMapping(OSEnvPair Kind)127 const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const { 128 auto Mapping = VersionMappings.find(Kind.Value); 129 if (Mapping == VersionMappings.end()) 130 return nullptr; 131 return Mapping->getSecond().hasValue() ? Mapping->getSecond().getPointer() 132 : nullptr; 133 } 134 135 static Optional<DarwinSDKInfo> 136 parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj); 137 138 private: 139 VersionTuple Version; 140 VersionTuple MaximumDeploymentTarget; 141 // Need to wrap the value in an optional here as the value has to be default 142 // constructible, and std::unique_ptr doesn't like DarwinSDKInfo being 143 // Optional as Optional is trying to copy it in emplace. 144 llvm::DenseMap<OSEnvPair::StorageType, Optional<RelatedTargetVersionMapping>> 145 VersionMappings; 146 }; 147 148 /// Parse the SDK information from the SDKSettings.json file. 149 /// 150 /// \returns an error if the SDKSettings.json file is invalid, None if the 151 /// SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise. 152 Expected<Optional<DarwinSDKInfo>> parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, 153 StringRef SDKRootPath); 154 155 } // end namespace clang 156 157 #endif // LLVM_CLANG_BASIC_DARWIN_SDK_INFO_H 158