Skip to content

Commit

Permalink
Merge pull request #1667 from swiftlang/hyp/reinstate-android-driver-…
Browse files Browse the repository at this point in the history
…changes-with-fixes

Reinstate: SwiftDriver: initial work to properly handle android cross-compilation
  • Loading branch information
hyp authored Jul 17, 2024
2 parents 8d32f70 + b54d4a2 commit 661e0bc
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 9 deletions.
31 changes: 23 additions & 8 deletions Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,24 @@ extension GenericUnixToolchain {
}
}

if targetInfo.sdkPath != nil {
for libpath in targetInfo.runtimeLibraryImportPaths {
commandLine.appendFlag(.L)
commandLine.appendPath(VirtualPath.lookup(libpath.path))
}
}

if !isEmbeddedEnabled && !parsedOptions.hasArgument(.nostartfiles) {
let swiftrtPath = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
.appending(
components: targetTriple.platformName() ?? "",
String(majorArchitectureName(for: targetTriple)),
"swiftrt.o"
)
commandLine.appendPath(swiftrtPath)
let rsrc: VirtualPath
// Prefer the swiftrt.o runtime file from the SDK if it's specified.
if let sdk = targetInfo.sdkPath {
rsrc = VirtualPath.lookup(sdk.path).appending(components: "usr", "lib", "swift")
} else {
rsrc = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
}
let platform: String = targetTriple.platformName() ?? ""
let architecture: String = majorArchitectureName(for: targetTriple)
commandLine.appendPath(rsrc.appending(components: platform, architecture, "swiftrt.o"))
}

// If we are linking statically, we need to add all
Expand Down Expand Up @@ -194,7 +204,12 @@ extension GenericUnixToolchain {
commandLine.appendPath(try VirtualPath(path: opt.argument.asSingle))
}

if let path = targetInfo.sdkPath?.path {
if targetTriple.environment == .android {
if let sysroot = try getAndroidNDKSysrootPath() {
commandLine.appendFlag("--sysroot")
commandLine.appendPath(sysroot)
}
} else if let path = targetInfo.sdkPath?.path {
commandLine.appendFlag("--sysroot")
commandLine.appendPath(VirtualPath.lookup(path))
}
Expand Down
46 changes: 46 additions & 0 deletions Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,50 @@ public final class GenericUnixToolchain: Toolchain {
let environment = (targetTriple.environment == .android) ? "-android" : ""
return "libclang_rt.\(sanitizer.libraryName)-\(targetTriple.archName)\(environment).a"
}

private func getAndroidNDKHostOSSuffix() -> String? {
#if os(Windows)
"windows"
#elseif os(Linux)
"linux"
#elseif os(macOS)
"darwin"
#else
// The NDK is only available on macOS, linux and windows hosts.
nil
#endif
}

func getAndroidNDKSysrootPath() throws -> AbsolutePath? {
#if arch(x86_64)
// The NDK's sysroot should be specified in the environment.
guard let ndk = env["ANDROID_NDK_ROOT"],
let osSuffix = getAndroidNDKHostOSSuffix() else {
return nil
}
var sysroot: AbsolutePath =
try AbsolutePath(validating: ndk)
.appending(components: "toolchains", "llvm", "prebuilt")
.appending(component: "\(osSuffix)-x86_64")
.appending(component: "sysroot")
return sysroot
#else
// The NDK is only available on an x86_64 host.
return nil
#endif
}

public func addPlatformSpecificCommonFrontendOptions(
commandLine: inout [Job.ArgTemplate],
inputs: inout [TypedVirtualPath],
frontendTargetInfo: FrontendTargetInfo,
driver: inout Driver
) throws {
if driver.targetTriple.environment == .android {
if let sysroot = try getAndroidNDKSysrootPath() {
commandLine.appendFlag("-sysroot")
commandLine.appendFlag(sysroot.pathString)
}
}
}
}
24 changes: 23 additions & 1 deletion Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7151,10 +7151,14 @@ final class SwiftDriverTests: XCTestCase {

func testRelativeResourceDir() throws {
do {
// Reset the environment to avoid 'SDKROOT' influencing the
// linux driver paths and taking the priority over the resource directory.
var env = ProcessEnv.vars
env["SDKROOT"] = nil
var driver = try Driver(args: ["swiftc",
"-target", "x86_64-unknown-linux", "-lto=llvm-thin",
"foo.swift",
"-resource-dir", "resource/dir"])
"-resource-dir", "resource/dir"], env: env)
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
let compileJob = plannedJobs[0]
XCTAssertEqual(compileJob.kind, .compile)
Expand All @@ -7170,6 +7174,24 @@ final class SwiftDriverTests: XCTestCase {
}
}

func testSDKDirLinuxPrioritizedOverRelativeResourceDirForLinkingSwiftRT() throws {
do {
let sdkRoot = try testInputsPath.appending(component: "mock-sdk.sdk")
var env = ProcessEnv.vars
env["SDKROOT"] = sdkRoot.pathString
var driver = try Driver(args: ["swiftc",
"-target", "x86_64-unknown-linux", "-lto=llvm-thin",
"foo.swift",
"-resource-dir", "resource/dir"], env: env)
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
let compileJob = plannedJobs[0]
XCTAssertEqual(compileJob.kind, .compile)
let linkJob = plannedJobs[1]
XCTAssertEqual(linkJob.kind, .link)
XCTAssertTrue(linkJob.commandLine.contains(try toPathOption(sdkRoot.pathString + "/usr/lib/swift/linux/x86_64/swiftrt.o")))
}
}

func testSanitizerArgsForTargets() throws {
let targets = ["x86_64-unknown-freebsd", "x86_64-unknown-linux", "x86_64-apple-macosx10.9"]
try targets.forEach {
Expand Down

0 comments on commit 661e0bc

Please sign in to comment.