diff options
author | Alex Lorenz <arphaman@gmail.com> | 2018-12-17 19:19:15 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2018-12-17 19:19:15 +0000 |
commit | 0a264f3928019b1db5205b96fcca8261b223eec1 (patch) | |
tree | 52772b336aa9a24cc6fff529115e39ceae1dd4a2 /clang/lib | |
parent | c32d47c6a83dec619c1dd911cb8b544952a5a2df (diff) | |
download | bcm5719-llvm-0a264f3928019b1db5205b96fcca8261b223eec1.tar.gz bcm5719-llvm-0a264f3928019b1db5205b96fcca8261b223eec1.zip |
[darwin] parse the SDK settings from SDKSettings.json if it exists and
pass in the -target-sdk-version to the compiler and backend
This commit adds support for reading the SDKSettings.json file in the Darwin
driver. This file is used by the driver to determine the SDK's version, and it
uses that information to pass it down to the compiler using the new
-target-sdk-version= option. This option is then used to set the appropriate
SDK Version module metadata introduced in r349119.
Note: I had to adjust the two ast tests as the SDKROOT environment variable
on macOS caused SDK version to be picked up for the compilation of source file
but not the AST.
rdar://45774000
Differential Revision: https://reviews.llvm.org/D55673
llvm-svn: 349380
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, |