Skip to content

updates build-tool documentation #8829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,37 @@ struct MyPlugin: BuildToolPlugin {

func createBuildCommands(context: PluginContext,
target: Target) throws -> [Command] {
guard let target = target.sourceModule else { return [] }
let inputFiles = target.sourceFiles.filter(
{ $0.path.extension == "dat" }
)
return try inputFiles.map {
let inputFile = $0
let inputPath = inputFile.path
let outputName = inputPath.stem + ".swift"
let outputPath = context.pluginWorkDirectory.appending(outputName)
return .buildCommand(
displayName: "Generating \(outputName) from \(inputPath.lastComponent)",
executable: try context.tool(named: "SomeTool").path,
arguments: [ "--verbose", "\(inputPath)", "\(outputPath)" ],
inputFiles: [ inputPath, ],
outputFiles: [ outputPath ]
)
// This plugin only runs for package targets that can have source files.
guard let sourceFiles = target.sourceModule?.sourceFiles else { return [] }

// Find the code generator tool to run (replace this with the actual one).
let generatorTool = try context.tool(named: "my-code-generator")

// Construct a build command for each source file with a particular suffix.
return sourceFiles.map(\.url).compactMap {
createBuildCommand(for: $0, in: context.pluginWorkDirectoryURL, with: generatorTool.url)
}
}

func createBuildCommand(for inputPath: URL,
in outputDirectoryPath: URL,
with generatorToolPath: URL) -> Command? {
// Skip any file that doesn't have the extension we're looking for
// (replace this with the actual one).
guard inputPath.pathExtension == "my-input-suffix" else { return .none }

// Return a command that will run during the build to generate the output file.
let inputName = inputPath.lastPathComponent
let outputName = inputPath.deletingPathExtension().lastPathComponent + ".swift"
let outputPath = outputDirectoryPath.appendingPathComponent(outputName)
return .buildCommand(
displayName: "Generating \(outputName) from \(inputName)",
executable: generatorToolPath,
arguments: ["\(inputPath)", "-o", "\(outputPath)"],
inputFiles: [inputPath],
outputFiles: [outputPath]
)
}
}
```

Expand All @@ -163,9 +176,11 @@ struct MyBuildToolPlugin: BuildToolPlugin {
// This example configures `sometool` to write to a
// "GeneratedFiles" directory in the plugin work directory
// (which is unique for each plugin and target).
let outputDir = context.pluginWorkDirectory.appending("GeneratedFiles")
try FileManager.default.createDirectory(atPath: outputDir.string,
withIntermediateDirectories: true)
let outputDir = context.pluginWorkDirectoryURL
.appendingPathComponent("GeneratedFiles")
try FileManager.default.createDirectory(
at: outputDir,
withIntermediateDirectories: true)

// Return a command to run `sometool` as a prebuild command.
// It runs before every build and generates source files
Expand Down Expand Up @@ -217,26 +232,24 @@ In order to write a plugin that works with packages in every environment, and th
For example:

```swift
import PackagePlugin

@main
struct MyCommandPlugin: CommandPlugin {
/// This entry point is called when operating on a Swift package.
func performCommand(context: PluginContext,
arguments: [String]) throws {
debugPrint(context)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension MyCommandPlugin: XcodeCommandPlugin {
/// This entry point is called when operating on an Xcode project.
func performCommand(context: XcodePluginContext,
arguments: [String]) throws {
debugPrint(context)

// Entry point for creating build commands for targets in Xcode projects.
func createBuildCommands(context: XcodePluginContext,
target: XcodeTarget) throws -> [Command] {
// Find the code generator tool to run (replace this with the actual one).
let generatorTool = try context.tool(named: "my-code-generator")

// Construct a build command for each source file with a particular suffix.
return target.inputFiles.map(\.url).compactMap {
createBuildCommand(for: $0,
in: context.pluginWorkDirectoryURL,
with: generatorTool.url)
}
}
}
#endif
```
Expand Down