From fc8f10ecd903ca3433c570fc025bdf0221a8144b Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 8 May 2025 17:42:58 -0700 Subject: [PATCH] Set the working directory of build tool plugin commands deterministically This resolves an issue where outputs of build tool plugins could be emitted to a random output directory based on whatever the working directory of the calling process happened to be at the time the build tool plugin was executed. Closes #7930 --- Sources/PackagePlugin/Plugin.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Sources/PackagePlugin/Plugin.swift b/Sources/PackagePlugin/Plugin.swift index 5589c23462e..6ee3ec5c23f 100644 --- a/Sources/PackagePlugin/Plugin.swift +++ b/Sources/PackagePlugin/Plugin.swift @@ -149,10 +149,11 @@ extension Plugin { // package is the one we'll set the context's `package` property to. let context: PluginContext let target: Target + let pluginWorkDirectory: URL do { var deserializer = PluginContextDeserializer(wireInput) let package = try deserializer.package(for: rootPackageId) - let pluginWorkDirectory = try deserializer.url(for: wireInput.pluginWorkDirId) + pluginWorkDirectory = try deserializer.url(for: wireInput.pluginWorkDirId) let toolSearchDirectories = try wireInput.toolSearchDirIds.map { try deserializer.url(for: $0) } @@ -208,7 +209,8 @@ extension Plugin { displayName: displayName, executable: executable, arguments: arguments, - environment: environment + environment: environment, + workingDirectory: pluginWorkDirectory ) let message = PluginToHostMessage.defineBuildCommand( configuration: command, @@ -222,7 +224,8 @@ extension Plugin { displayName: displayName, executable: executable, arguments: arguments, - environment: environment + environment: environment, + workingDirectory: pluginWorkDirectory ) let message = PluginToHostMessage.definePrebuildCommand( configuration: command, @@ -248,6 +251,7 @@ extension Plugin { // Deserialize the context from the wire input structures, and create a record for us to pass to the XcodeProjectPlugin library. let record: XcodeProjectPluginInvocationRecord + let pluginWorkDirectory: URL do { var deserializer = PluginContextDeserializer(wireInput) let xcodeProject = try deserializer.xcodeProject(for: rootProjectId) @@ -256,7 +260,7 @@ extension Plugin { pluginGeneratedSources: try generatedSources.map { try deserializer.url(for: $0) }, pluginGeneratedResources: try generatedResources.map { try deserializer.url(for: $0) } ) - let pluginWorkDirectory = try deserializer.url(for: wireInput.pluginWorkDirId) + pluginWorkDirectory = try deserializer.url(for: wireInput.pluginWorkDirId) let toolSearchDirectories = try wireInput.toolSearchDirIds.map { try deserializer.url(for: $0) } @@ -288,7 +292,7 @@ extension Plugin { executable: exec, arguments: args, environment: env, - workingDirectory: nil) + workingDirectory: pluginWorkDirectory) let message = PluginToHostMessage.defineBuildCommand( configuration: command, inputFiles: inputs, @@ -301,7 +305,7 @@ extension Plugin { executable: exec, arguments: args, environment: env, - workingDirectory: nil) + workingDirectory: pluginWorkDirectory) let message = PluginToHostMessage.definePrebuildCommand( configuration: command, outputFilesDirectory: outdir)