//===--- DarwinSDKInfo.h - SDK Information parser for darwin ----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_DARWINSDKINFO_H #define LLVM_CLANG_BASIC_DARWINSDKINFO_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Error.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" #include namespace llvm { namespace json { class Object; } // end namespace json } // end namespace llvm namespace clang { /// The information about the darwin SDK that was used during this compilation. class DarwinSDKInfo { public: /// A value that describes two os-environment pairs that can be used as a key /// to the version map in the SDK. struct OSEnvPair { public: using StorageType = uint64_t; constexpr OSEnvPair(llvm::Triple::OSType FromOS, llvm::Triple::EnvironmentType FromEnv, llvm::Triple::OSType ToOS, llvm::Triple::EnvironmentType ToEnv) : Value(((StorageType(FromOS) * StorageType(llvm::Triple::LastOSType) + StorageType(FromEnv)) << 32ull) | (StorageType(ToOS) * StorageType(llvm::Triple::LastOSType) + StorageType(ToEnv))) {} /// Returns the os-environment mapping pair that's used to represent the /// macOS -> Mac Catalyst version mapping. static inline constexpr OSEnvPair macOStoMacCatalystPair() { return OSEnvPair(llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment, llvm::Triple::IOS, llvm::Triple::MacABI); } /// Returns the os-environment mapping pair that's used to represent the /// Mac Catalyst -> macOS version mapping. static inline constexpr OSEnvPair macCatalystToMacOSPair() { return OSEnvPair(llvm::Triple::IOS, llvm::Triple::MacABI, llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment); } /// Returns the os-environment mapping pair that's used to represent the /// iOS -> watchOS version mapping. static inline constexpr OSEnvPair iOStoWatchOSPair() { return OSEnvPair(llvm::Triple::IOS, llvm::Triple::UnknownEnvironment, llvm::Triple::WatchOS, llvm::Triple::UnknownEnvironment); } /// Returns the os-environment mapping pair that's used to represent the /// iOS -> tvOS version mapping. static inline constexpr OSEnvPair iOStoTvOSPair() { return OSEnvPair(llvm::Triple::IOS, llvm::Triple::UnknownEnvironment, llvm::Triple::TvOS, llvm::Triple::UnknownEnvironment); } private: StorageType Value; friend class DarwinSDKInfo; }; /// Represents a version mapping that maps from a version of one target to a /// version of a related target. /// /// e.g. "macOS_iOSMac":{"10.15":"13.1"} is an example of a macOS -> Mac /// Catalyst version map. class RelatedTargetVersionMapping { public: RelatedTargetVersionMapping( VersionTuple MinimumKeyVersion, VersionTuple MaximumKeyVersion, VersionTuple MinimumValue, VersionTuple MaximumValue, llvm::DenseMap Mapping) : MinimumKeyVersion(MinimumKeyVersion), MaximumKeyVersion(MaximumKeyVersion), MinimumValue(MinimumValue), MaximumValue(MaximumValue), Mapping(Mapping) { assert(!this->Mapping.empty() && "unexpected empty mapping"); } /// Returns the value with the lowest version in the mapping. const VersionTuple &getMinimumValue() const { return MinimumValue; } /// Returns the mapped key, or the appropriate Minimum / MaximumValue if /// they key is outside of the mapping bounds. If they key isn't mapped, but /// within the minimum and maximum bounds, std::nullopt is returned. std::optional map(const VersionTuple &Key, const VersionTuple &MinimumValue, std::optional MaximumValue) const; static std::optional parseJSON(const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget); private: VersionTuple MinimumKeyVersion; VersionTuple MaximumKeyVersion; VersionTuple MinimumValue; VersionTuple MaximumValue; llvm::DenseMap Mapping; }; DarwinSDKInfo( VersionTuple Version, VersionTuple MaximumDeploymentTarget, llvm::DenseMap> VersionMappings = llvm::DenseMap>()) : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget), VersionMappings(std::move(VersionMappings)) {} const llvm::VersionTuple &getVersion() const { return Version; } // Returns the optional, target-specific version mapping that maps from one // target to another target. // // This mapping is constructed from an appropriate mapping in the SDKSettings, // for instance, when building for Mac Catalyst, the mapping would contain the // "macOS_iOSMac" mapping as it maps the macOS versions to the Mac Catalyst // versions. // // This mapping does not exist when the target doesn't have an appropriate // related version mapping, or when there was an error reading the mapping // from the SDKSettings, or when it's missing in the SDKSettings. const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const { auto Mapping = VersionMappings.find(Kind.Value); if (Mapping == VersionMappings.end()) return nullptr; return Mapping->getSecond() ? &*Mapping->getSecond() : nullptr; } static std::optional parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj); private: VersionTuple Version; VersionTuple MaximumDeploymentTarget; // Need to wrap the value in an optional here as the value has to be default // constructible, and std::unique_ptr doesn't like DarwinSDKInfo being // Optional as Optional is trying to copy it in emplace. llvm::DenseMap> VersionMappings; }; /// Parse the SDK information from the SDKSettings.json file. /// /// \returns an error if the SDKSettings.json file is invalid, std::nullopt if /// the SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise. Expected> parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath); } // end namespace clang #endif // LLVM_CLANG_BASIC_DARWINSDKINFO_H