From 64cc0be7399e0700d53bd658661252d9e70ea243 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 1 May 2024 12:55:09 -0700 Subject: [PATCH] Prefer toolchain's plugins to SDK plugins if the toolchain has stdlib For example, when using a OSS toolchain, which contains the stdlib in the resource directory, we should use toolchain's SwiftMacros plugin instead of the platform's one. --- .../SwiftDriver/Jobs/FrontendJobHelpers.swift | 39 ++++++++++++++----- Tests/SwiftDriverTests/SwiftDriverTests.swift | 10 ++++- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift b/Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift index 89dedeb32..338f78172 100644 --- a/Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift +++ b/Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift @@ -473,21 +473,24 @@ extension Driver { commandLine.appendFlag($0) } + let toolchainStdlibPath = VirtualPath.lookup(frontendTargetInfo.runtimeResourcePath.path) + .appending(components: frontendTargetInfo.target.triple.platformName() ?? "", "Swift.swiftmodule") + let hasToolchainStdlib = try fileSystem.exists(toolchainStdlibPath) + + // If the resource directory has the standard library, prefer the toolchain's plugins + // to the platform SDK plugins. + if hasToolchainStdlib { + try addPluginPathArguments(commandLine: &commandLine) + } + try toolchain.addPlatformSpecificCommonFrontendOptions(commandLine: &commandLine, inputs: &inputs, frontendTargetInfo: frontendTargetInfo, driver: &self) - // Platform-agnostic options that need to happen after platform-specific ones. - if isFrontendArgSupported(.pluginPath) { - // Default paths for compiler plugins found within the toolchain - // (loaded as shared libraries). - let pluginPathRoot = VirtualPath.absolute(try toolchain.executableDir.parentDirectory) - commandLine.appendFlag(.pluginPath) - commandLine.appendPath(pluginPathRoot.pluginPath) - - commandLine.appendFlag(.pluginPath) - commandLine.appendPath(pluginPathRoot.localPluginPath) + // Otherwise, prefer the platform's plugins. + if !hasToolchainStdlib { + try addPluginPathArguments(commandLine: &commandLine) } } @@ -774,6 +777,22 @@ extension Driver { try explicitDependencyBuildPlanner?.resolveBridgingHeaderDependencies(inputs: &inputs, commandLine: &commandLine) } + mutating func addPluginPathArguments(commandLine: inout [Job.ArgTemplate]) throws { + guard isFrontendArgSupported(.pluginPath) else { + return + } + + // Default paths for compiler plugins found within the toolchain + // (loaded as shared libraries). + let pluginPathRoot = VirtualPath.absolute(try toolchain.executableDir.parentDirectory) + commandLine.appendFlag(.pluginPath) + commandLine.appendPath(pluginPathRoot.pluginPath) + + commandLine.appendFlag(.pluginPath) + commandLine.appendPath(pluginPathRoot.localPluginPath) + } + + /// If explicit dependency planner supports creating bridging header pch command. public func supportsBridgingHeaderPCHCommand() throws -> Bool { return try explicitDependencyBuildPlanner?.supportsBridgingHeaderPCHCommand() ?? false diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index f8be84497..f3c09affb 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -7395,7 +7395,15 @@ final class SwiftDriverTests: XCTestCase { let toolchainPluginPathIndex = job.commandLine.firstIndex(of: .path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins")))) XCTAssertNotNil(toolchainPluginPathIndex) - XCTAssertLessThan(platformLocalPluginPathIndex!, toolchainPluginPathIndex!) + + let toolchainStdlibPath = VirtualPath.lookup(driver.frontendTargetInfo.runtimeResourcePath.path) + .appending(components: driver.frontendTargetInfo.target.triple.platformName() ?? "", "Swift.swiftmodule") + let hasToolchainStdlib = try driver.fileSystem.exists(toolchainStdlibPath) + if hasToolchainStdlib { + XCTAssertGreaterThan(platformLocalPluginPathIndex!, toolchainPluginPathIndex!) + } else { + XCTAssertLessThan(platformLocalPluginPathIndex!, toolchainPluginPathIndex!) + } #endif XCTAssertTrue(job.commandLine.contains(.flag("-plugin-path")))