Skip to content

Commit a128b82

Browse files
committed
[Unix] Move all ELF SDK runtime libraries into their own architecture-specific directories
This is needed for all platforms that don't have multi-architecture libraries like Darwin. Also, add the new architecture-specific rpath to the resulting swift-driver and make it possible to cross-compile this repo for non-Darwin platforms on Darwin. The driver changes are the Swift translation of the Driver-specific changes of swiftlang/swift#63782. Resolves swiftlang/swift#63645
1 parent 679b324 commit a128b82

File tree

5 files changed

+51
-57
lines changed

5 files changed

+51
-57
lines changed

Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,6 @@ extension GenericUnixToolchain {
3838
}
3939
}
4040

41-
private func majorArchitectureName(for triple: Triple) -> String {
42-
// The concept of a "major" arch name only applies to Linux triples
43-
guard triple.os == .linux else { return triple.archName }
44-
45-
// HACK: We don't wrap LLVM's ARM target architecture parsing, and we should
46-
// definitely not try to port it. This check was only normalizing
47-
// "armv7a/armv7r" and similar variants for armv6 to 'armv7' and
48-
// 'armv6', so just take a brute-force approach
49-
if triple.archName.contains("armv7") { return "armv7" }
50-
if triple.archName.contains("armv6") { return "armv6" }
51-
if triple.archName.contains("armv5") { return "armv5" }
52-
return triple.archName
53-
}
54-
5541
public func addPlatformSpecificLinkerArgs(
5642
to commandLine: inout [Job.ArgTemplate],
5743
parsedOptions: inout ParsedOptions,

Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ extension Toolchain {
3838
isShared: Bool
3939
) throws -> [VirtualPath] {
4040
let triple = targetInfo.target.triple
41-
let resourceDirPath = VirtualPath.lookup(targetInfo.runtimeResourcePath.path).appending(component: triple.platformName() ?? "")
41+
var resourceDirPath = VirtualPath.lookup(targetInfo.runtimeResourcePath.path).appending(component: triple.platformName() ?? "")
42+
// Only Darwin has multi-architecture libraries, so link against architecture-specific libraries everywhere else.
43+
if !triple.isDarwin {
44+
resourceDirPath = resourceDirPath.appending(component: majorArchitectureName(for: triple))
45+
}
4246
var result = [resourceDirPath]
4347

4448
let secondaryResourceDir = computeSecondaryResourceDirPath(for: triple, primaryPath: resourceDirPath)
@@ -84,6 +88,20 @@ extension Toolchain {
8488
commandLine.appendFlag(match.option.spelling + match.argument.asSingle)
8589
}
8690
}
91+
92+
func majorArchitectureName(for triple: Triple) -> String {
93+
// The concept of a "major" arch name only applies to Linux triples
94+
guard triple.os == .linux else { return triple.archName }
95+
96+
// HACK: We don't wrap LLVM's ARM target architecture parsing, and we should
97+
// definitely not try to port it. This check was only normalizing
98+
// "armv7a/armv7r" and similar variants for armv6 to 'armv7' and
99+
// 'armv6', so just take a brute-force approach
100+
if triple.archName.contains("armv7") { return "armv7" }
101+
if triple.archName.contains("armv6") { return "armv6" }
102+
if triple.archName.contains("armv5") { return "armv5" }
103+
return triple.archName
104+
}
87105
}
88106

89107
// MARK: - Common argument routines

Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,6 @@ import SwiftOptions
1515
import func TSCBasic.lookupExecutablePath
1616
import struct TSCBasic.AbsolutePath
1717

18-
private func architecture(for triple: Triple) -> String {
19-
// The concept of a "major" arch name only applies to Linux triples
20-
guard triple.os == .linux else { return triple.archName }
21-
22-
// HACK: We don't wrap LLVM's ARM target architecture parsing, and we should
23-
// definitely not try to port it. This check was only normalizing
24-
// "armv7a/armv7r" and similar variants for armv6 to 'armv7' and
25-
// 'armv6', so just take a brute-force approach
26-
if triple.archName.contains("armv7") { return "armv7" }
27-
if triple.archName.contains("armv6") { return "armv6" }
28-
return triple.archName
29-
}
30-
3118
extension WindowsToolchain {
3219
public func addPlatformSpecificLinkerArgs(to commandLine: inout [Job.ArgTemplate],
3320
parsedOptions: inout ParsedOptions,
@@ -137,7 +124,7 @@ extension WindowsToolchain {
137124
rsrc = try VirtualPath(path: AbsolutePath(validating: sdk)
138125
.appending(components: "usr", "lib", "swift",
139126
targetTriple.platformName() ?? "",
140-
architecture(for: targetTriple))
127+
majorArchitectureName(for: targetTriple))
141128
.pathString)
142129
} else {
143130
rsrc = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6267,10 +6267,10 @@ final class SwiftDriverTests: XCTestCase {
62676267
XCTAssertEqual(linkJob.kind, .link)
62686268
XCTAssertTrue(linkJob.commandLine.contains(subsequence:
62696269
["-Xlinker", "-rpath",
6270-
"-Xlinker", .path(.relative(.init("resource/dir/linux")))]))
6270+
"-Xlinker", .path(.relative(.init("resource/dir/linux/x86_64")))]))
62716271
XCTAssertTrue(linkJob.commandLine.contains(.path(.relative(.init("resource/dir/linux/x86_64/swiftrt.o")))))
62726272
XCTAssertTrue(linkJob.commandLine.contains(subsequence:
6273-
["-L", .path(.relative(.init("resource/dir/linux")))]))
6273+
["-L", .path(.relative(.init("resource/dir/linux/x86_64")))]))
62746274
}
62756275
}
62766276

Utilities/build-script-helper.py

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import subprocess
1010
import sys
1111
import errno
12-
import re
1312

1413
if platform.system() == 'Darwin':
1514
shared_lib_ext = '.dylib'
@@ -80,7 +79,9 @@ def get_swiftpm_options(args):
8079
if args.verbose:
8180
swiftpm_args += ['--verbose']
8281

83-
if platform.system() == 'Darwin':
82+
build_arch = args.build_target.split('-')[0]
83+
build_os = args.build_target.split('-')[2]
84+
if build_os.startswith('macosx'):
8485
swiftpm_args += [
8586
# Relative library rpath for swift; will only be used when /usr/lib/swift
8687
# is not available.
@@ -99,18 +100,17 @@ def get_swiftpm_options(args):
99100
if args.cross_compile_hosts:
100101
swiftpm_args += ['--destination', args.cross_compile_config]
101102

102-
if 'ANDROID_DATA' in os.environ or (args.cross_compile_hosts and re.match(
103-
'android-', args.cross_compile_hosts[0])):
103+
if '-android' in args.build_target:
104104
swiftpm_args += [
105-
'-Xlinker', '-rpath', '-Xlinker', '$ORIGIN/../lib/swift/android',
105+
'-Xlinker', '-rpath', '-Xlinker', '$ORIGIN/../lib/swift/android/' + build_arch,
106106
# SwiftPM will otherwise try to compile against GNU strerror_r on
107107
# Android and fail.
108108
'-Xswiftc', '-Xcc', '-Xswiftc', '-U_GNU_SOURCE',
109109
]
110110
else:
111111
# Library rpath for swift, dispatch, Foundation, etc. when installing
112112
swiftpm_args += [
113-
'-Xlinker', '-rpath', '-Xlinker', '$ORIGIN/../lib/swift/linux',
113+
'-Xlinker', '-rpath', '-Xlinker', '$ORIGIN/../lib/swift/' + build_os + '/' + build_arch,
114114
]
115115

116116
if args.action == 'install':
@@ -158,15 +158,14 @@ def handle_invocation(args):
158158
swiftpm_args = get_swiftpm_options(args)
159159
toolchain_bin = os.path.join(args.toolchain, 'bin')
160160
swift_exec = os.path.join(toolchain_bin, 'swift')
161-
swiftc_exec = os.path.join(toolchain_bin, 'swiftc')
162161

163162
# Platform-specific targets for which we must build swift-driver
164163
if args.cross_compile_hosts:
165164
targets = args.cross_compile_hosts
166-
elif platform.system() == 'Darwin':
167-
targets = [get_build_target(swiftc_exec, args) + macos_deployment_target]
165+
elif '-apple-macosx' in args.build_target:
166+
targets = [args.build_target + macos_deployment_target]
168167
else:
169-
targets = [get_build_target(swiftc_exec, args)]
168+
targets = [args.build_target]
170169

171170
env = os.environ
172171
# Use local dependencies (i.e. checked out next to swift-driver).
@@ -182,7 +181,7 @@ def handle_invocation(args):
182181
env['SWIFT_EXEC'] = '%sc' % (swift_exec)
183182

184183
if args.action == 'build':
185-
if args.cross_compile_hosts and not re.match('-macosx', args.cross_compile_hosts[0]):
184+
if args.cross_compile_hosts and not '-macosx' in args.cross_compile_hosts[0]:
186185
swiftpm('build', swift_exec, swiftpm_args, env)
187186
else:
188187
build_using_cmake(args, toolchain_bin, args.build_path, targets)
@@ -205,7 +204,7 @@ def handle_invocation(args):
205204
env['SWIFT_DRIVER_LIT_DIR'] = args.lit_test_dir
206205
swiftpm('test', swift_exec, test_args, env)
207206
elif args.action == 'install':
208-
if platform.system() == 'Darwin':
207+
if '-apple-macosx' in args.build_target:
209208
build_using_cmake(args, toolchain_bin, args.build_path, targets)
210209
install(args, args.build_path, targets)
211210
else:
@@ -425,7 +424,7 @@ def build_using_cmake(args, toolchain_bin, build_dir, targets):
425424
base_cmake_flags = []
426425
swift_flags = base_swift_flags.copy()
427426
swift_flags.append('-target %s' % target)
428-
if platform.system() == 'Darwin':
427+
if '-apple-macosx' in args.build_target:
429428
base_cmake_flags.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=%s' % macos_deployment_target)
430429
base_cmake_flags.append('-DCMAKE_OSX_ARCHITECTURES=%s' % target.split('-')[0])
431430

@@ -477,7 +476,7 @@ def build_llbuild_using_cmake(args, target, swiftc_exec, build_dir, base_cmake_f
477476
llbuild_cmake_flags.append('-DSQLite3_INCLUDE_DIR=%s/usr/include' % args.sysroot)
478477
# FIXME: This may be particularly hacky but CMake finds a different version of libsqlite3
479478
# on some machines. This is also Darwin-specific...
480-
if platform.system() == 'Darwin':
479+
if '-apple-macosx' in args.build_target:
481480
llbuild_cmake_flags.append('-DSQLite3_LIBRARY=%s/usr/lib/libsqlite3.tbd' % args.sysroot)
482481
llbuild_swift_flags = swift_flags[:]
483482

@@ -517,7 +516,7 @@ def build_yams_using_cmake(args, target, swiftc_exec, build_dir, base_cmake_flag
517516
'-DCMAKE_C_COMPILER:=clang',
518517
'-DBUILD_SHARED_LIBS=OFF']
519518

520-
if platform.system() == 'Darwin':
519+
if '-apple-macosx' in args.build_target:
521520
yams_cmake_flags.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=%s' % macos_deployment_target)
522521
yams_cmake_flags.append('-DCMAKE_C_FLAGS=-target %s' % target)
523522
else:
@@ -595,16 +594,20 @@ def cmake_build(args, swiftc_exec, cmake_args, swift_flags, source_path,
595594
if args.verbose:
596595
print(stdout)
597596

598-
def get_build_target(swiftc_path, args):
597+
def get_build_target(swiftc_path, args, cross_compile=False):
599598
"""Returns the target-triple of the current machine."""
600599
try:
601-
target_info_json = subprocess.check_output([swiftc_path, '-print-target-info'],
600+
command = [swiftc_path, '-print-target-info']
601+
if cross_compile:
602+
cross_compile_json = json.load(open(args.cross_compile_config))
603+
command += ['-target', cross_compile_json["target"]]
604+
target_info_json = subprocess.check_output(command,
602605
stderr=subprocess.PIPE,
603606
universal_newlines=True).strip()
604607
args.target_info = json.loads(target_info_json)
605608
triple = args.target_info['target']['triple']
606609
# Windows also wants unversionedTriple, but does not use this.
607-
if platform.system() == 'Darwin':
610+
if '-apple-macosx' in args.target_info["target"]["unversionedTriple"]:
608611
triple = args.target_info['target']['unversionedTriple']
609612
return triple
610613
except Exception as e:
@@ -662,18 +665,18 @@ def add_common_args(parser):
662665
args.build_path = os.path.abspath(args.build_path)
663666
args.toolchain = os.path.abspath(args.toolchain)
664667

665-
if platform.system() == 'Darwin':
668+
swift_exec = os.path.join(os.path.join(args.toolchain, 'bin'), 'swiftc')
669+
args.build_target = get_build_target(swift_exec, args, cross_compile=(True if args.cross_compile_config else False))
670+
if '-apple-macosx' in args.build_target:
666671
args.sysroot = call_output(["xcrun", "--sdk", "macosx", "--show-sdk-path"], verbose=args.verbose)
667672
else:
668673
args.sysroot = None
669674

670-
swift_exec = os.path.join(os.path.join(args.toolchain, 'bin'), 'swiftc')
671-
build_target = get_build_target(swift_exec, args)
672-
if (build_target == 'x86_64-apple-macosx' and 'macosx-arm64' in args.cross_compile_hosts):
673-
args.cross_compile_hosts = [build_target + macos_deployment_target, 'arm64-apple-macosx%s' % macos_deployment_target]
674-
elif (build_target == 'arm64-apple-macosx' and 'macosx-x86_64' in args.cross_compile_hosts):
675-
args.cross_compile_hosts = [build_target + macos_deployment_target, 'x86_64-apple-macosx%s' % macos_deployment_target]
676-
elif args.cross_compile_hosts and re.match('android-', args.cross_compile_hosts[0]):
675+
if (args.build_target == 'x86_64-apple-macosx' and 'macosx-arm64' in args.cross_compile_hosts):
676+
args.cross_compile_hosts = [args.build_target + macos_deployment_target, 'arm64-apple-macosx%s' % macos_deployment_target]
677+
elif (args.build_target == 'arm64-apple-macosx' and 'macosx-x86_64' in args.cross_compile_hosts):
678+
args.cross_compile_hosts = [args.build_target + macos_deployment_target, 'x86_64-apple-macosx%s' % macos_deployment_target]
679+
elif args.cross_compile_hosts and 'android-' in args.cross_compile_hosts[0]:
677680
print('Cross-compiling for %s' % args.cross_compile_hosts[0])
678681
elif args.cross_compile_hosts:
679682
error("cannot cross-compile for %s" % cross_compile_hosts)

0 commit comments

Comments
 (0)