Xcode integration of Swift Package Plugins in Xcode 14
Xcode Extensions to the PackagePlugin API
WWDC 2022 video "Meet Swift Package plugins" explains how to perform actions on Swift packages and Xcode projects with Swift package plugins.
Swift Package plugins can be divided into two types:
- Command plugin
- Build tool plugin
Both plugin types were introduced in Swift 5.6 and work in Xcode 13.3 when used on Swift packages. So what's new in Xcode 14 (Swift 5.7) ?
Command plugins can be triggered within Xcode
No adoption from plugin authors is required :)
You can trigger the command plugin from the contextual menu
You can also trigger the command plugin from the "File Menu"
Both options will start the following dialog that lets you choose on which target(s) the command plugin shall be executed
Command plugins can be executed on Xcode projects
Adoption from plugin authors is required or otherwise you will receive the following error when triggering a command plugin on an Xcode project: Malformed input JSON: Couldn't find the XcodeProjectPlugin entry point
New in Xcode 14 is a library module called XcodeProjectPlugin
which extends SPM's PackagePlugin
API.
With the XcodeProjectPlugin
API, a Swift package plugin can get a simplified description of the Xcode projectโs structure (XcodePluginContext
). The XcodePluginContext
input structure is similar to the regular PluginContext
structure, except that it provides access to an Xcode project that uses Xcode naming and semantics for the project model (which is somewhat different from that of SwiftPM).
Structure of a command plugin with conditional support for Xcode projects when running in Xcode
import PackagePlugin
@main
struct MyPlugin: CommandPlugin {
/// This entry point is called when operating on a Swift package.
func performCommand(context: PluginContext, arguments: [String]) throws {
print("Command plugin execution for Swift package \(context.package.displayName)")
}
}
#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin
extension MyPlugin: XcodeCommandPlugin {
/// ๐ This entry point is called when operating on an Xcode project.
func performCommand(context: XcodePluginContext, arguments: [String]) throws {
print("Command plugin execution for Xcode project \(context.xcodeProject.displayName)")
}
}
#endif
Build plugins can be executed on Xcode projects
A build tool plugin is able to conform to the new XcodeBuildToolPlugin
type. This type was introduced in XcodeProjectPlugin
with Xcode 14 Beta 3.
Structure of a build tool plugin with conditional support for Xcode projects when running in Xcode
import PackagePlugin
@main
struct MyPlugin: BuildToolPlugin {
/// This entry point is called when operating on a Swift package.
func createBuildCommands(context: PluginContext, target: Target) throws -> [Command]
return []
}
}
#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin
extension MyPlugin: XcodeBuildToolPlugin {
/// ๐ This entry point is called when operating on an Xcode project.
func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) throws -> [Command]
return []
}
}
#endif
The Xcode target editor lets an App target be configured to use a build tool plugin provided by any of the projectโs package dependencies.