# Xcode integration of Swift Package Plugins in Xcode 14

WWDC 2022 video ["Meet Swift Package plugins"](https://developer.apple.com/videos/play/wwdc2022/110359) explains how to perform actions on Swift packages and Xcode projects with Swift package plugins.

Swift Package plugins can be divided into two types:

1. Command plugin
2. 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

![Trigger Plugin from Contextual Menu](https://cdn.hashnode.com/res/hashnode/image/upload/v1654897049964/giZOVIrcN.png align="left")

You can also trigger the command plugin from the "File Menu"

![Trigger Plugin from File Menu](https://cdn.hashnode.com/res/hashnode/image/upload/v1654897058460/QRYrULk7w.png align="left")

Both options will start the following dialog that lets you choose on which target(s) the command plugin shall be executed

![Command Plugin Dialog](https://cdn.hashnode.com/res/hashnode/image/upload/v1654897089067/XL_fI8Lvh.png align="left")

## 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

```swift
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

```swift
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.

![Run Build Tool Plug-ins](https://cdn.hashnode.com/res/hashnode/image/upload/v1657210763691/ruwc-Zwbs.gif align="left")

