Skip to content

Commit 2a2d40d

Browse files
committed
Driver: Link against compatibility library for deploying back to Swift 5.0 runtimes
1 parent 9e1907a commit 2a2d40d

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,4 +888,8 @@ def vfsoverlay : JoinedOrSeparate<["-"], "vfsoverlay">,
888888
def vfsoverlay_EQ : Joined<["-"], "vfsoverlay=">,
889889
Alias<vfsoverlay>;
890890

891+
// Runtime compatibility version
892+
def runtime_compatibility_version : Separate<["-"], "runtime-compatibility-version">,
893+
Flags<[FrontendOption]>,
894+
HelpText<"Link compatibility library for Swift runtime version, or 'none'">;
891895
include "FrontendOptions.td"

lib/Driver/DarwinToolChains.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,46 @@ static bool wantsObjCRuntime(const llvm::Triple &triple) {
221221
llvm_unreachable("unknown Darwin OS");
222222
}
223223

224+
/// Return the earliest backward deployment compatibility version we need to
225+
/// link in for the given target triple, if any.
226+
static Optional<std::pair<unsigned, unsigned>>
227+
getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple) {
228+
unsigned Major, Minor, Micro;
229+
230+
if (Triple.isMacOSX()) {
231+
Triple.getMacOSXVersion(Major, Minor, Micro);
232+
if (Major == 10) {
233+
if (Minor <= 14) {
234+
return std::make_pair(5u, 0u);
235+
} else {
236+
return None;
237+
}
238+
} else {
239+
return None;
240+
}
241+
} else if (Triple.isiOS()) { // includes tvOS
242+
Triple.getiOSVersion(Major, Minor, Micro);
243+
if (Major <= 12) {
244+
return std::make_pair(5u, 0u);
245+
} else {
246+
return None;
247+
}
248+
} else if (Triple.isWatchOS()) {
249+
Triple.getWatchOSVersion(Major, Minor, Micro);
250+
if (Major <= 5) {
251+
return std::make_pair(5u, 0u);
252+
} else {
253+
return None;
254+
}
255+
} else {
256+
return None;
257+
}
258+
}
259+
224260
ToolChain::InvocationInfo
225261
toolchains::Darwin::constructInvocation(const LinkJobAction &job,
226-
const JobContext &context) const {
262+
const JobContext &context) const
263+
{
227264
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
228265
"Invalid linker output type.");
229266

@@ -392,6 +429,38 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
392429
SmallString<128> RuntimeLibPath;
393430
getRuntimeLibraryPath(RuntimeLibPath, context.Args, /*Shared=*/true);
394431

432+
// Link compatibility libraries, if we're deploying back to OSes that
433+
// have an older Swift runtime.
434+
Optional<std::pair<unsigned, unsigned>> runtimeCompatibilityVersion;
435+
436+
if (context.Args.hasArg(options::OPT_runtime_compatibility_version)) {
437+
auto value = context.Args.getLastArgValue(options::OPT_runtime_compatibility_version);
438+
if (value.equals("5.0")) {
439+
runtimeCompatibilityVersion = std::make_pair(5u, 0u);
440+
} else if (value.equals("none")) {
441+
runtimeCompatibilityVersion = None;
442+
} else {
443+
// TODO: diagnose unknown runtime compatibility version?
444+
}
445+
} else if (job.getKind() == LinkKind::Executable) {
446+
runtimeCompatibilityVersion
447+
= getSwiftRuntimeCompatibilityVersionForTarget(Triple);
448+
}
449+
450+
if (runtimeCompatibilityVersion) {
451+
if (*runtimeCompatibilityVersion <= std::make_pair(5u, 0u)) {
452+
// Swift 5.0 compatibility library
453+
SmallString<128> BackDeployLib;
454+
BackDeployLib.append(RuntimeLibPath);
455+
llvm::sys::path::append(BackDeployLib, "libswiftCompatibility50.a");
456+
457+
if (llvm::sys::fs::exists(BackDeployLib)) {
458+
Arguments.push_back("-force_load");
459+
Arguments.push_back(context.Args.MakeArgString(BackDeployLib));
460+
}
461+
}
462+
}
463+
395464
// Link the standard library.
396465
Arguments.push_back("-L");
397466
if (context.Args.hasFlag(options::OPT_static_stdlib,

validation-test/stdlib/MicroStdlib/Inputs/RuntimeStubs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ void swift_storeEnumTagSinglePayloadGeneric(void) {}
1717
void swift_retain(){}
1818
void swift_allocBox(){}
1919
void swift_getWitnessTable(void) {}
20+
void swift_getObjCClassMetadata(void) {}

0 commit comments

Comments
 (0)