diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift index 42c3617e4..34ccbaffc 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift @@ -421,17 +421,7 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT allLinkLibraries.append(linkLibrary) } } - - for linkLibrary in allLinkLibraries { - if !linkLibrary.isFramework { - commandLine.appendFlag("-l\(linkLibrary.linkName)") - } else { - commandLine.appendFlag(.Xlinker) - commandLine.appendFlag("-framework") - commandLine.appendFlag(.Xlinker) - commandLine.appendFlag(linkLibrary.linkName) - } - } + toolchain.addAutoLinkFlags(for: allLinkLibraries, to: &commandLine) } /// Resolve all module dependencies of the main module and add them to the lists of diff --git a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift index 2382c5798..cfb4c9f05 100644 --- a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift @@ -114,6 +114,20 @@ public final class DarwinToolchain: Toolchain { } } + public func addAutoLinkFlags(for linkLibraries: [LinkLibraryInfo], to commandLine: inout [Job.ArgTemplate]) { + for linkLibrary in linkLibraries { + if !linkLibrary.isFramework { + commandLine.appendFlag(.Xlinker) + commandLine.appendFlag("-possible-l\(linkLibrary.linkName)") + } else { + commandLine.appendFlag(.Xlinker) + commandLine.appendFlag("-possible_framework") + commandLine.appendFlag(.Xlinker) + commandLine.appendFlag(linkLibrary.linkName) + } + } + } + public func defaultSDKPath(_ target: Triple?) throws -> AbsolutePath? { let hostIsMacOS: Bool #if os(macOS) diff --git a/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift b/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift index 18286a1bf..25adc84c7 100644 --- a/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift @@ -78,6 +78,12 @@ public final class GenericUnixToolchain: Toolchain { } } + public func addAutoLinkFlags(for linkLibraries: [LinkLibraryInfo], to commandLine: inout [Job.ArgTemplate]) { + for linkLibrary in linkLibraries { + commandLine.appendFlag("-l\(linkLibrary.linkName)") + } + } + /// Retrieve the absolute path for a given tool. public func getToolPath(_ tool: Tool) throws -> AbsolutePath { // Check the cache diff --git a/Sources/SwiftDriver/Toolchains/Toolchain.swift b/Sources/SwiftDriver/Toolchains/Toolchain.swift index 5b6210b0d..c696ca0be 100644 --- a/Sources/SwiftDriver/Toolchains/Toolchain.swift +++ b/Sources/SwiftDriver/Toolchains/Toolchain.swift @@ -115,6 +115,9 @@ public protocol Toolchain { /// Constructs a proper output file name for a linker product. func makeLinkerOutputFilename(moduleName: String, type: LinkOutputType) -> String + /// Adds linker flags corresponding to the specified set of link libraries + func addAutoLinkFlags(for linkLibraries: [LinkLibraryInfo], to commandLine: inout [Job.ArgTemplate]) + /// Perform platform-specific argument validation. func validateArgs(_ parsedOptions: inout ParsedOptions, targetTriple: Triple, diff --git a/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift b/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift index 25cdb90c0..4e1fa1cd0 100644 --- a/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift @@ -79,6 +79,12 @@ public final class WebAssemblyToolchain: Toolchain { } } + public func addAutoLinkFlags(for linkLibraries: [LinkLibraryInfo], to commandLine: inout [Job.ArgTemplate]) { + for linkLibrary in linkLibraries { + commandLine.appendFlag("-l\(linkLibrary.linkName)") + } + } + /// Retrieve the absolute path for a given tool. public func getToolPath(_ tool: Tool) throws -> AbsolutePath { // Check the cache diff --git a/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift b/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift index 43cb1aafc..de4d92572 100644 --- a/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift @@ -113,6 +113,12 @@ extension WindowsToolchain.ToolchainValidationError { } } + public func addAutoLinkFlags(for linkLibraries: [LinkLibraryInfo], to commandLine: inout [Job.ArgTemplate]) { + for linkLibrary in linkLibraries { + commandLine.appendFlag("-l\(linkLibrary.linkName)") + } + } + public func defaultSDKPath(_ target: Triple?) throws -> AbsolutePath? { // TODO(compnerd): replicate the SPM processing of the SDKInfo.plist if let SDKROOT = env["SDKROOT"] { diff --git a/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift b/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift index 4d420fc59..966c9d8c2 100644 --- a/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift +++ b/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift @@ -500,6 +500,60 @@ final class ExplicitModuleBuildTests: XCTestCase { } } + func testExplicitLinkFlags() throws { + try withTemporaryDirectory { path in + let (_, _, toolchain, _) = try getDriverArtifactsForScanning() + + let main = path.appending(component: "testExplicitLinkLibraries.swift") + try localFileSystem.writeFileContents(main, bytes: + """ + import C;import E;import G; + """ + ) + + let cHeadersPath: AbsolutePath = + try testInputsPath.appending(component: "ExplicitModuleBuilds") + .appending(component: "CHeaders") + let bridgingHeaderpath: AbsolutePath = + cHeadersPath.appending(component: "Bridging.h") + let swiftModuleInterfacesPath: AbsolutePath = + try testInputsPath.appending(component: "ExplicitModuleBuilds") + .appending(component: "Swift") + let sdkArgumentsForTesting = (try? Driver.sdkArgumentsForTesting()) ?? [] + + // Verify the dependency scanner supports link library reporting + let dependencyOracle = InterModuleDependencyOracle() + let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib()) + try dependencyOracle.verifyOrCreateScannerInstance(swiftScanLibPath: scanLibPath) + guard try dependencyOracle.supportsLinkLibraries() else { + throw XCTSkip("libSwiftScan does not support link library reporting.") + } + + let args = ["swiftc", + "-I", cHeadersPath.nativePathString(escaped: true), + "-I", swiftModuleInterfacesPath.nativePathString(escaped: true), + "-explicit-module-build", "-explicit-auto-linking", + "-import-objc-header", bridgingHeaderpath.nativePathString(escaped: true), + main.nativePathString(escaped: true)] + sdkArgumentsForTesting + var driver = try Driver(args: args) + let jobs = try driver.planBuild() + + let linkJob = try jobs.findJob(.link) + if driver.targetTriple.isDarwin { + XCTAssertTrue(linkJob.commandLine.contains("-possible-lswiftCore")) + XCTAssertTrue(linkJob.commandLine.contains("-possible-lswift_StringProcessing")) + XCTAssertTrue(linkJob.commandLine.contains("-possible-lobjc")) + XCTAssertTrue(linkJob.commandLine.contains("-possible-lswift_Concurrency")) + XCTAssertTrue(linkJob.commandLine.contains("-possible-lswiftSwiftOnoneSupport")) + } else { + XCTAssertTrue(linkJob.commandLine.contains("-lswiftCore")) + XCTAssertTrue(linkJob.commandLine.contains("-lswift_StringProcessing")) + XCTAssertTrue(linkJob.commandLine.contains("-lswift_Concurrency")) + XCTAssertTrue(linkJob.commandLine.contains("-lswiftSwiftOnoneSupport")) + } + } + } + func testExplicitLinkLibraries() throws { try withTemporaryDirectory { path in let (_, _, toolchain, _) = try getDriverArtifactsForScanning()