Plugin.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright 2024, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Foundation
  17. import PackagePlugin
  18. @main
  19. struct GRPCGeneratorCommandPlugin: CommandPlugin {
  20. /// Perform command, the entry-point when using a Package manifest.
  21. func performCommand(context: PluginContext, arguments: [String]) async throws {
  22. // MARK: Configuration
  23. let commandConfig: CommandConfiguration
  24. do {
  25. commandConfig = try CommandConfiguration(arguments: arguments)
  26. } catch PluginError.helpRequested {
  27. Flag.printHelp()
  28. return // don't throw, the user requested this
  29. } catch {
  30. Flag.printHelp()
  31. throw error
  32. }
  33. let config = commandConfig.common
  34. let inputFiles = inputFiles(from: arguments)
  35. print("InputFiles: \(inputFiles.joined(separator: ", "))")
  36. let protocPath = try deriveProtocPath(using: config, tool: context.tool)
  37. let protocGenGRPCSwiftPath = try context.tool(named: "protoc-gen-grpc-swift").url
  38. let protocGenSwiftPath = try context.tool(named: "protoc-gen-swift").url
  39. let outputDirectory =
  40. config.outputPath.map { URL(fileURLWithPath: $0) } ?? context.pluginWorkDirectoryURL
  41. print("Generated files will be written to: '\(outputDirectory.relativePath)'")
  42. let inputFileURLs = inputFiles.map { URL(fileURLWithPath: $0) }
  43. // MARK: proto-gen-grpc-swift
  44. if config.client != false || config.server != false {
  45. let arguments = constructProtocGenGRPCSwiftArguments(
  46. config: config,
  47. using: config.fileNaming,
  48. inputFiles: inputFileURLs,
  49. protoDirectoryPaths: inputFileURLs.map { $0.deletingLastPathComponent() },
  50. protocGenGRPCSwiftPath: protocGenGRPCSwiftPath,
  51. outputDirectory: outputDirectory
  52. )
  53. printProtocInvocation(protocPath, arguments)
  54. if !commandConfig.dryRun {
  55. let process = try Process.run(protocPath, arguments: arguments)
  56. process.waitUntilExit()
  57. if process.terminationReason == .exit && process.terminationStatus == 0 {
  58. print("Generated gRPC Swift files for \(inputFiles.joined(separator: ", ")).")
  59. } else {
  60. let problem = "\(process.terminationReason):\(process.terminationStatus)"
  61. Diagnostics.error("Generating gRPC Swift files failed: \(problem)")
  62. }
  63. }
  64. }
  65. // MARK: proto-gen-swift
  66. if config.message != false {
  67. let arguments = constructProtocGenSwiftArguments(
  68. config: config,
  69. using: config.fileNaming,
  70. inputFiles: inputFileURLs,
  71. protoDirectoryPaths: inputFileURLs.map { $0.deletingLastPathComponent() },
  72. protocGenSwiftPath: protocGenSwiftPath,
  73. outputDirectory: outputDirectory
  74. )
  75. printProtocInvocation(protocPath, arguments)
  76. if !commandConfig.dryRun {
  77. let process = try Process.run(protocPath, arguments: arguments)
  78. process.waitUntilExit()
  79. if process.terminationReason == .exit && process.terminationStatus == 0 {
  80. print("Generated protobuf message Swift files for \(inputFiles.joined(separator: ", ")).")
  81. } else {
  82. let problem = "\(process.terminationReason):\(process.terminationStatus)"
  83. Diagnostics.error("Generating Protobuf message Swift files failed: \(problem)")
  84. }
  85. }
  86. }
  87. }
  88. }
  89. /// Print a single invocation of `protoc`
  90. /// - Parameters:
  91. /// - executableURL: The path to the `protoc` executable.
  92. /// - arguments: The arguments to be passed to `protoc`.
  93. func printProtocInvocation(_ executableURL: URL, _ arguments: [String]) {
  94. print("protoc invocation:")
  95. print(" \(executableURL.relativePath) \\")
  96. for argument in arguments[..<arguments.count.advanced(by: -1)] {
  97. print(" \(argument) \\")
  98. }
  99. if let lastArgument = arguments.last {
  100. print(" \(lastArgument)")
  101. }
  102. }