@@ -402,40 +402,82 @@ public final class InitPackage {
402402 if packageType == . buildToolPlugin {
403403 content += """
404404 struct \( typeName) : BuildToolPlugin {
405+ /// Entry point for creating build commands for targets in Swift packages.
405406 func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
406- // The plugin can choose what parts of the package to process .
407+ // This plugin only runs for package targets that can have source files .
407408 guard let sourceFiles = target.sourceModule?.sourceFiles else { return [] }
408409
409410 // Find the code generator tool to run (replace this with the actual one).
410411 let generatorTool = try context.tool(named: " my-code-generator " )
411412
412413 // Construct a build command for each source file with a particular suffix.
413- return sourceFiles.map( \\ .path).compactMap { inputPath in
414- guard inputPath.extension == " my-input-suffix " else { return .none }
415- let inputName = inputPath.lastComponent
416- let outputName = inputPath.stem + " .swift "
417- let outputPath = context.pluginWorkDirectory.appending(outputName)
418- return .buildCommand(
419- displayName: " Generating \\ (outputName) from \\ (inputName) " ,
420- executable: generatorTool.path,
421- arguments: [ " \\ (inputPath) " , " -o " , " \\ (outputPath) " ],
422- inputFiles: [inputPath],
423- outputFiles: [outputPath]
424- )
414+ return sourceFiles.map( \\ .path).compactMap {
415+ createBuildCommand(for: $0, in: context.pluginWorkDirectory, with: generatorTool.path)
425416 }
426417 }
427418 }
428419
420+ #if canImport(XcodeProjectPlugin)
421+ import XcodeProjectPlugin
422+
423+ extension \( typeName) : XcodeBuildToolPlugin {
424+ // Entry point for creating build commands for targets in Xcode projects.
425+ func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) async throws -> [Command] {
426+ // Find the code generator tool to run (replace this with the actual one).
427+ let generatorTool = try context.tool(named: " my-code-generator " )
428+
429+ // Construct a build command for each source file with a particular suffix.
430+ return target.inputFiles.map( \\ .path).compactMap {
431+ createBuildCommand(for: $0, in: context.pluginWorkDirectory, with: generatorTool.path)
432+ }
433+ }
434+ }
435+
436+ #endif
437+
438+ extension \( typeName) {
439+ /// Shared function that returns a configured build command if the input files is one that should be processed.
440+ func createBuildCommand(for inputPath: Path, in outputDirectoryPath: Path, with generatorToolPath: Path) -> Command? {
441+ // Skip any file that doesn't have the extension we're looking for (replace this with the actual one).
442+ guard inputPath.extension == " my-input-suffix " else { return .none }
443+
444+ // Return a command that will run during the build to generate the output file.
445+ let inputName = inputPath.lastComponent
446+ let outputName = inputPath.stem + " .swift "
447+ let outputPath = outputDirectoryPath.appending(outputName)
448+ return .buildCommand(
449+ displayName: " Generating \\ (outputName) from \\ (inputName) " ,
450+ executable: generatorToolPath,
451+ arguments: [ " \\ (inputPath) " , " -o " , " \\ (outputPath) " ],
452+ inputFiles: [inputPath],
453+ outputFiles: [outputPath]
454+ )
455+ }
456+ }
457+
429458 """
430459 }
431460 else {
432461 content += """
433462 struct \( typeName) : CommandPlugin {
463+ // Entry point for command plugins applied to Swift Packages.
434464 func performCommand(context: PluginContext, arguments: [String]) async throws {
435465 print( " Hello, World! " )
436466 }
437467 }
438468
469+ #if canImport(XcodeProjectPlugin)
470+ import XcodeProjectPlugin
471+
472+ extension MyCommandPlugin: CommandPlugin {
473+ // Entry point for command plugins applied to Xcode projects.
474+ func performCommand(context: XcodePluginContext, arguments: [String]) async throws {
475+ print( " Hello, World! " )
476+ }
477+ }
478+
479+ #endif
480+
439481 """
440482 }
441483
0 commit comments