|
5 | 5 | import Foundation |
6 | 6 | import PackagePlugin |
7 | 7 |
|
8 | | -@main |
| 8 | +@main @available(macOS 13.0, *) |
9 | 9 | struct KnitBuildPlugin: BuildToolPlugin { |
10 | 10 |
|
11 | 11 | func createBuildCommands( |
12 | 12 | context: PluginContext, |
13 | 13 | target: any Target |
14 | 14 | ) async throws -> [Command] { |
15 | | - // This method is only invoked when the plugin is consumed by an SPM-only project |
16 | | - fatalError("Unexpected project type. Please add plugin to an Xcode project.") |
| 15 | + let jsonFile = context.package.directory.appending(subpath: "knitconfig.json") |
| 16 | + |
| 17 | + return [ |
| 18 | + try KnitBuildPlugin.createCommand( |
| 19 | + type: .source, |
| 20 | + toolPath: try context.tool(named: "knit-cli").path, |
| 21 | + configFilePath: jsonFile, |
| 22 | + workingDirectory: context.pluginWorkDirectory |
| 23 | + ) |
| 24 | + ] |
| 25 | + |
17 | 26 | } |
18 | 27 |
|
19 | 28 | } |
20 | 29 |
|
21 | 30 | #if canImport(XcodeProjectPlugin) |
22 | 31 | import XcodeProjectPlugin |
23 | 32 |
|
| 33 | +@available(macOS 13.0, *) |
24 | 34 | extension KnitBuildPlugin: XcodeBuildToolPlugin { |
25 | 35 |
|
26 | 36 | func createBuildCommands( |
@@ -50,29 +60,60 @@ extension XcodePluginContext { |
50 | 60 | from configFilePath: Path, |
51 | 61 | target: XcodeTarget |
52 | 62 | ) throws -> Command { |
53 | | - let configFileData = try Data(contentsOf: URL(filePath: configFilePath.string)) |
54 | | - |
55 | | - let config = try JSONDecoder().decode(KnitPluginConfig.self, from: configFileData) |
56 | | - |
57 | | - let typeSafetyOutputPath: Path? |
58 | | - let unitTestOutputPath: Path? |
| 63 | + let command: CommandType |
59 | 64 | switch target.product?.kind { |
60 | 65 | case .application: |
61 | | - typeSafetyOutputPath = self.pluginWorkDirectory.appending("KnitDITypeSafety.swift") |
62 | | - unitTestOutputPath = nil |
| 66 | + command = .source |
63 | 67 | case .other("com.apple.product-type.bundle.unit-test"): |
64 | | - typeSafetyOutputPath = nil |
65 | | - unitTestOutputPath = self.pluginWorkDirectory.appending(subpath: "KnitDIRegistrationTests.swift") |
66 | | - |
| 68 | + command = .tests |
67 | 69 | default: |
68 | | - typeSafetyOutputPath = nil |
69 | | - unitTestOutputPath = nil |
| 70 | + command = .unknown |
70 | 71 | } |
| 72 | + |
| 73 | + return try KnitBuildPlugin.createCommand( |
| 74 | + type: command, |
| 75 | + toolPath: try self.tool(named: "knit-cli").path, |
| 76 | + configFilePath: configFilePath, |
| 77 | + workingDirectory: self.pluginWorkDirectory |
| 78 | + ) |
| 79 | + } |
| 80 | + |
| 81 | +} |
71 | 82 |
|
| 83 | +#endif |
| 84 | + |
| 85 | +fileprivate enum CommandType { |
| 86 | + case source, tests, unknown |
| 87 | +} |
| 88 | + |
| 89 | +@available(macOS 13.0, *) |
| 90 | +extension KnitBuildPlugin { |
| 91 | + fileprivate static func createCommand( |
| 92 | + type: CommandType, |
| 93 | + toolPath: Path, |
| 94 | + configFilePath: Path, |
| 95 | + workingDirectory: Path |
| 96 | + ) throws -> Command { |
| 97 | + let configFileData = try Data(contentsOf: URL(filePath: configFilePath.string)) |
| 98 | + let config = try JSONDecoder().decode(KnitPluginConfig.self, from: configFileData) |
72 | 99 | let assemblyInputPaths = config.makeInputPaths( |
73 | 100 | configFilePath: configFilePath |
74 | 101 | ) |
75 | | - |
| 102 | + |
| 103 | + let typeSafetyOutputPath: Path? |
| 104 | + let unitTestOutputPath: Path? |
| 105 | + switch type { |
| 106 | + case .source: |
| 107 | + typeSafetyOutputPath = workingDirectory.appending("KnitDITypeSafety.swift") |
| 108 | + unitTestOutputPath = nil |
| 109 | + case .tests: |
| 110 | + typeSafetyOutputPath = nil |
| 111 | + unitTestOutputPath = workingDirectory.appending(subpath: "KnitDIRegistrationTests.swift") |
| 112 | + case .unknown: |
| 113 | + unitTestOutputPath = nil |
| 114 | + typeSafetyOutputPath = nil |
| 115 | + } |
| 116 | + |
76 | 117 | let assemblyInputArgs: [String] = assemblyInputPaths.flatMap { path in |
77 | 118 | [ |
78 | 119 | "--assembly-input-path", |
@@ -101,18 +142,15 @@ extension XcodePluginContext { |
101 | 142 | unitTestArgs |
102 | 143 |
|
103 | 144 | return .buildCommand( |
104 | | - displayName: "Knit Plugin: Generate Knit files based on config \(configFilePath.description)", |
105 | | - executable: try self.tool(named: "knit-cli").path, |
| 145 | + displayName: "Knit Plugin: Generate Knit files based on config \(configFilePath.description). Output folder: \(workingDirectory.description)", |
| 146 | + executable: toolPath, |
106 | 147 | arguments: arguments, |
107 | 148 | inputFiles: assemblyInputPaths, |
108 | 149 | outputFiles: [typeSafetyOutputPath, unitTestOutputPath].compactMap { $0 } |
109 | 150 | ) |
110 | 151 | } |
111 | | - |
112 | 152 | } |
113 | 153 |
|
114 | | -#endif |
115 | | - |
116 | 154 | /// Corresponds to the `knitconfig.json` file. |
117 | 155 | /// That JSON data will be decoded into a `KnitPluginConfig` instance. |
118 | 156 | struct KnitPluginConfig: Decodable { |
|
0 commit comments