Skip to content

Commit b02d554

Browse files
authored
Merge pull request #17843 from jrose-apple/batteries-included
[Driver] Always link compiler_rt on Darwin (when available) rdar://problem/41911599
2 parents e4f8e6e + 51f6e9a commit b02d554

File tree

8 files changed

+122
-13
lines changed

8 files changed

+122
-13
lines changed

include/swift/Basic/Platform.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ namespace swift {
5858
/// Returns the platform Kind for Darwin triples.
5959
DarwinPlatformKind getDarwinPlatformKind(const llvm::Triple &triple);
6060

61+
/// Maps an arbitrary platform to its non-simulator equivalent.
62+
///
63+
/// If \p platform is not a simulator platform, it will be returned as is.
64+
DarwinPlatformKind getNonSimulatorPlatform(DarwinPlatformKind platform);
65+
6166
/// Returns the architecture component of the path for a given target triple.
6267
///
6368
/// Typically this is used for mapping the architecture component of the

lib/Basic/Platform.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ DarwinPlatformKind swift::getDarwinPlatformKind(const llvm::Triple &triple) {
7676
llvm_unreachable("Unsupported Darwin platform");
7777
}
7878

79+
DarwinPlatformKind swift::getNonSimulatorPlatform(DarwinPlatformKind platform) {
80+
switch (platform) {
81+
case DarwinPlatformKind::MacOS:
82+
return DarwinPlatformKind::MacOS;
83+
case DarwinPlatformKind::IPhoneOS:
84+
case DarwinPlatformKind::IPhoneOSSimulator:
85+
return DarwinPlatformKind::IPhoneOS;
86+
case DarwinPlatformKind::TvOS:
87+
case DarwinPlatformKind::TvOSSimulator:
88+
return DarwinPlatformKind::TvOS;
89+
case DarwinPlatformKind::WatchOS:
90+
case DarwinPlatformKind::WatchOSSimulator:
91+
return DarwinPlatformKind::WatchOS;
92+
}
93+
}
94+
7995
static StringRef getPlatformNameForDarwin(const DarwinPlatformKind platform) {
8096
switch (platform) {
8197
case DarwinPlatformKind::MacOS:

lib/Driver/DarwinToolChains.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,12 @@ toolchains::Darwin::constructInvocation(const InterpretJobAction &job,
8484
}
8585

8686
static StringRef
87-
getDarwinLibraryNameSuffixForTriple(const llvm::Triple &triple) {
88-
switch (getDarwinPlatformKind(triple)) {
87+
getDarwinLibraryNameSuffixForTriple(const llvm::Triple &triple,
88+
bool distinguishSimulator = true) {
89+
const DarwinPlatformKind kind = getDarwinPlatformKind(triple);
90+
const DarwinPlatformKind effectiveKind =
91+
distinguishSimulator ? kind : getNonSimulatorPlatform(kind);
92+
switch (effectiveKind) {
8993
case DarwinPlatformKind::MacOS:
9094
return "osx";
9195
case DarwinPlatformKind::IPhoneOS:
@@ -262,7 +266,22 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
262266
assert(Triple.isOSDarwin());
263267

264268
// FIXME: If we used Clang as a linker instead of going straight to ld,
265-
// we wouldn't have to replicate Clang's logic here.
269+
// we wouldn't have to replicate a bunch of Clang's logic here.
270+
271+
// Always link the regular compiler_rt if it's present.
272+
//
273+
// Note: Normally we'd just add this unconditionally, but it's valid to build
274+
// Swift and use it as a linker without building compiler_rt.
275+
SmallString<128> CompilerRTPath;
276+
getClangLibraryPath(context.Args, CompilerRTPath);
277+
llvm::sys::path::append(
278+
CompilerRTPath,
279+
Twine("libclang_rt.") +
280+
getDarwinLibraryNameSuffixForTriple(Triple, /*simulator*/false) +
281+
".a");
282+
if (llvm::sys::fs::exists(CompilerRTPath))
283+
Arguments.push_back(context.Args.MakeArgString(CompilerRTPath));
284+
266285
bool wantsObjCRuntime = false;
267286
if (Triple.isiOS())
268287
wantsObjCRuntime = Triple.isOSVersionLT(9);
@@ -375,9 +394,8 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
375394
}
376395

377396
if (context.Args.hasArg(options::OPT_profile_generate)) {
378-
SmallString<128> LibProfile(RuntimeLibPath);
379-
llvm::sys::path::remove_filename(LibProfile); // remove platform name
380-
llvm::sys::path::append(LibProfile, "clang", "lib", "darwin");
397+
SmallString<128> LibProfile;
398+
getClangLibraryPath(context.Args, LibProfile);
381399

382400
StringRef RT;
383401
if (Triple.isiOS()) {

test/Driver/linker-clang_rt.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Make sure that the platform-appropriate clang_rt library (found relative to
2+
// the compiler) is included when using Swift as a linker (with Apple targets).
3+
4+
// We use hard links to make sure the Swift driver really thinks it's been
5+
// moved.
6+
7+
// RUN: rm -rf %t
8+
// RUN: %empty-directory(%t/bin)
9+
// RUN: %hardlink-or-copy(from: %swift_driver_plain, to: %t/bin/swiftc)
10+
// RUN: %empty-directory(%t/lib/clang/darwin/)
11+
12+
// RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-macosx10.9 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-NO-RUNTIME %s
13+
14+
// RUN: touch %t/lib/clang/darwin/libclang_rt.osx.a %t/lib/clang/darwin/libclang_rt.ios.a %t/lib/clang/darwin/libclang_rt.tvos.a %t/lib/clang/darwin/libclang_rt.watchos.a
15+
16+
// RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-macosx10.9 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix MACOS %s
17+
18+
// RUN: %t/bin/swiftc -driver-print-jobs -target i386-apple-ios7 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix IOS %s
19+
// RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-ios7 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix IOS %s
20+
// RUN: %t/bin/swiftc -driver-print-jobs -target armv7s-apple-ios7 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix IOS %s
21+
// RUN: %t/bin/swiftc -driver-print-jobs -target arm64-apple-ios7 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix IOS %s
22+
23+
// RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-ios9 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix TVOS %s
24+
// RUN: %t/bin/swiftc -driver-print-jobs -target arm64-apple-tvos9 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix TVOS %s
25+
26+
// RUN: %t/bin/swiftc -driver-print-jobs -target i386-apple-watchos2 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix WATCHOS %s
27+
// RUN: %t/bin/swiftc -driver-print-jobs -target armv7k-apple-watchos2 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix WATCHOS %s
28+
29+
// Clean up the test executable because hard links are expensive.
30+
// RUN: rm -f %t/bin/swiftc
31+
32+
// CHECK: bin/ld{{"? }}
33+
// CHECK-NO-RUNTIME-NOT: libclang_rt
34+
// CHECK-MACOS-SAME: {{[^ ]+/lib/clang/darwin/libclang_rt.osx.a}}
35+
// CHECK-IOS-SAME: {{[^ ]+/lib/clang/darwin/libclang_rt.ios.a}}
36+
// CHECK-TVOS-SAME: {{[^ ]+/lib/clang/darwin/libclang_rt.tvos.a}}
37+
// CHECK-WATCHOS-SAME: {{[^ ]+/lib/clang/darwin/libclang_rt.watchos.a}}
38+
// CHECK-SAME: -o {{[^ ]+}}

test/Driver/linker.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787

8888
// SIMPLE: bin/ld{{"? }}
8989
// SIMPLE-NOT: -syslibroot
90-
// SIMPLE-DAG: -macosx_version_min 10.{{[0-9]+}}.{{[0-9]+}}
90+
// SIMPLE: -macosx_version_min 10.{{[0-9]+}}.{{[0-9]+}}
9191
// SIMPLE-NOT: -syslibroot
9292
// SIMPLE: -o linker
9393

@@ -312,11 +312,11 @@
312312

313313

314314
// FILELIST: bin/ld{{"? }}
315-
// FILELIST-NOT: .o
315+
// FILELIST-NOT: .o{{"? }}
316316
// FILELIST: -filelist {{"?[^-]}}
317-
// FILELIST-NOT: .o
318-
// FILELIST: /a.o
319-
// FILELIST-NOT: .o
317+
// FILELIST-NOT: .o{{"? }}
318+
// FILELIST: /a.o{{"? }}
319+
// FILELIST-NOT: .o{{"? }}
320320
// FILELIST: -o linker
321321

322322

test/lit.cfg

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -945,8 +945,9 @@ def source_compiler_rt_libs(path):
945945
if lib.startswith('libclang_rt.')
946946
and config.compiler_rt_platform in lib])
947947

948-
source_compiler_rt_libs(make_path(test_resource_dir, 'clang', 'lib',
949-
platform.system().lower()))
948+
compiler_rt_dir = make_path(test_resource_dir, 'clang', 'lib',
949+
platform.system().lower())
950+
source_compiler_rt_libs(compiler_rt_dir)
950951

951952
def check_runtime_libs(features_to_check):
952953
for lib in config.compiler_rt_libs:
@@ -967,6 +968,17 @@ if run_ptrsize != "32":
967968

968969
check_runtime_libs(runtime_libs)
969970

971+
# From https://stackoverflow.com/a/2393022
972+
def strip_right(text, suffix):
973+
if not text.endswith(suffix):
974+
return text
975+
return text[:len(text)-len(suffix)]
976+
977+
base_runtime_lib_name = (
978+
'libclang_rt.' + strip_right(config.compiler_rt_platform, 'sim') + '.a')
979+
if os.path.exists(make_path(compiler_rt_dir, base_runtime_lib_name)):
980+
config.available_features.add('c_runtime')
981+
970982
if not getattr(config, 'target_run_simple_swift', None):
971983
config.target_run_simple_swift = (
972984
'%%empty-directory(%%t) && '
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <stdbool.h>
2+
3+
static inline bool isRunningOnFairlyRecentOS() {
4+
if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
5+
return true;
6+
} else {
7+
return false;
8+
}
9+
}

validation-test/Driver/clang_rt.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-build-swift -emit-executable %s -import-objc-header %S/Inputs/clang_rt-helper.h -o %t
2+
3+
// REQUIRES: c_runtime
4+
5+
// Just make sure we can build and link successfully.
6+
7+
if isRunningOnFairlyRecentOS() {
8+
print("new!")
9+
} else {
10+
print("old...")
11+
}

0 commit comments

Comments
 (0)