summaryrefslogtreecommitdiffstats
path: root/clang/lib/Driver/ToolChains/Darwin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/ToolChains/Darwin.cpp')
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp115
1 files changed, 87 insertions, 28 deletions
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 *
OpenPOWER on IntegriCloud