def warn_drv_moutline_unsupported_opt : Warning<
"The '%0' architecture does not support -moutline; flag ignored">,
InGroup<OptionIgnored>;
+
+def warn_drv_darwin_sdk_invalid_settings : Warning<
+ "SDK settings were ignored as 'SDKSettings.json' could not be parsed">,
+ InGroup<DiagGroup<"darwin-sdk-settings">>;
}
return None;
}
+ /// \returns The version of the SDK which was used during the compilation if
+ /// one was specified, or an empty version otherwise.
+ const llvm::VersionTuple &getSDKVersion() const {
+ return getTargetOpts().SDKVersion;
+ }
+
/// Check the target is valid after it is fully initialized.
virtual bool validateTarget(DiagnosticsEngine &Diags) const {
return true;
#ifndef LLVM_CLANG_BASIC_TARGETOPTIONS_H
#define LLVM_CLANG_BASIC_TARGETOPTIONS_H
-#include <string>
-#include <vector>
#include "clang/Basic/OpenCLOptions.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Target/TargetOptions.h"
+#include <string>
+#include <vector>
namespace clang {
// "default" for the case when the user has not explicitly specified a
// code model.
std::string CodeModel;
+
+ /// The version of the SDK which was used during the compilation.
+ VersionTuple SDKVersion;
};
} // end namespace clang
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
def target_abi : Separate<["-"], "target-abi">,
HelpText<"Target a particular ABI type">;
+def target_sdk_version_EQ : Joined<["-"], "target-sdk-version=">,
+ HelpText<"The version of target SDK used for compilation">;
}
--- /dev/null
+//===--- DarwinSDKInfo.h - SDK Information parser for darwin ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H
+#define LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+namespace clang {
+namespace driver {
+
+/// The information about the darwin SDK that was used during this compilation.
+class DarwinSDKInfo {
+public:
+ DarwinSDKInfo(llvm::VersionTuple Version) : Version(Version) {}
+
+ const llvm::VersionTuple &getVersion() const { return Version; }
+
+private:
+ llvm::VersionTuple Version;
+};
+
+/// Parse the SDK information from the SDKSettings.json file.
+///
+/// \returns an error if the SDKSettings.json file is invalid, None if the
+/// SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise.
+Expected<Optional<DarwinSDKInfo>> parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS,
+ StringRef SDKRootPath);
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H
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));
add_clang_library(clangDriver
Action.cpp
Compilation.cpp
+ DarwinSDKInfo.cpp
Distro.cpp
Driver.cpp
DriverOptions.cpp
--- /dev/null
+//===--- 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());
+}
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) {}
}
/// 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;
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;
}
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 {
}
}
+ // 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());
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)
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 *
#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 {
/// 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:
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,
--- /dev/null
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14 -target-sdk-version=10.14.1 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: !llvm.module.flags = !{!0
+// CHECK: !0 = !{i32 2, !"SDK Version", [3 x i32] [i32 10, i32 14, i32 1]}
--- /dev/null
+{"Version":"10.14"}
--- /dev/null
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %S/Inputs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck %s
+// RUN: env SDKROOT=%S/Inputs/MacOSX10.14.sdk %clang -target x86_64-apple-macosx10.13 -c -### %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.10.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.10.sdk
+// RUN: %clang -isysroot %t/SDKs/MacOSX10.10.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=INFER_SDK_VERSION %s
+// RUN: cp %S/Inputs/MacOSX10.14.sdk/SDKSettings.json %t/SDKs/MacOSX10.10.sdk
+// RUN: %clang -isysroot %t/SDKs/MacOSX10.10.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=INFER_DEPLOYMENT_TARGET_VERSION %s
+// REQUIRES: system-darwin && native
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.14.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.14.sdk
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %t/SDKs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=NO_VERSION %s
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.14.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.14.sdk
+// RUN: echo '{broken json' > %t/SDKs/MacOSX10.14.sdk/SDKSettings.json
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %t/SDKs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=NO_VERSION,ERROR %s
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.14.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.14.sdk
+// RUN: echo '{"Version":1}' > %t/SDKs/MacOSX10.14.sdk/SDKSettings.json
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %t/SDKs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=NO_VERSION,ERROR %s
+
+// CHECK: -target-sdk-version=10.14
+// INFER_SDK_VERSION: "-triple" "x86_64-apple-macosx10.10.0"
+// INFER_SDK_VERSION-SAME: -target-sdk-version=10.10
+// INFER_DEPLOYMENT_TARGET_VERSION: "-triple" "x86_64-apple-macosx10.14.0"
+// NO_VERSION-NOT: target-sdk-version
+// ERROR: warning: SDK settings were ignored as 'SDKSettings.json' could not be parsed
-// RUN: %clang -emit-llvm -S -o %t1.ll -x c - < %s
-// RUN: %clang -emit-ast -o %t.ast %s
-// RUN: %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t1.ll -x c - < %s
+// RUN: env SDKROOT="/" %clang -emit-ast -o %t.ast %s
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
// RUN: diff %t1.ll %t2.ll
int main() {
-// RUN: %clang -emit-llvm -S -o %t1.ll -x c++ - < %s
-// RUN: %clang -fno-delayed-template-parsing -emit-ast -o %t.ast %s
-// RUN: %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t1.ll -x c++ - < %s
+// RUN: env SDKROOT="/" %clang -fno-delayed-template-parsing -emit-ast -o %t.ast %s
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
// RUN: diff %t1.ll %t2.ll
// http://llvm.org/bugs/show_bug.cgi?id=15377