Skip to content

Commit 970ff6b

Browse files
committed
[Driver] Read SDK version information to pass to the Darwin linker.
Recent-ish SDKs for Darwin platforms include an SDKSettings.json file with version information and Catalyst SDK version mappings. Read these (when available) and use them to pass the appropriate SDK version down to the Darwin linker via `-platform_version`. Finishes rdar://problem/55972144.
1 parent 6edc325 commit 970ff6b

File tree

9 files changed

+165
-2
lines changed

9 files changed

+165
-2
lines changed

include/swift/AST/DiagnosticsDriver.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ ERROR(cannot_find_migration_script, none,
207207
ERROR(error_darwin_static_stdlib_not_supported, none,
208208
"-static-stdlib is no longer supported on Apple platforms", ())
209209

210+
WARNING(warn_drv_darwin_sdk_invalid_settings, none,
211+
"SDK settings were ignored because 'SDKSettings.json' could not be parsed",
212+
())
213+
210214
#ifndef DIAG_NO_UNDEF
211215
# if defined(DIAG)
212216
# undef DIAG

include/swift/Driver/ToolChain.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,13 @@ class ToolChain {
318318
const llvm::opt::ArgList &args,
319319
StringRef defaultTarget) const {}
320320

321+
/// Validate the output information.
322+
///
323+
/// An override point for platform-specific subclasses to customize their
324+
/// behavior once the outputs are known.
325+
virtual void validateOutputInfo(DiagnosticEngine &diags,
326+
const OutputInfo &outputInfo) const { }
327+
321328
llvm::Expected<file_types::ID>
322329
remarkFileTypeFromArgs(const llvm::opt::ArgList &Args) const;
323330
};

lib/Driver/DarwinToolChains.cpp

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/Basic/TaskQueue.h"
2222
#include "swift/Config.h"
2323
#include "swift/Driver/Compilation.h"
24+
#include "clang/Driver/DarwinSDKInfo.h"
2425
#include "swift/Driver/Driver.h"
2526
#include "swift/Driver/Job.h"
2627
#include "swift/Option/Options.h"
@@ -481,10 +482,45 @@ toolchains::Darwin::addProfileGenerationArgs(ArgStringList &Arguments,
481482
}
482483
}
483484

485+
/// Remap the given version number via the version map, or produce \c None if
486+
/// there is no mapping for this version.
487+
static Optional<llvm::VersionTuple> remapVersion(
488+
const llvm::StringMap<llvm::VersionTuple> &versionMap,
489+
llvm::VersionTuple version) {
490+
// The build number is never used in the lookup.
491+
version = version.withoutBuild();
492+
493+
// Look for this specific version.
494+
auto known = versionMap.find(version.getAsString());
495+
if (known != versionMap.end())
496+
return known->second;
497+
498+
// If an extra ".0" was specified (in the subminor version), drop that
499+
// and look again.
500+
if (!version.getSubminor() || *version.getSubminor() != 0)
501+
return None;
502+
503+
version = llvm::VersionTuple(version.getMajor(), *version.getMinor());
504+
known = versionMap.find(version.getAsString());
505+
if (known != versionMap.end())
506+
return known->second;
507+
508+
// If another extra ".0" wa specified (in the minor version), drop that
509+
// and look again.
510+
if (!version.getMinor() || *version.getMinor() != 0)
511+
return None;
512+
513+
version = llvm::VersionTuple(version.getMajor());
514+
known = versionMap.find(version.getAsString());
515+
if (known != versionMap.end())
516+
return known->second;
517+
518+
return None;
519+
}
520+
484521
void
485522
toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments,
486523
const JobContext &context) const {
487-
488524
auto addPlatformVersionArg = [&](const llvm::Triple &triple) {
489525
// Compute the name of the platform for the linker.
490526
const char *platformName;
@@ -546,10 +582,31 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments,
546582
}
547583
}
548584

585+
// Compute the SDK version.
586+
unsigned sdkMajor = 0, sdkMinor = 0, sdkMicro = 0;
587+
if (SDKInfo) {
588+
// Retrieve the SDK version.
589+
auto SDKVersion = SDKInfo->getVersion();
590+
591+
// For the Mac Catalyst environment, we have a macOS SDK with a macOS
592+
// SDK version. Map that to the corresponding iOS version number to pass
593+
// down to the linker.
594+
if (tripleIsMacCatalystEnvironment(triple)) {
595+
SDKVersion = remapVersion(
596+
SDKInfo->getVersionMap().MacOS2iOSMacMapping, SDKVersion)
597+
.getValueOr(llvm::VersionTuple(0, 0, 0));
598+
}
599+
600+
// Extract the version information.
601+
sdkMajor = SDKVersion.getMajor();
602+
sdkMinor = SDKVersion.getMinor().getValueOr(0);
603+
sdkMicro = SDKVersion.getSubminor().getValueOr(0);
604+
}
605+
549606
Arguments.push_back("-platform_version");
550607
Arguments.push_back(platformName);
551608
addVersionString(context.Args, Arguments, major, minor, micro);
552-
addVersionString(context.Args, Arguments, 0, 0, 0);
609+
addVersionString(context.Args, Arguments, sdkMajor, sdkMinor, sdkMicro);
553610
};
554611

555612
addPlatformVersionArg(getTriple());
@@ -799,3 +856,20 @@ toolchains::Darwin::validateArguments(DiagnosticEngine &diags,
799856
diags.diagnose(SourceLoc(), diag::error_darwin_static_stdlib_not_supported);
800857
}
801858
}
859+
860+
void
861+
toolchains::Darwin::validateOutputInfo(DiagnosticEngine &diags,
862+
const OutputInfo &outputInfo) const {
863+
// If we are linking and have been provided with an SDK, go read the SDK
864+
// information.
865+
if (outputInfo.shouldLink() && !outputInfo.SDKPath.empty()) {
866+
auto SDKInfoOrErr = clang::driver::parseDarwinSDKInfo(
867+
*llvm::vfs::getRealFileSystem(), outputInfo.SDKPath);
868+
if (SDKInfoOrErr) {
869+
SDKInfo = *SDKInfoOrErr;
870+
} else {
871+
llvm::consumeError(SDKInfoOrErr.takeError());
872+
diags.diagnose(SourceLoc(), diag::warn_drv_darwin_sdk_invalid_settings);
873+
}
874+
}
875+
}

lib/Driver/Driver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,10 @@ Driver::buildCompilation(const ToolChain &TC,
883883
assert(OI.CompilerOutputType != file_types::ID::TY_INVALID &&
884884
"buildOutputInfo() must set a valid output type!");
885885

886+
TC.validateOutputInfo(Diags, OI);
887+
if (Diags.hadAnyError())
888+
return nullptr;
889+
886890
validateEmbedBitcode(*TranslatedArgList, OI, Diags);
887891

888892
if (OI.CompilerMode == OutputInfo::Mode::REPL)

lib/Driver/ToolChains.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/Basic/LLVM.h"
1717
#include "swift/Driver/ToolChain.h"
18+
#include "clang/Driver/DarwinSDKInfo.h"
1819
#include "llvm/Option/ArgList.h"
1920
#include "llvm/Support/Compiler.h"
2021

@@ -58,10 +59,18 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
5859
const llvm::opt::ArgList &args,
5960
StringRef defaultTarget) const override;
6061

62+
void validateOutputInfo(DiagnosticEngine &diags,
63+
const OutputInfo &outputInfo) const override;
64+
6165
std::string findProgramRelativeToSwiftImpl(StringRef name) const override;
6266

6367
bool shouldStoreInvocationInDebugInfo() const override;
6468

69+
/// Information about the SDK that the application is being built against.
70+
/// This information is only used by the linker, so it is only populated
71+
/// when there will be a linker job.
72+
mutable Optional<clang::driver::DarwinSDKInfo> SDKInfo;
73+
6574
const Optional<llvm::Triple> TargetVariant;
6675

6776
public:
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"Version":"10.15.4",
3+
"VersionMap" : {
4+
"macOS_iOSMac" : {
5+
"10.14.4" : "12.4",
6+
"10.14.3" : "12.3",
7+
"10.14.2" : "12.2",
8+
"10.14.1" : "12.1",
9+
"10.15" : "13.0",
10+
"10.14" : "12.0",
11+
"10.14.5" : "12.5",
12+
"10.15.1" : "13.2",
13+
"10.15.4" : "13.4"
14+
},
15+
"iOSMac_macOS" : {
16+
"13.0" : "10.15",
17+
"12.3" : "10.14.3",
18+
"12.0" : "10.14",
19+
"12.4" : "10.14.4",
20+
"12.1" : "10.14.1",
21+
"12.5" : "10.14.5",
22+
"12.2" : "10.14.2",
23+
"13.2" : "10.15.1",
24+
"13.4" : "10.15.4"
25+
}
26+
}
27+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"Version":"10.15",
3+
"VersionMap" : {
4+
"macOS_iOSMac" : {
5+
"10.15" : "13.1",
6+
"10.15.1" : "13.2"
7+
},
8+
"iOSMac_macOS" : {
9+
"13.1" : "10.15",
10+
"13.2" : "10.15.1"
11+
}
12+
}
13+
}

test/Driver/linker.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@
101101
// INFERRED_NAMED_DARWIN tests above: 'libLINKER.dylib'.
102102
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -emit-library %s -o libLINKER.dylib | %FileCheck -check-prefix INFERRED_NAME_DARWIN %s
103103

104+
// Check reading the SDKSettings.json from an SDK
105+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -sdk %S/Inputs/MacOSX10.15.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15 %s
106+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -sdk %S/Inputs/MacOSX10.15.4.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15_4 %s
107+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -sdk %S/Inputs/MacOSX10.15.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_UNVERSIONED %s
108+
109+
// MACOS_10_15: -platform_version macos 10.9.0 10.15.0
110+
// MACOS_10_15_4: -platform_version macos 10.9.0 10.15.4
111+
// MACOS_UNVERSIONED: -platform_version macos 10.9.0 0.0.0
112+
104113
// There are more RUN lines further down in the file.
105114

106115
// CHECK: swift

test/Driver/macabi-environment.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,19 @@
9797
// IOS13-NO-MACABI-DAG: -L {{[^ ]+/lib/swift/iphoneos}}
9898
// IOS13-NO-MACABI-DAG: -L {{[^ ]+/clang-importer-sdk/usr/lib/swift}}
9999
// IOS13-NO-MACABI-DAG: -platform_version ios 13.0.0
100+
101+
// Check reading the SDKSettings.json from an SDK and using it to map Catalyst
102+
// SDK version information.
103+
104+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi -sdk %S/Inputs/MacOSX10.15.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15_ZIPPERED %s
105+
// MACOS_10_15_ZIPPERED: -platform_version macos 10.14.0 10.15.0
106+
// MACOS_10_15_ZIPPERED: -platform_version "mac catalyst" 13.0.0 13.1.0
107+
108+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi -sdk %S/Inputs/MacOSX10.15.4.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15_4_ZIPPERED %s
109+
// MACOS_10_15_4_ZIPPERED: -platform_version macos 10.14.0 10.15.4
110+
// MACOS_10_15_4_ZIPPERED: -platform_version "mac catalyst" 13.0.0 13.4.0
111+
112+
// RUN: %swiftc_driver -driver-print-jobs -target-variant x86_64-apple-macosx10.14 -target x86_64-apple-ios13.0-macabi -sdk %S/Inputs/MacOSX10.15.4.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15_4_REVERSE_ZIPPERED %s
113+
// MACOS_10_15_4_REVERSE_ZIPPERED: -platform_version "mac catalyst" 13.0.0 13.4.0
114+
// MACOS_10_15_4_REVERSE_ZIPPERED: -platform_version macos 10.14.0 10.15.4
115+

0 commit comments

Comments
 (0)