Skip to content

Commit 2d75055

Browse files
committed
Implement proposed adjustments to SE-0303 to use @main for plugins
This is an implementation of the proposed adjustments to SE-0303 in swiftlang/swift-evolution#1434. This changes the entry point to use `@main` rather than top-level code, and introduces protocols for the entry points corresponding to the various plugin capabilities. It gets rid of the globals in favour of plugin parameters and return values (except for diagnostics, which are still collected using a process-wide list).
1 parent c9a8f60 commit 2d75055

File tree

17 files changed

+394
-294
lines changed

17 files changed

+394
-294
lines changed
Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
11
import PackagePlugin
22

3-
for inputFile in targetBuildContext.inputFiles.filter({ $0.path.extension == "dat" }) {
4-
let inputPath = inputFile.path
5-
let outputName = "Ambiguous_" + inputPath.stem + ".swift"
6-
let outputPath = targetBuildContext.pluginWorkDirectory.appending(outputName)
7-
commandConstructor.addBuildCommand(
8-
displayName:
9-
"This is a constant name",
10-
executable:
11-
try targetBuildContext.tool(named: "MySourceGenBuildTool").path,
12-
arguments: [
13-
"\(inputPath)",
14-
"\(outputPath)"
15-
],
16-
environment: [
17-
"VARIABLE_NAME_PREFIX": "SECOND_PREFIX_"
18-
],
19-
inputFiles: [
20-
inputPath,
21-
],
22-
outputFiles: [
23-
outputPath
24-
]
25-
)
3+
@main struct MyPlugin: BuildToolPlugin {
4+
5+
func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
6+
var commands: [Command] = []
7+
for inputFile in context.inputFiles.filter({ $0.path.extension == "dat" }) {
8+
let inputPath = inputFile.path
9+
let outputName = "Ambiguous_" + inputPath.stem + ".swift"
10+
let outputPath = context.pluginWorkDirectory.appending(outputName)
11+
commands.append(.buildCommand(
12+
displayName:
13+
"This is a constant name",
14+
executable:
15+
try context.tool(named: "MySourceGenBuildTool").path,
16+
arguments: [
17+
"\(inputPath)",
18+
"\(outputPath)"
19+
],
20+
environment: [
21+
"VARIABLE_NAME_PREFIX": "SECOND_PREFIX_"
22+
],
23+
inputFiles: [
24+
inputPath,
25+
],
26+
outputFiles: [
27+
outputPath
28+
]
29+
))
30+
}
31+
return commands
32+
}
2633
}
Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
11
import PackagePlugin
22

3-
print("Hello from the Build Tool Plugin!")
4-
5-
for inputFile in targetBuildContext.inputFiles.filter({ $0.path.extension == "dat" }) {
6-
let inputPath = inputFile.path
7-
let outputName = inputPath.stem + ".swift"
8-
let outputPath = targetBuildContext.pluginWorkDirectory.appending(outputName)
9-
commandConstructor.addBuildCommand(
10-
displayName:
11-
"Generating \(outputName) from \(inputPath.lastComponent)",
12-
executable:
13-
try targetBuildContext.tool(named: "MySourceGenBuildTool").path,
14-
arguments: [
15-
"\(inputPath)",
16-
"\(outputPath)"
17-
],
18-
environment: [
19-
"VARIABLE_NAME_PREFIX": "PREFIX_"
20-
],
21-
inputFiles: [
22-
inputPath,
23-
],
24-
outputFiles: [
25-
outputPath
26-
]
27-
)
3+
@main struct MyPlugin: BuildToolPlugin {
4+
5+
func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
6+
let inputFiles = context.inputFiles.filter({ $0.path.extension == "dat" })
7+
return try inputFiles.map {
8+
let inputFile = $0
9+
let inputPath = inputFile.path
10+
let outputName = inputPath.stem + ".swift"
11+
let outputPath = context.pluginWorkDirectory.appending(outputName)
12+
return .buildCommand(
13+
displayName:
14+
"Generating \(outputName) from \(inputPath.lastComponent)",
15+
executable:
16+
try context.tool(named: "MySourceGenBuildTool").path,
17+
arguments: [
18+
"\(inputPath)",
19+
"\(outputPath)"
20+
],
21+
environment: [
22+
"VARIABLE_NAME_PREFIX": "PREFIX_"
23+
],
24+
inputFiles: [
25+
inputPath,
26+
],
27+
outputFiles: [
28+
outputPath
29+
]
30+
)
31+
}
32+
}
2833
}
Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
11
import PackagePlugin
2-
3-
print("Hello from the Build Tool Plugin!")
42

5-
for inputFile in targetBuildContext.inputFiles.filter({ $0.path.extension == "dat" }) {
6-
let inputPath = inputFile.path
7-
let outputName = inputPath.stem + ".swift"
8-
let outputPath = targetBuildContext.pluginWorkDirectory.appending(outputName)
9-
commandConstructor.addBuildCommand(
10-
displayName:
11-
"Generating \(outputName) from \(inputPath.lastComponent)",
12-
executable:
13-
try targetBuildContext.tool(named: "mytool").path,
14-
arguments: [
15-
"--verbose",
16-
"\(inputPath)",
17-
"\(outputPath)"
18-
],
19-
inputFiles: [
20-
inputPath,
21-
],
22-
outputFiles: [
23-
outputPath
24-
]
25-
)
3+
@main struct MyPlugin: BuildToolPlugin {
4+
5+
func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
6+
print("Hello from the Build Tool Plugin!")
7+
8+
let inputFiles = context.inputFiles.filter({ $0.path.extension == "dat" })
9+
return try inputFiles.map {
10+
let inputFile = $0
11+
let inputPath = inputFile.path
12+
let outputName = inputPath.stem + ".swift"
13+
let outputPath = context.pluginWorkDirectory.appending(outputName)
14+
return .buildCommand(
15+
displayName:
16+
"Generating \(outputName) from \(inputPath.lastComponent)",
17+
executable:
18+
try context.tool(named: "mytool").path,
19+
arguments: [
20+
"--verbose",
21+
"\(inputPath)",
22+
"\(outputPath)"
23+
],
24+
inputFiles: [
25+
inputPath,
26+
],
27+
outputFiles: [
28+
outputPath
29+
]
30+
)
31+
}
32+
}
2633
}
Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
import PackagePlugin
2-
3-
print("Hello from the Build Tool Plugin!")
42

5-
for inputPath in targetBuildContext.inputFiles.map{ $0.path } {
6-
guard inputPath.extension == "dat" else { continue }
7-
let outputName = inputPath.stem + ".swift"
8-
let outputPath = targetBuildContext.pluginWorkDirectory.appending(outputName)
9-
commandConstructor.addBuildCommand(
10-
displayName:
11-
"Generating \(outputName) from \(inputPath.lastComponent)",
12-
executable:
13-
try targetBuildContext.tool(named: "MySourceGenBuildTool").path,
14-
arguments: [
15-
"\(inputPath)",
16-
"\(outputPath)"
17-
],
18-
inputFiles: [
19-
inputPath,
20-
],
21-
outputFiles: [
22-
outputPath
23-
]
24-
)
3+
@main struct MyPlugin: BuildToolPlugin {
4+
5+
func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
6+
print("Hello from the Build Tool Plugin!")
7+
8+
return try context.inputFiles.map{ $0.path }.compactMap {
9+
guard $0.extension == "dat" else { return .none }
10+
let outputName = $0.stem + ".swift"
11+
let outputPath = context.pluginWorkDirectory.appending(outputName)
12+
return .buildCommand(
13+
displayName:
14+
"Generating \(outputName) from \($0.lastComponent)",
15+
executable:
16+
try context.tool(named: "MySourceGenBuildTool").path,
17+
arguments: [
18+
"\($0)",
19+
"\(outputPath)"
20+
],
21+
inputFiles: [
22+
$0,
23+
],
24+
outputFiles: [
25+
outputPath
26+
]
27+
)
28+
}
29+
}
2530
}
Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
import PackagePlugin
2-
3-
print("Hello from the Prebuild Plugin!")
42

5-
let outputPaths: [Path] = targetBuildContext.inputFiles.filter{ $0.path.extension == "dat" }.map { file in
6-
targetBuildContext.pluginWorkDirectory.appending(file.path.stem + ".swift")
7-
}
3+
@main struct MyPlugin: BuildToolPlugin {
4+
5+
func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
6+
print("Hello from the Prebuild Plugin!")
87

9-
if !outputPaths.isEmpty {
10-
commandConstructor.addPrebuildCommand(
11-
displayName:
12-
"Running prebuild command for target \(targetBuildContext.targetName)",
13-
executable:
14-
Path("/usr/bin/touch"),
15-
arguments:
16-
outputPaths.map{ $0.string },
17-
outputFilesDirectory:
18-
targetBuildContext.pluginWorkDirectory
19-
)
8+
let outputPaths: [Path] = context.inputFiles.filter{ $0.path.extension == "dat" }.map { file in
9+
context.pluginWorkDirectory.appending(file.path.stem + ".swift")
10+
}
11+
var commands: [Command] = []
12+
if !outputPaths.isEmpty {
13+
commands.append(.prebuildCommand(
14+
displayName:
15+
"Running prebuild command for target \(context.targetName)",
16+
executable:
17+
Path("/usr/bin/touch"),
18+
arguments:
19+
outputPaths.map{ $0.string },
20+
outputFilesDirectory:
21+
context.pluginWorkDirectory
22+
))
23+
}
24+
return commands
25+
}
2026
}
Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
import PackagePlugin
22
import Foundation
3-
4-
// Check that we can write to the output directory.
5-
let allowedOutputPath = targetBuildContext.pluginWorkDirectory.appending("Foo")
6-
if mkdir(allowedOutputPath.string, 0o777) != 0 {
7-
throw StringError("unexpectedly could not write to '\(allowedOutputPath)': \(String(utf8String: strerror(errno)))")
8-
}
93

10-
// Check that we cannot write to the source directory.
11-
let disallowedOutputPath = targetBuildContext.targetDirectory.appending("Bar")
12-
if mkdir(disallowedOutputPath.string, 0o777) == 0 {
13-
throw StringError("unexpectedly could write to '\(disallowedOutputPath)'")
14-
}
4+
@main struct MyPlugin: BuildToolPlugin {
5+
6+
func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
7+
8+
// Check that we can write to the output directory.
9+
let allowedOutputPath = context.pluginWorkDirectory.appending("Foo")
10+
if mkdir(allowedOutputPath.string, 0o777) != 0 {
11+
throw StringError("unexpectedly could not write to '\(allowedOutputPath)': \(String(utf8String: strerror(errno)))")
12+
}
1513

14+
// Check that we cannot write to the source directory.
15+
let disallowedOutputPath = context.targetDirectory.appending("Bar")
16+
if mkdir(disallowedOutputPath.string, 0o777) == 0 {
17+
throw StringError("unexpectedly could write to '\(disallowedOutputPath)'")
18+
}
19+
20+
return []
21+
}
1622

17-
struct StringError: Error, CustomStringConvertible {
18-
var error: String
19-
init(_ error: String) {
20-
self.error = error
23+
struct StringError: Error, CustomStringConvertible {
24+
var error: String
25+
init(_ error: String) {
26+
self.error = error
27+
}
28+
var description: String { error }
2129
}
22-
var description: String { error }
2330
}

Sources/PackagePlugin/CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
add_library(PackagePlugin
10-
PublicAPI/CommandConstructor.swift
11-
PublicAPI/DiagnosticsEmitter.swift
10+
PublicAPI/Command.swift
11+
PublicAPI/Context.swift
12+
PublicAPI/Diagnostics.swift
1213
PublicAPI/FileList.swift
13-
PublicAPI/Globals.swift
1414
PublicAPI/Path.swift
15-
PublicAPI/TargetBuildContext.swift
16-
ImplementationDetails.swift)
15+
PublicAPI/Protocols.swift
16+
Implementation.swift)
1717

1818
target_compile_options(PackagePlugin PUBLIC
1919
$<$<COMPILE_LANGUAGE:Swift>:-package-description-version$<SEMICOLON>999.0>)

0 commit comments

Comments
 (0)