diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/ModuleBuilder.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Driver/DarwinSDKInfo.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Darwin.cpp | 115 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Darwin.h | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 8 |
6 files changed, 148 insertions, 29 deletions
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 1264893ec13..c0a37698e76 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -132,6 +132,9 @@ namespace { M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple()); M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); + const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion(); + if (!SDKVersion.empty()) + M->setSDKVersion(SDKVersion); Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags, CoverageInfo)); diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index bc96098d0ae..084176b5246 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -12,6 +12,7 @@ endif() add_clang_library(clangDriver Action.cpp Compilation.cpp + DarwinSDKInfo.cpp Distro.cpp Driver.cpp DriverOptions.cpp diff --git a/clang/lib/Driver/DarwinSDKInfo.cpp b/clang/lib/Driver/DarwinSDKInfo.cpp new file mode 100644 index 00000000000..547978b2f97 --- /dev/null +++ b/clang/lib/Driver/DarwinSDKInfo.cpp @@ -0,0 +1,44 @@ +//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/DarwinSDKInfo.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" + +using namespace clang::driver; +using namespace clang; + +Expected<Optional<DarwinSDKInfo>> +driver::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) { + llvm::SmallString<256> Filepath = SDKRootPath; + llvm::sys::path::append(Filepath, "SDKSettings.json"); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = + VFS.getBufferForFile(Filepath); + if (!File) { + // If the file couldn't be read, assume it just doesn't exist. + return None; + } + Expected<llvm::json::Value> Result = + llvm::json::parse(File.get()->getBuffer()); + if (!Result) + return Result.takeError(); + + if (const auto *Obj = Result->getAsObject()) { + auto VersionString = Obj->getString("Version"); + if (VersionString) { + VersionTuple Version; + if (!Version.tryParse(*VersionString)) + return DarwinSDKInfo(Version); + } + } + return llvm::make_error<llvm::StringError>("invalid SDKSettings.json", + llvm::inconvertibleErrorCode()); +} diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index e5dafa2b092..0cc187ab475 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1287,6 +1287,18 @@ struct DarwinPlatform { return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value); } + /// Constructs an inferred SDKInfo value based on the version inferred from + /// the SDK path itself. Only works for values that were created by inferring + /// the platform from the SDKPath. + DarwinSDKInfo inferSDKInfo() { + assert(Kind == InferredFromSDK && "can infer SDK info only"); + llvm::VersionTuple Version; + bool IsValid = !Version.tryParse(OSVersion); + (void)IsValid; + assert(IsValid && "invalid SDK version"); + return DarwinSDKInfo(Version); + } + private: DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument) : Kind(Kind), Platform(Platform), Argument(Argument) {} @@ -1420,8 +1432,11 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, } /// Tries to infer the deployment target from the SDK specified by -isysroot -/// (or SDKROOT). -Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) { +/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if +/// it's available. +Optional<DarwinPlatform> +inferDeploymentTargetFromSDK(DerivedArgList &Args, + const Optional<DarwinSDKInfo> &SDKInfo) { const Arg *A = Args.getLastArg(options::OPT_isysroot); if (!A) return None; @@ -1429,28 +1444,37 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) { StringRef SDK = Darwin::getSDKName(isysroot); if (!SDK.size()) return None; - // Slice the version number out. - // Version number is between the first and the last number. - size_t StartVer = SDK.find_first_of("0123456789"); - size_t EndVer = SDK.find_last_of("0123456789"); - if (StartVer != StringRef::npos && EndVer > StartVer) { - StringRef Version = SDK.slice(StartVer, EndVer + 1); - if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator")) - return DarwinPlatform::createFromSDK( - Darwin::IPhoneOS, Version, - /*IsSimulator=*/SDK.startswith("iPhoneSimulator")); - else if (SDK.startswith("MacOSX")) - return DarwinPlatform::createFromSDK(Darwin::MacOS, - getSystemOrSDKMacOSVersion(Version)); - else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator")) - return DarwinPlatform::createFromSDK( - Darwin::WatchOS, Version, - /*IsSimulator=*/SDK.startswith("WatchSimulator")); - else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator")) - return DarwinPlatform::createFromSDK( - Darwin::TvOS, Version, - /*IsSimulator=*/SDK.startswith("AppleTVSimulator")); - } + + std::string Version; + if (SDKInfo) { + // Get the version from the SDKSettings.json if it's available. + Version = SDKInfo->getVersion().getAsString(); + } else { + // Slice the version number out. + // Version number is between the first and the last number. + size_t StartVer = SDK.find_first_of("0123456789"); + size_t EndVer = SDK.find_last_of("0123456789"); + if (StartVer != StringRef::npos && EndVer > StartVer) + Version = SDK.slice(StartVer, EndVer + 1); + } + if (Version.empty()) + return None; + + if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator")) + return DarwinPlatform::createFromSDK( + Darwin::IPhoneOS, Version, + /*IsSimulator=*/SDK.startswith("iPhoneSimulator")); + else if (SDK.startswith("MacOSX")) + return DarwinPlatform::createFromSDK(Darwin::MacOS, + getSystemOrSDKMacOSVersion(Version)); + else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator")) + return DarwinPlatform::createFromSDK( + Darwin::WatchOS, Version, + /*IsSimulator=*/SDK.startswith("WatchSimulator")); + else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator")) + return DarwinPlatform::createFromSDK( + Darwin::TvOS, Version, + /*IsSimulator=*/SDK.startswith("AppleTVSimulator")); return None; } @@ -1525,6 +1549,22 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg( Args.getLastArg(options::OPT_target)); } +Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS, + const ArgList &Args, + const Driver &TheDriver) { + const Arg *A = Args.getLastArg(options::OPT_isysroot); + if (!A) + return None; + StringRef isysroot = A->getValue(); + auto SDKInfoOrErr = driver::parseDarwinSDKInfo(VFS, isysroot); + if (!SDKInfoOrErr) { + llvm::consumeError(SDKInfoOrErr.takeError()); + TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings); + return None; + } + return *SDKInfoOrErr; +} + } // namespace void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { @@ -1549,6 +1589,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } + // Read the SDKSettings.json file for more information, like the SDK version + // that we can pass down to the compiler. + SDKInfo = parseSDKSettings(getVFS(), Args, getDriver()); + // The OS and the version can be specified using the -target argument. Optional<DarwinPlatform> OSTarget = getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver()); @@ -1594,16 +1638,22 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple()); if (OSTarget) { // Don't infer simulator from the arch when the SDK is also specified. - Optional<DarwinPlatform> SDKTarget = inferDeploymentTargetFromSDK(Args); + Optional<DarwinPlatform> SDKTarget = + inferDeploymentTargetFromSDK(Args, SDKInfo); if (SDKTarget) OSTarget->setEnvironment(SDKTarget->getEnvironment()); } } // If there is no command-line argument to specify the Target version and // no environment variable defined, see if we can set the default based - // on -isysroot. - if (!OSTarget) - OSTarget = inferDeploymentTargetFromSDK(Args); + // on -isysroot using SDKSettings.json if it exists. + if (!OSTarget) { + OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo); + /// If the target was successfully constructed from the SDK path, try to + /// infer the SDK info if the SDK doesn't have it. + if (OSTarget && !SDKInfo) + SDKInfo = OSTarget->inferSDKInfo(); + } // If no OS targets have been specified, try to guess platform from -target // or arch name and compute the version from the triple. if (!OSTarget) @@ -2046,6 +2096,15 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, options::OPT_fno_aligned_allocation) && isAlignedAllocationUnavailable()) CC1Args.push_back("-faligned-alloc-unavailable"); + + if (SDKInfo) { + /// Pass the SDK version to the compiler when the SDK information is + /// available. + std::string Arg; + llvm::raw_string_ostream OS(Arg); + OS << "-target-sdk-version=" << SDKInfo->getVersion(); + CC1Args.push_back(DriverArgs.MakeArgString(OS.str())); + } } DerivedArgList * diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index e6a88dce3c7..d753f8967a6 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -11,9 +11,10 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H #include "Cuda.h" -#include "clang/Driver/XRayArgs.h" +#include "clang/Driver/DarwinSDKInfo.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "clang/Driver/XRayArgs.h" namespace clang { namespace driver { @@ -288,6 +289,9 @@ public: /// The OS version we are targeting. mutable VersionTuple TargetVersion; + /// The information about the darwin SDK that was used. + mutable Optional<DarwinSDKInfo> SDKInfo; + CudaInstallationDetector CudaInstallation; private: diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d491f35769c..eaa61b29d9d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3193,6 +3193,14 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, Opts.ForceEnableInt128 = Args.hasArg(OPT_fforce_enable_int128); Opts.NVPTXUseShortPointers = Args.hasFlag( options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false); + if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) { + llvm::VersionTuple Version; + if (Version.tryParse(A->getValue())) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + else + Opts.SDKVersion = Version; + } } bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, |