diff --git a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift index f9de16dba..79bce9cc2 100644 --- a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift @@ -456,29 +456,53 @@ public final class DarwinToolchain: Toolchain { } if driver.isFrontendArgSupported(.externalPluginPath) { - // Determine the platform path. For simulator platforms, look into the - // corresponding device platform instance. - let origPlatformPath = VirtualPath.lookup(sdkPath) - .parentDirectory - .parentDirectory - .parentDirectory - let platformPath: VirtualPath - if let simulatorRange = origPlatformPath.basename.range(of: "Simulator.platform") { - let devicePlatform = origPlatformPath.basename.replacingCharacters(in: simulatorRange, with: "OS.platform") - platformPath = origPlatformPath.parentDirectory.appending(component: devicePlatform) - } else { - platformPath = origPlatformPath + // If the PLATFORM_DIR environment variable is set, also add plugin + // paths into it. Since this is a user override, it comes beore the + // default platform path that's based on the SDK. + if let platformDir = env["PLATFORM_DIR"], + let platformPath = try? VirtualPath(path: platformDir) { + addPluginPaths( + forPlatform: platformPath, + commandLine: &commandLine + ) } - // Default paths for compiler plugins within the platform (accessed via that - // platform's plugin server). - let platformPathRoot = platformPath.appending(components: "Developer", "usr") - commandLine.appendFlag(.externalPluginPath) - commandLine.appendFlag("\(platformPathRoot.pluginPath.name)#\(platformPathRoot.pluginServerPath.name)") + // Determine the platform path based on the SDK path. + addPluginPaths( + forPlatform: VirtualPath.lookup(sdkPath) + .parentDirectory + .parentDirectory + .parentDirectory, + commandLine: &commandLine + ) + } + } - commandLine.appendFlag(.externalPluginPath) - commandLine.appendFlag("\(platformPathRoot.localPluginPath.name)#\(platformPathRoot.pluginServerPath.name)") + /// Given the platform path (e.g., a path into something like iPhoneOS.platform), + /// add external plugin path arguments for compiler plugins that are distributed + /// within that path. + func addPluginPaths( + forPlatform origPlatformPath: VirtualPath, + commandLine: inout [Job.ArgTemplate] + ) { + // For simulator platforms, look into the corresponding device platform instance, + // because they share compiler plugins. + let platformPath: VirtualPath + if let simulatorRange = origPlatformPath.basename.range(of: "Simulator.platform") { + let devicePlatform = origPlatformPath.basename.replacingCharacters(in: simulatorRange, with: "OS.platform") + platformPath = origPlatformPath.parentDirectory.appending(component: devicePlatform) + } else { + platformPath = origPlatformPath } + + // Default paths for compiler plugins within the platform (accessed via that + // platform's plugin server). + let platformPathRoot = platformPath.appending(components: "Developer", "usr") + commandLine.appendFlag(.externalPluginPath) + commandLine.appendFlag("\(platformPathRoot.pluginPath.name)#\(platformPathRoot.pluginServerPath.name)") + + commandLine.appendFlag(.externalPluginPath) + commandLine.appendFlag("\(platformPathRoot.localPluginPath.name)#\(platformPathRoot.pluginServerPath.name)") } } diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index ac7b95bbe..c1a2c413d 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -7749,7 +7749,12 @@ final class SwiftDriverTests: XCTestCase { func pluginPathTest(platform: String, sdk: String, searchPlatform: String) throws { let sdkRoot = try testInputsPath.appending( components: ["Platform Checks", "\(platform).platform", "Developer", "SDKs", "\(sdk).sdk"]) - var driver = try Driver(args: ["swiftc", "-typecheck", "foo.swift", "-sdk", VirtualPath.absolute(sdkRoot).name, "-plugin-path", "PluginA", "-external-plugin-path", "Plugin~B#Bexe", "-load-plugin-library", "PluginB2", "-plugin-path", "PluginC", "-working-directory", "/tmp"]) + var env = ProcessEnv.vars + env["PLATFORM_DIR"] = "/tmp/PlatformDir/\(platform).platform" + var driver = try Driver( + args: ["swiftc", "-typecheck", "foo.swift", "-sdk", VirtualPath.absolute(sdkRoot).name, "-plugin-path", "PluginA", "-external-plugin-path", "Plugin~B#Bexe", "-load-plugin-library", "PluginB2", "-plugin-path", "PluginC", "-working-directory", "/tmp"], + env: env + ) guard driver.isFrontendArgSupported(.pluginPath) && driver.isFrontendArgSupported(.externalPluginPath) else { return } @@ -7791,6 +7796,18 @@ final class SwiftDriverTests: XCTestCase { XCTAssertNotNil(platformLocalPluginPathIndex) XCTAssertLessThan(platformPluginPathIndex!, platformLocalPluginPathIndex!) + // Plugin paths that come from the PLATFORM_DIR environment variable. + let envOrigPlatformPath = try AbsolutePath(validating: "/tmp/PlatformDir/\(searchPlatform).platform") + let envPlatformPath = envOrigPlatformPath.appending(components: "Developer", "usr") + let envPlatformServerPath = envPlatformPath.appending(components: "bin", "swift-plugin-server").pathString + let envPlatformPluginPath = envPlatformPath.appending(components: "lib", "swift", "host", "plugins") + let envPlatformPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(envPlatformPluginPath)#\(envPlatformServerPath)")) + XCTAssertNotNil(envPlatformPluginPathIndex) + + if let platformPluginPathIndex, let envPlatformPluginPathIndex { + XCTAssertLessThan(envPlatformPluginPathIndex, platformPluginPathIndex) + } + let toolchainPluginPathIndex = job.commandLine.firstIndex(of: .path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins")))) XCTAssertNotNil(toolchainPluginPathIndex)