diff --git a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift index e17d8a88a..d364a1451 100644 --- a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift @@ -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.flatMap({ VirtualPath.lookup($0.path) }) { + rsrc = sdk.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 @@ -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)) } diff --git a/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift b/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift index 7abe9d771..1b2d96808 100644 --- a/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift @@ -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) + } + } + } } diff --git a/Sources/SwiftOptions/Options.swift b/Sources/SwiftOptions/Options.swift index 3365d6713..770fafd96 100644 --- a/Sources/SwiftOptions/Options.swift +++ b/Sources/SwiftOptions/Options.swift @@ -788,6 +788,7 @@ extension Option { public static let swiftVersion: Option = Option("-swift-version", .separate, attributes: [.frontend, .moduleInterface], metaVar: "", helpText: "Interpret input according to a specific Swift language version number") public static let switchCheckingInvocationThresholdEQ: Option = Option("-switch-checking-invocation-threshold=", .joined, attributes: [.helpHidden, .frontend, .noDriver]) public static let symbolGraphMinimumAccessLevel: Option = Option("-symbol-graph-minimum-access-level", .separate, attributes: [.helpHidden, .frontend, .noInteractive, .supplementaryOutput], metaVar: "", helpText: "Include symbols with this access level or more when emitting a symbol graph") + public static let sysroot: Option = Option("-sysroot", .separate, attributes: [.frontend, .argumentIsPath], metaVar: "", helpText: "Native Platform sysroot") public static let S: Option = Option("-S", .flag, alias: Option.emitAssembly, attributes: [.frontend, .noInteractive], group: .modes) public static let tabWidth: Option = Option("-tab-width", .separate, attributes: [.noInteractive, .noBatch, .indent], metaVar: "", helpText: "Width of tab character.", group: .codeFormatting) 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 { Option.swiftVersion, Option.switchCheckingInvocationThresholdEQ, Option.symbolGraphMinimumAccessLevel, + Option.sysroot, Option.S, Option.tabWidth, Option.targetCpu,