Skip to content

Commit 112ae4a

Browse files
committed
SwiftDriver: initial work to properly handle android cross-compilation
The intent here is to permit the Windows/macOS style cross-compilation for Android. This involves passing `-sdk` with the path to the "Swift SDK" which overlays the system's native SDK (NDK). The `ANDROID_NDK_ROOT` is a well-defined environment variable (setup by the SDK installer as well as a general expectation for Android development) that identifies the root of the installation of the NDK. This allows us to locate the native SDK root (`--sysroot`) for driving the linker driver amongst other paths.
1 parent 3519916 commit 112ae4a

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

+20
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,26 @@ extension Driver {
182182
try commandLine.appendAll(.F, .Fsystem, from: &parsedOptions)
183183
try commandLine.appendAll(.vfsoverlay, from: &parsedOptions)
184184

185+
if targetTriple.environment == .android {
186+
if let ndk = env["ANDROID_NDK_ROOT"] {
187+
var sysroot: AbsolutePath =
188+
try AbsolutePath(validating: ndk)
189+
.appending(components: "toolchains", "llvm", "prebuilt")
190+
#if arch(x86_64)
191+
#if os(Windows)
192+
.appending(component: "windows-x86_64")
193+
#elseif os(Linux)
194+
.appending(component: "linux-x86_64")
195+
#else
196+
.appending(component: "darwin-x86_64")
197+
#endif
198+
#endif
199+
.appending(component: "sysroot")
200+
commandLine.appendFlag("-sysroot")
201+
commandLine.appendFlag(sysroot.pathString)
202+
}
203+
}
204+
185205
if let gccToolchain = parsedOptions.getLastArgument(.gccToolchain) {
186206
appendXccFlag("--gcc-toolchain=\(gccToolchain.asSingle)")
187207
}

Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift

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

150+
if let sdk = parsedOptions.getLastArgument(.sdk)?.asSingle ?? env["SDKROOT"], !sdk.isEmpty {
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+
if let sdk = parsedOptions.getLastArgument(.sdk)?.asSingle ?? env["SDKROOT"], !sdk.isEmpty {
160+
rsrc = try VirtualPath(path: AbsolutePath(validating: sdk)
161+
.appending(components: "usr", "lib", "swift")
162+
.pathString)
163+
} else {
164+
rsrc = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
165+
}
166+
let platform: String = targetTriple.platformName() ?? ""
167+
let architecture: String = majorArchitectureName(for: targetTriple)
168+
commandLine.appendPath(rsrc.appending(components: platform, architecture, "swiftrt.o"))
158169
}
159170

160171
// If we are linking statically, we need to add all
@@ -194,7 +205,25 @@ extension GenericUnixToolchain {
194205
commandLine.appendPath(try VirtualPath(path: opt.argument.asSingle))
195206
}
196207

197-
if let path = targetInfo.sdkPath?.path {
208+
if targetTriple.environment == .android {
209+
if let ndk = env["ANDROID_NDK_ROOT"] {
210+
var sysroot: AbsolutePath =
211+
try AbsolutePath(validating: ndk)
212+
.appending(components: "toolchains", "llvm", "prebuilt")
213+
#if arch(x86_64)
214+
#if os(Windows)
215+
.appending(component: "windows-x86_64")
216+
#elseif os(Linux)
217+
.appending(component: "linux-x86_64")
218+
#else
219+
.appending(component: "darwin-x86_64")
220+
#endif
221+
#endif
222+
.appending(component: "sysroot")
223+
commandLine.appendFlag("--sysroot")
224+
commandLine.appendPath(sysroot)
225+
}
226+
} else if let path = targetInfo.sdkPath?.path {
198227
commandLine.appendFlag("--sysroot")
199228
commandLine.appendPath(VirtualPath.lookup(path))
200229
}

Sources/SwiftOptions/Options.swift

+2
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ extension Option {
788788
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")
789789
public static let switchCheckingInvocationThresholdEQ: Option = Option("-switch-checking-invocation-threshold=", .joined, attributes: [.helpHidden, .frontend, .noDriver])
790790
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")
791+
public static let sysroot: Option = Option("-sysroot", .separate, attributes: [.frontend, .argumentIsPath], metaVar: "<sysroot>", helpText: "Native Platform sysroot")
791792
public static let S: Option = Option("-S", .flag, alias: Option.emitAssembly, attributes: [.frontend, .noInteractive], group: .modes)
792793
public static let tabWidth: Option = Option("-tab-width", .separate, attributes: [.noInteractive, .noBatch, .indent], metaVar: "<n>", helpText: "Width of tab character.", group: .codeFormatting)
793794
public static let targetCpu: Option = Option("-target-cpu", .separate, attributes: [.frontend, .moduleInterface], helpText: "Generate code for a particular CPU variant")
@@ -1651,6 +1652,7 @@ extension Option {
16511652
Option.swiftVersion,
16521653
Option.switchCheckingInvocationThresholdEQ,
16531654
Option.symbolGraphMinimumAccessLevel,
1655+
Option.sysroot,
16541656
Option.S,
16551657
Option.tabWidth,
16561658
Option.targetCpu,

0 commit comments

Comments
 (0)