BuildToolPlugin 'Multiple commands produce ...' error when embedding wachOS app in iOS app target

I'm an author of a tool called xcstrings-tool that offers a BuildToolPlugin to generate Swift source code for accessing localized strings that are declared in an Xcode Strings Catalog.

While BuildTool Plugins have some rough edges, things are mostly great however a user of my tool reported a tricky issue recently:

When using my Build Tool Plugin as a dependency on a Swift Package Target that in turn is a dependency of both the iOS app target and the embedded watchOS app target, the graph fails to build with an error “Multiple Commands produce '...'”.

The file that the error references is the file that my plugin writes into the pluginWorkDirectory.

I traced the issue back, and it seems that because the iOS app target embeds the watchOS app target via the “Embed Watch Contents” build phase, the SPM target must be compiled twice. Once for iOS and again for watchOS.

When doing this, the build tool plugin is invoked twice for the SPM target within the same build, which is what causes the original error.

The problem is however that it's necessary for the build to happen twice, and what I really need is to output the generated source into two different locations but my BuildToolPlugin doesn't seem to have enough power to do that.

The PluginContext/Target doesn't provide enough information for me to make my own unique output subdirectories, so it seems that really I probably want SPM to return pluginWorkDirectory as something more unique.

I raised FB13750966 because technically this is an Xcode issue since I can't reproduce the same scenario using swift build, but really I think that this is still partially an SPM specific issue.

I'm wondering if anybody here has any creative workarounds that I might have missed. The full feedback as well as a reproducible sample can be found in the GitHub issue linked above. Thanks!

I've been having the same issue with a company project using SwiftPM build tools. Same package and iOS/watchOS app setup, also for localization. Can't reproduce with swift build but that's because swift build doesn't know how to build the app's Xcode project.

Also for a time had trouble with generated .lproj folders from the app target weren't top-level and so weren't merged into the .main bundle. I believe this was fixed but I don't quite remember since we're using another solution for now.

1 Like