Skip to content

Commit bdb2aee

Browse files
authored
Merge pull request swiftlang#30788 from DougGregor/driver-darwin-sdk-version-to-linker
[Driver] Use -platform_version to specify platform versions for the Darwin linker
2 parents e5a7fd3 + 82ceb29 commit bdb2aee

File tree

9 files changed

+257
-57
lines changed

9 files changed

+257
-57
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: 140 additions & 45 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,61 +482,138 @@ 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-
const llvm::Triple &Triple = getTriple();
488-
// FIXME: Properly handle deployment targets.
489-
assert(Triple.isiOS() || Triple.isWatchOS() || Triple.isMacOSX());
490-
if (Triple.isiOS()) {
491-
bool isiOSSimulator = tripleIsiOSSimulator(Triple);
492-
if (Triple.isTvOS()) {
493-
if (isiOSSimulator)
494-
Arguments.push_back("-tvos_simulator_version_min");
495-
else
496-
Arguments.push_back("-tvos_version_min");
524+
auto addPlatformVersionArg = [&](const llvm::Triple &triple) {
525+
// Compute the name of the platform for the linker.
526+
const char *platformName;
527+
if (tripleIsMacCatalystEnvironment(triple)) {
528+
platformName = "mac-catalyst";
497529
} else {
498-
if (isiOSSimulator)
499-
Arguments.push_back("-ios_simulator_version_min");
500-
else if (tripleIsMacCatalystEnvironment(Triple))
501-
Arguments.push_back("-maccatalyst_version_min");
502-
else
503-
Arguments.push_back("-iphoneos_version_min");
530+
switch (getDarwinPlatformKind(triple)) {
531+
case DarwinPlatformKind::MacOS:
532+
platformName = "macos";
533+
break;
534+
case DarwinPlatformKind::IPhoneOS:
535+
platformName = "ios";
536+
break;
537+
case DarwinPlatformKind::IPhoneOSSimulator:
538+
platformName = "ios-simulator";
539+
break;
540+
case DarwinPlatformKind::TvOS:
541+
platformName = "tvos";
542+
break;
543+
case DarwinPlatformKind::TvOSSimulator:
544+
platformName = "tvos-simulator";
545+
break;
546+
case DarwinPlatformKind::WatchOS:
547+
platformName = "watchos";
548+
break;
549+
case DarwinPlatformKind::WatchOSSimulator:
550+
platformName = "watchos-simulator";
551+
break;
552+
}
504553
}
554+
555+
// Compute the platform version.
505556
unsigned major, minor, micro;
506-
Triple.getiOSVersion(major, minor, micro);
507-
addVersionString(context.Args, Arguments, major, minor, micro);
557+
if (tripleIsMacCatalystEnvironment(triple)) {
558+
triple.getiOSVersion(major, minor, micro);
559+
560+
// Mac Catalyst was introduced with an iOS deployment target of 13.0;
561+
// the linker doesn't want to see a deployment target before that.
562+
if (major < 13) {
563+
major = 13;
564+
minor = 0;
565+
micro = 0;
566+
}
567+
} else {
568+
switch (getDarwinPlatformKind((triple))) {
569+
case DarwinPlatformKind::MacOS:
570+
triple.getMacOSXVersion(major, minor, micro);
571+
break;
572+
case DarwinPlatformKind::IPhoneOS:
573+
case DarwinPlatformKind::IPhoneOSSimulator:
574+
case DarwinPlatformKind::TvOS:
575+
case DarwinPlatformKind::TvOSSimulator:
576+
triple.getiOSVersion(major, minor, micro);
577+
break;
578+
case DarwinPlatformKind::WatchOS:
579+
case DarwinPlatformKind::WatchOSSimulator:
580+
triple.getOSVersion(major, minor, micro);
581+
break;
582+
}
583+
}
584+
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+
}
508599

509-
if (TargetVariant) {
510-
assert(triplesAreValidForZippering(Triple, *TargetVariant));
511-
assert(TargetVariant->isMacOSX());
512-
Arguments.push_back("-macosx_version_min");
513-
unsigned major, minor, micro;
514-
TargetVariant->getMacOSXVersion(major, minor, micro);
515-
addVersionString(context.Args, Arguments, major, minor, micro);
600+
// Extract the version information.
601+
sdkMajor = SDKVersion.getMajor();
602+
sdkMinor = SDKVersion.getMinor().getValueOr(0);
603+
sdkMicro = SDKVersion.getSubminor().getValueOr(0);
516604
}
517-
} else if (Triple.isWatchOS()) {
518-
if (tripleIsWatchSimulator(Triple))
519-
Arguments.push_back("-watchos_simulator_version_min");
520-
else
521-
Arguments.push_back("-watchos_version_min");
522-
unsigned major, minor, micro;
523-
Triple.getOSVersion(major, minor, micro);
524-
addVersionString(context.Args, Arguments, major, minor, micro);
525-
} else {
526-
Arguments.push_back("-macosx_version_min");
527-
unsigned major, minor, micro;
528-
Triple.getMacOSXVersion(major, minor, micro);
605+
606+
Arguments.push_back("-platform_version");
607+
Arguments.push_back(platformName);
529608
addVersionString(context.Args, Arguments, major, minor, micro);
609+
addVersionString(context.Args, Arguments, sdkMajor, sdkMinor, sdkMicro);
610+
};
530611

531-
if (TargetVariant) {
532-
assert(triplesAreValidForZippering(Triple, *TargetVariant));
533-
assert(tripleIsMacCatalystEnvironment(*TargetVariant));
534-
Arguments.push_back("-maccatalyst_version_min");
535-
unsigned major, minor, micro;
536-
TargetVariant->getiOSVersion(major, minor, micro);
537-
addVersionString(context.Args, Arguments, major, minor, micro);
538-
}
612+
addPlatformVersionArg(getTriple());
613+
614+
if (auto targetVariant = getTargetVariant()) {
615+
assert(triplesAreValidForZippering(getTriple(), *targetVariant));
616+
addPlatformVersionArg(*targetVariant);
539617
}
540618
}
541619

@@ -778,3 +856,20 @@ toolchains::Darwin::validateArguments(DiagnosticEngine &diags,
778856
diags.diagnose(SourceLoc(), diag::error_darwin_static_stdlib_not_supported);
779857
}
780858
}
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: 14 additions & 5 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
@@ -117,7 +126,7 @@
117126

118127
// SIMPLE: {{(bin/)?}}ld{{"? }}
119128
// SIMPLE-NOT: -syslibroot
120-
// SIMPLE: -macosx_version_min 10.{{[0-9]+}}.{{[0-9]+}}
129+
// SIMPLE: -platform_version macos 10.{{[0-9]+}}.{{[0-9]+}} 0.0.0
121130
// SIMPLE-NOT: -syslibroot
122131
// SIMPLE: -o linker
123132

@@ -133,7 +142,7 @@
133142
// IOS_SIMPLE-DAG: -L {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)iphonesimulator}}
134143
// IOS_SIMPLE-DAG: -lSystem
135144
// IOS_SIMPLE-DAG: -arch x86_64
136-
// IOS_SIMPLE-DAG: -ios_simulator_version_min 7.1.{{[0-9]+}}
145+
// IOS_SIMPLE-DAG: -platform_version ios-simulator 7.1.{{[0-9]+}} 0.0.0
137146
// IOS_SIMPLE: -o linker
138147

139148

@@ -145,7 +154,7 @@
145154
// tvOS_SIMPLE-DAG: -L {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)appletvsimulator}}
146155
// tvOS_SIMPLE-DAG: -lSystem
147156
// tvOS_SIMPLE-DAG: -arch x86_64
148-
// tvOS_SIMPLE-DAG: -tvos_simulator_version_min 9.0.{{[0-9]+}}
157+
// tvOS_SIMPLE-DAG: -platform_version tvos-simulator 9.0.{{[0-9]+}} 0.0.0
149158
// tvOS_SIMPLE: -o linker
150159

151160

@@ -157,7 +166,7 @@
157166
// watchOS_SIMPLE-DAG: -L {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)watchsimulator}}
158167
// watchOS_SIMPLE-DAG: -lSystem
159168
// watchOS_SIMPLE-DAG: -arch i386
160-
// watchOS_SIMPLE-DAG: -watchos_simulator_version_min 2.0.{{[0-9]+}}
169+
// watchOS_SIMPLE-DAG: -platform_version watchos-simulator 2.0.{{[0-9]+}} 0.0.0
161170
// watchOS_SIMPLE: -o linker
162171

163172

@@ -298,7 +307,7 @@
298307
// COMPLEX-DAG: -L baz
299308
// COMPLEX-DAG: -F garply -F car -F cdr
300309
// COMPLEX-DAG: -undefined dynamic_lookup
301-
// COMPLEX-DAG: -macosx_version_min 10.9.1
310+
// COMPLEX-DAG: -platform_version macos 10.9.1 0.0.0
302311
// COMPLEX: -o sdk.out
303312

304313
// LINUX_DYNLIB-x86_64: swift

0 commit comments

Comments
 (0)