Skip to content

Commit 270bf6c

Browse files
authored
Merge pull request #1560 from compnerd/android
SwiftDriver: initial work to properly handle android cross-compilation
2 parents f4709ef + 7e83253 commit 270bf6c

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed

Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift

+23-8
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,24 @@ extension GenericUnixToolchain {
147147
}
148148
}
149149

150+
if targetInfo.sdkPath != nil {
151+
for libpath in targetInfo.runtimeLibraryImportPaths {
152+
commandLine.appendFlag(.L)
153+
commandLine.appendPath(VirtualPath.lookup(libpath.path))
154+
}
155+
}
156+
150157
if !isEmbeddedEnabled && !parsedOptions.hasArgument(.nostartfiles) {
151-
let swiftrtPath = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
152-
.appending(
153-
components: targetTriple.platformName() ?? "",
154-
String(majorArchitectureName(for: targetTriple)),
155-
"swiftrt.o"
156-
)
157-
commandLine.appendPath(swiftrtPath)
158+
let rsrc: VirtualPath
159+
// Prefer the swiftrt.o runtime file from the SDK if it's specified.
160+
if let sdk = targetInfo.sdkPath.flatMap({ VirtualPath.lookup($0.path) }) {
161+
rsrc = sdk.appending(components: "usr", "lib", "swift")
162+
} else {
163+
rsrc = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
164+
}
165+
let platform: String = targetTriple.platformName() ?? ""
166+
let architecture: String = majorArchitectureName(for: targetTriple)
167+
commandLine.appendPath(rsrc.appending(components: platform, architecture, "swiftrt.o"))
158168
}
159169

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

197-
if let path = targetInfo.sdkPath?.path {
207+
if targetTriple.environment == .android {
208+
if let sysroot = try getAndroidNDKSysrootPath() {
209+
commandLine.appendFlag("--sysroot")
210+
commandLine.appendPath(sysroot)
211+
}
212+
} else if let path = targetInfo.sdkPath?.path {
198213
commandLine.appendFlag("--sysroot")
199214
commandLine.appendPath(VirtualPath.lookup(path))
200215
}

Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift

+46
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,50 @@ public final class GenericUnixToolchain: Toolchain {
117117
let environment = (targetTriple.environment == .android) ? "-android" : ""
118118
return "libclang_rt.\(sanitizer.libraryName)-\(targetTriple.archName)\(environment).a"
119119
}
120+
121+
private func getAndroidNDKHostOSSuffix() -> String? {
122+
#if os(Windows)
123+
"windows"
124+
#elseif os(Linux)
125+
"linux"
126+
#elseif os(macOS)
127+
"darwin"
128+
#else
129+
// The NDK is only available on macOS, linux and windows hosts.
130+
nil
131+
#endif
132+
}
133+
134+
func getAndroidNDKSysrootPath() throws -> AbsolutePath? {
135+
#if arch(x86_64)
136+
// The NDK's sysroot should be specified in the environment.
137+
guard let ndk = env["ANDROID_NDK_ROOT"],
138+
let osSuffix = getAndroidNDKHostOSSuffix() else {
139+
return nil
140+
}
141+
var sysroot: AbsolutePath =
142+
try AbsolutePath(validating: ndk)
143+
.appending(components: "toolchains", "llvm", "prebuilt")
144+
.appending(component: "\(osSuffix)-x86_64")
145+
.appending(component: "sysroot")
146+
return sysroot
147+
#else
148+
// The NDK is only available on an x86_64 host.
149+
return nil
150+
#endif
151+
}
152+
153+
public func addPlatformSpecificCommonFrontendOptions(
154+
commandLine: inout [Job.ArgTemplate],
155+
inputs: inout [TypedVirtualPath],
156+
frontendTargetInfo: FrontendTargetInfo,
157+
driver: inout Driver
158+
) throws {
159+
if driver.targetTriple.environment == .android {
160+
if let sysroot = try getAndroidNDKSysrootPath() {
161+
commandLine.appendFlag("-sysroot")
162+
commandLine.appendFlag(sysroot.pathString)
163+
}
164+
}
165+
}
120166
}

Sources/SwiftOptions/Options.swift

+2
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ extension Option {
789789
public static let swiftVersion: Option = Option("-swift-version", .separate, attributes: [.frontend, .moduleInterface], metaVar: "<vers>", helpText: "Interpret input according to a specific Swift language version number")
790790
public static let switchCheckingInvocationThresholdEQ: Option = Option("-switch-checking-invocation-threshold=", .joined, attributes: [.helpHidden, .frontend, .noDriver])
791791
public static let symbolGraphMinimumAccessLevel: Option = Option("-symbol-graph-minimum-access-level", .separate, attributes: [.helpHidden, .frontend, .noInteractive, .supplementaryOutput], metaVar: "<level>", helpText: "Include symbols with this access level or more when emitting a symbol graph")
792+
public static let sysroot: Option = Option("-sysroot", .separate, attributes: [.frontend, .argumentIsPath], metaVar: "<sysroot>", helpText: "Native Platform sysroot")
792793
public static let S: Option = Option("-S", .flag, alias: Option.emitAssembly, attributes: [.frontend, .noInteractive], group: .modes)
793794
public static let tabWidth: Option = Option("-tab-width", .separate, attributes: [.noInteractive, .noBatch, .indent], metaVar: "<n>", helpText: "Width of tab character.", group: .codeFormatting)
794795
public static let targetCpu: Option = Option("-target-cpu", .separate, attributes: [.frontend, .moduleInterface], helpText: "Generate code for a particular CPU variant")
@@ -1653,6 +1654,7 @@ extension Option {
16531654
Option.swiftVersion,
16541655
Option.switchCheckingInvocationThresholdEQ,
16551656
Option.symbolGraphMinimumAccessLevel,
1657+
Option.sysroot,
16561658
Option.S,
16571659
Option.tabWidth,
16581660
Option.targetCpu,

0 commit comments

Comments
 (0)