Code Monkey home page Code Monkey logo

sbt-protoc's Introduction

sbt-protoc

CI

This plugin uses protoc to generate code from proto files. This SBT plugin is meant to supersede sbt-protobuf and sbt-scalapb.

Highlights

  1. Generates source code directly under src_managed by default (works better with IntelliJ)
  2. Supports compiling protos in both Test and Compile configuration.
  3. Supports JVM-based code generators. Write your own custom code generator.
  4. Straightforward: No PB.protobufSettings, packaged as auto-plugin.

Installation

Step 1: create project/protoc.sbt with:

addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.7")

libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.10.10"

Step 2: add to build.sbt:

If you only want to generate Java code:

Compile / PB.targets := Seq(
  PB.gens.java -> (Compile / sourceManaged).value
)

A version of protobuf-java is going to get added to the runtime dependencies. To explicitly set this version you can write:

Compile / PB.targets := Seq(
  PB.gens.java("3.7.0") -> (Compile / sourceManaged).value
)

To pass generator parameters, for example to request the Java lite runtime, use:

Compile / PB.targets := Seq(
  Target(PB.gens.java, (Compile / sourceManaged).value, Seq("lite"))
)

For ScalaPB:

Compile / PB.targets := Seq(
  scalapb.gen() -> (Compile / sourceManaged).value
)

To generate Java + Scala with Java conversions:

Compile / PB.targets := Seq(
  PB.gens.java -> (Compile / sourceManaged).value,
  scalapb.gen(javaConversions = true) -> (Compile / sourceManaged).value
)

To make standard google.protobuf types available to import:

libraryDependencies ++= Seq(
  "com.google.protobuf" % "protobuf-java" % "3.13.0" % "protobuf"
)

The following includes both standard google.protobuf types and ScalaPB:

libraryDependencies ++= Seq(
    "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"
)

Step 3: Put some protos in src/main/protobuf and compile

Download plugins that are available on maven repository

To download an artifact and use it as a code generator plugin:

libraryDependencies += "io.grpc" % "protoc-gen-grpc-java" % "1.23.0" asProtocPlugin()

Compile / PB.targets := Seq(
  PB.gens.plugin("grpc-java") -> (Compile / sourceManaged).value,
)

Note the asProtocPlugin provided to the dependency, this is equivalent to:

libraryDependencies += "io.grpc" % "protoc-gen-grpc-java" % "1.23.0" % "protobuf" artifacts(
  Artifact("protoc-gen-grpc-java", PB.ProtocPlugin, "exe", "linux-x86_64"))

with the operating system replaced accordingly to the system you are running on. You can use the full syntax in case the code generator you are trying to download follows a different pattern.

To invoke a plugin that is already locally installed

Compile / PB.targets := Seq(
  PB.gens.plugin(name="myplugin", path="/path/to/plugin") -> (Compile / sourceManaged).value / "js"
)

If you need to pass parameters to the plugin, it can be done as follows:

val grpcWebGen = PB.gens.plugin(
  name="grpc-web",
  path="/usr/local/bin/protoc-gen-grpc-web-1.0.7-linux-x86_64"
)

Compile / PB.targets := Seq(
  (grpcWebGen, Seq("mode=grpcwebtext")) -> (Compile / sourceManaged).value / "js"
)

Migration notes

From sbt-protoc 1.0.0 to 1.0.1

  • Protos imported with "protobuf-src" are now compiled only once per project, in the Compile configuration. Use Test / PB.protoSources += PB.externalSourcePath.value to trigger compilation also in Test (the previous behavior).
  • The cacheClassLoaders setting key is now deprecated as sbt-protoc now automatically reloads the class loaders used for sandboxing if it detects that the classpath it targets has changed since the last invocation. For advanced setups with a custom PB.artifactResolver returning different files on each invocation (and only for those), consider setting cacheArtifactResolution to false.

From sbt-protoc < 1.0.0 to 1.0.0

  • PB.protocVersion now accepts a version in x.y.z format (for example, 3.13.0). Previously, this key accepted protoc-jar style version flags such as -v361. Version 1.0.x of ScalaPB will strip out the -v part (a behavior that will be deprecated later), however it does not take version numbers without dot seperators.
  • Use PB.protocExecutable to use a locally installed protoc. By default this key downloads and caches protoc from Maven.
  • If you previously used protoc-jar's option --include_std_types, see Installation instructions above, and look for "To make standard google.protobuf types available to import"
  • Use PB.protocRun to have more control on how sbt-protoc invokes protoc (By default, it run PB.protocExecutable.

See CHANGELOG.md for more details.

Additional options

The options below need to be scoped to either Compile or Test (if unsure, you probably want Compile)

Example settings:

// Force the version for the protoc binary
PB.protocVersion := "3.21.7"

// Additional directories to search for imports:
Compile / PB.includePaths ++= Seq(file("/some/other/path"))

// Make protos from some Jar available to import.
libraryDependencies ++= Seq(
  "com.google.protobuf" % "protobuf-java" % "3.13.0" % "protobuf"
)

// Compile protos from some Jar (and make them available to import). Without
// the intrasitive() directory, `protobuf-src` would also unpack and compile
// all transitive dependencies of the package. This could lead to having
// duplicate class files, if another library is already providing compiled
// classes for your dependencies.
libraryDependencies ++= Seq(
  "com.google.api.grpc" % "proto-google-common-protos" % "1.17.0" % "protobuf-src" intransitive()
)

// Changing where to look for protos to compile (default src/main/protobuf):
Compile / PB.protoSources := Seq(sourceDirectory.value / "somewhere")

// Additional options to pass to protoc:
Compile / PB.protocOptions := Seq("-xyz")

// Excluding some proto files:
PB.generate / excludeFilter := "test-*.proto"

// Rarely needed: override where proto files from library dependencies are
// extracted to:
Compile / PB.externalIncludePath := file("/tmp/foo")

// By default we generate into target/src_managed. To customize:
Compile / PB.targets := Seq(
  scalapb.gen() -> file("/some/other/dir")
)

// Use a locally provided protoc (in 1.x):
PB.protocExecutable := file("/path/to/protoc")

// For sbt-protoc < 1.0 only:
Compile / PB.runProtoc := (args => Process("/path/to/protoc", args)!)

// Prevents the plugin from adding libraryDependencies to your project
PB.additionalDependencies := Nil

// Before version 0.99.15, when compiling in Windows, Python was used to bridge
// protoc and this JVM. To set the path for Python.exe:
// Note that this must be Python2 and not Python3.
// Since version 0.99.15 this option has no effect, and will be removed in a
// future version.
PB.pythonExe := "/path/to/python.exe"

// Disables the manifest processing feature of sbt-protoc that automatically
// adds option protos as a source file to protoc when `ScalaPB-Options-Proto`
// is found in a dependency jar manifest. This setting is turned on by default,
// and disabling it can lead to generation of code that does not compile due
// to inconsistent generator settings between your project and the dependencies
// added. See also https://scalapb.github.io/docs/customizations/#publishing-package-scoped-options
Compile / PB.manifestProcessing := false

Protos in other configs

This plugin supports generating protos in the Test config. That means, that you can put protos under src/test/protobuf and have it generated and compiled under the Test configuration, so the generated code is only available to your tests, but not to your main code.

To do that, add:

Test / PB.targets := Seq(
    PB.gens.java("3.11.4") -> (Test / sourceManaged).value
)

If you want to have protos in some other configuration (not Compile or Test), for example IntegrationTest you need to manually add the plugin default settings in that configuration:

configs(IntegrationTest)

inConfig(IntegrationTest)(sbtprotoc.ProtocPlugin.protobufConfigSettings)

IntegrationTest / PB.targets := Seq(
    PB.gens.java("3.11.4") -> (IntegrationTest / sourceManaged).value
)

Debugging

Show proto files extracted and where there are coming from:

sbt> set logLevel := Level.Debug
sbt> protocUnpackDependencies

IntelliJ IDEA BSP bug

IntelliJ has a bug where it only recognizes generated sources if there is at least one Scala class in the same package - otherwise you'll see red squiggles. As a workaround, you can configure your project to add a private empty class, e.g. like this:

Compile / sourceGenerators += Def.task {
  // adapt this for your build:
  val protoPackage = "org.example.proto.foo"
  val scalaFile = (Compile/sourceManaged).value / "_ONLY_FOR_INTELLIJ.scala"
  
  IO.write(scalaFile,
    s"""package $protoPackage
      |
      |private class _ONLY_FOR_INTELLIJ
      |""".stripMargin)
  Seq(scalaFile)
}.taskValue

sbt-protoc's People

Contributors

bjaglin avatar dimitriho avatar dispalt avatar gaazolee avatar ghisvail avatar github-brice-jaglin avatar jacoby6000 avatar jiminhsieh avatar jvican avatar jyane avatar masseguillaume avatar maxperrimond avatar mpollmeier avatar ngbinh avatar phderome avatar plaflamme avatar povder avatar scala-steward avatar shinnya avatar thesamet avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sbt-protoc's Issues

Lots of warnings from wartremover and scapegoat

I am using wartremover (with wartremoverErrors ++= Warts.unsafe) and scapegoat (default settings) and I have setup the Akka gRPC Hellow World server and I get a whole lot of warnings/errors from the generated code.

Now I will probably just have to exclude the managed sources from these checks but I still feel that generated code should still avoid "unsafe" features. There are such a large number in such a small amount of code.

Is this just the style that the code was written with or is there something inherent about the code itself that requires these unsafe features? I gave it a quick look and it just seems to follow a very imperative style. My guess is that this is because it was easier to do it this way when using the protobuf-java library.

Here is the output from wartremover:

sbt:console-api> compile
[info] Compiling 8 Scala sources to /Users/jason/source/console-api/target/scala-2.13/classes ...
[warn] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/GreeterServiceHandler.scala:113:85: The unicode arrow `โ‡’` is deprecated, use `=>` instead. If you still wish to display it as one character, consider using a font with programming ligatures such as Fira Code.
[warn]         case Path.Slash(Segment(`prefix`, Path.Slash(Segment(method, Path.Empty)))) โ‡’
[warn]                                                                                     ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/GreeterServiceHandler.scala:75:49: [wartremover:DefaultArguments] Function has default arguments
[error]     def partial(implementation: GreeterService, prefix: String = GreeterService.name, eHandler: ActorSystem => PartialFunction[Throwable, io.grpc.Status] = GrpcExceptionHandler.defaultMapper)(implicit mat: Materializer, system: ActorSystem): PartialFunction[HttpRequest, scala.concurrent.Future[HttpResponse]] = {
[error]                                                 ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:84:19: [wartremover:Any] Inferred type containing Any: Any
[error]       __fieldsMap.getOrElse(__fields.get(0), "").asInstanceOf[_root_.scala.Predef.String]
[error]                   ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:84:50: [wartremover:AsInstanceOf] asInstanceOf is disabled
[error]       __fieldsMap.getOrElse(__fields.get(0), "").asInstanceOf[_root_.scala.Predef.String]
[error]                                                  ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:12:5: [wartremover:DefaultArguments] Function has default arguments
[error]     message: _root_.scala.Predef.String = ""
[error]     ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:64:35: [wartremover:Null] null is disabled
[error]           if (__t != "") __t else null
[error]                                   ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:91:62: [wartremover:OptionPartial] Option#get is disabled - use Option#fold instead
[error]         __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse("")
[error]                                                              ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:93:15: [wartremover:Throw] throw is disabled
[error]     case _ => throw new RuntimeException("Expected PMessage")
[error]               ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:97:113: [wartremover:Throw] throw is disabled
[error]   def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number)
[error]                                                                                                                 ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:99:112: [wartremover:Throw] throw is disabled
[error]   def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber)
[error]                                                                                                                ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:15:23: [wartremover:Var] var is disabled
[error]     private[this] var __serializedSizeCachedValue: _root_.scala.Int = 0
[error]                       ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:17:11: [wartremover:Var] var is disabled
[error]       var __size = 0
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:28:11: [wartremover:Var] var is disabled
[error]       var read = __serializedSizeCachedValue
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:44:11: [wartremover:Var] var is disabled
[error]       var __message = this.message
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:45:11: [wartremover:Var] var is disabled
[error]       var _done__ = false
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:85:19: [wartremover:Any] Inferred type containing Any: Any
[error]       __fieldsMap.getOrElse(__fields.get(0), "").asInstanceOf[_root_.scala.Predef.String]
[error]                   ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:85:50: [wartremover:AsInstanceOf] asInstanceOf is disabled
[error]       __fieldsMap.getOrElse(__fields.get(0), "").asInstanceOf[_root_.scala.Predef.String]
[error]                                                  ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:13:5: [wartremover:DefaultArguments] Function has default arguments
[error]     name: _root_.scala.Predef.String = ""
[error]     ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:65:35: [wartremover:Null] null is disabled
[error]           if (__t != "") __t else null
[error]                                   ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:92:62: [wartremover:OptionPartial] Option#get is disabled - use Option#fold instead
[error]         __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse("")
[error]                                                              ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:94:15: [wartremover:Throw] throw is disabled
[error]     case _ => throw new RuntimeException("Expected PMessage")
[error]               ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:98:113: [wartremover:Throw] throw is disabled
[error]   def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number)
[error]                                                                                                                 ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:100:112: [wartremover:Throw] throw is disabled
[error]   def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber)
[error]                                                                                                                ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:16:23: [wartremover:Var] var is disabled
[error]     private[this] var __serializedSizeCachedValue: _root_.scala.Int = 0
[error]                       ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:18:11: [wartremover:Var] var is disabled
[error]       var __size = 0
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:29:11: [wartremover:Var] var is disabled
[error]       var read = __serializedSizeCachedValue
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:45:11: [wartremover:Var] var is disabled
[error]       var __name = this.name
[error]           ^
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:46:11: [wartremover:Var] var is disabled
[error]       var _done__ = false
[error]           ^
[warn] one warning found
[error] 27 errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 2 s, completed 29/11/2019 10:05:32 AM

And the output from scapegoat:

sbt:console-api> scapegoat
[info] [scapegoat] Removing scapegoat class directory: /Users/jason/source/console-api/target/scala-2.13/scapegoat-classes
[info] [scapegoat] setting output dir to [/Users/jason/source/console-api/target/scala-2.13/scapegoat-report]
[info] [scapegoat] source prefix: src/main/scala
[info] [scapegoat] minimal warn level: info
[info] Compiling 8 Scala sources to /Users/jason/source/console-api/target/scala-2.13/scapegoat-classes ...
[warn] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/GreeterServiceHandler.scala:113:85: The unicode arrow `โ‡’` is deprecated, use `=>` instead. If you still wish to display it as one character, consider using a font with programming ligatures such as Fira Code.
[warn]         case Path.Slash(Segment(`prefix`, Path.Slash(Segment(method, Path.Empty)))) โ‡’
[warn]                                                                                     ^
[info] [info] [scapegoat] 116 activated inspections
[warning] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloReply.scala:84: Use of asInstanceOf
          asInstanceOf used near __fieldsMap.getOrElse[Any](__fields.get(0), "").asInstanceOf[String]. Consider using pattern matching.

[warn] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:84:62: Use of asInstanceOf
[warn]       __fieldsMap.getOrElse(__fields.get(0), "").asInstanceOf[_root_.scala.Predef.String]
[warn]                                                              ^
[info] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloReply.scala:16: Method name not recommended
          Methods should be in camelCase style with the first letter lower-case. See http://docs.scala-lang.org/style/naming-conventions.html#methods

[info] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:16:23: Method name not recommended
[info]     private[this] def __computeSerializedValue(): _root_.scala.Int = {
[info]                       ^
[warning] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloReply.scala:60: Method Returning Any
          Method returns Any. Consider using a more specialized type: def getFieldByNumber(__fieldNumber: Int): Any = (__fieldNumber: Int @unchecked) match {
  case 1 => {
    val __t: String = HelloReply.this.message;
    if (__t.!=(""))
      __tnsole-api / Scapegoat / compileIncremental 2s
    else
      null
  }
}

[warn] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:60:9: Method Returning Any
[warn]     def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = {
[warn]         ^
[error] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloReply.scala:91: Use of Option.get
          HelloReply.this.scalaDescriptor.findFieldByNumber(1).get

[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:91:62: Use of Option.get
[error]         __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse("")
[error]                                                              ^
[info] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloReply.scala:27: Redundant final modifier on method
          example.myapp.helloworld.grpc.HelloReply.serializedSize cannot be overridden, final modifier is redundant

[info] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloReply.scala:27:24: Redundant final modifier on method
[info]     final override def serializedSize: _root_.scala.Int = {
[info]                        ^
[warning] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloRequest.scala:85: Use of asInstanceOf
          asInstanceOf used near __fieldsMap.getOrElse[Any](__fields.get(0), "").asInstanceOf[String]. Consider using pattern matching.

[warn] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:85:62: Use of asInstanceOf
[warn]       __fieldsMap.getOrElse(__fields.get(0), "").asInstanceOf[_root_.scala.Predef.String]
[warn]                                                              ^
[info] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloRequest.scala:17: Method name not recommended
          Methods should be in camelCase style with the first letter lower-case. See http://docs.scala-lang.org/style/naming-conventions.html#methods

[info] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:17:23: Method name not recommended
[info]     private[this] def __computeSerializedValue(): _root_.scala.Int = {
[info]                       ^
[warning] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloRequest.scala:61: Method Returning Any
          Method returns Any. Consider using a more specialized type: def getFieldByNumber(__fieldNumber: Int): Any = (__fieldNumber: Int @unchecked) match {
  case 1 => {
    val __t: String = HelloRequest.this.name;
    if (__t.!=(""))
      __tnsole-api / Scapegoat / compileIncremental 2s
    else
      null
  }
}

[warn] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:61:9: Method Returning Any
[warn]     def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = {
[warn]         ^
[error] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloRequest.scala:92: Use of Option.get
          HelloRequest.this.scalaDescriptor.findFieldByNumber(1).get

[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:92:62: Use of Option.get
[error]         __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse("")
[error]                                                              ^
[info] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloRequest.scala:28: Redundant final modifier on method
          example.myapp.helloworld.grpc.HelloRequest.serializedSize cannot be overridden, final modifier is redundant

[info] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloRequest.scala:28:24: Redundant final modifier on method
[info]     final override def serializedSize: _root_.scala.Int = {
[info]                        ^
[info] .Users.jason.source.console-api.target.scala-2.13.src_managed.main.example.myapp.helloworld.grpc.HelloworldProto.scala:9: Prefer Seq.empty
          Seq[T]() allocates an intermediate object. Consider Seq.empty wich returns a singleton instance without creating a new object. scala.collection.immutable.Seq.apply[Nothing]()

[info] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/HelloworldProto.scala:9:71: Prefer Seq.empty
[info]   lazy val dependencies: Seq[_root_.scalapb.GeneratedFileObject] = Seq(
[info]                                                                       ^
[info] [error] [scapegoat] Analysis complete: 8 files - 2 errors 4 warns 5 infos
[info] [info] [scapegoat] Written HTML report [/Users/jason/source/console-api/target/scala-2.13/scapegoat-report/scapegoat.html]
[info] [info] [scapegoat] Written XML report [/Users/jason/source/console-api/target/scala-2.13/scapegoat-report/scapegoat.xml]
[info] [info] [scapegoat] Written Scalastyle XML report [/Users/jason/source/console-api/target/scala-2.13/scapegoat-report/scapegoat-scalastyle.xml]
[warn] 5 warnings found
[error] two errors found
[error] (Scapegoat / compileIncremental) Compilation failed
[error] Total time: 3 s, completed 29/11/2019 9:59:48 AM

Error when creating a message with the name String

Hi, if you try to compile this simpile message you will get an error:
syntax = "proto3";

package demo;

message String {
    string chars = 1;
    bool valid = 2;
}

The .scala file is generated correctly but the error is thrown when sbt try to compile it.

final case class String(
    chars: String = "", // The error is here, String is java.lang.String but it takes demo.String
    valid: Boolean = false

Support Packaging and Import of Proto files

In sbt-proto you can both package and import proto files from other JAR files using the PB.protobuf config command as outlined here. I would like to still be able to do this with this library. Is there a analogous functionality that currently exists for this?

Sources dir included twice

We are using a proto repository shared between multiple applications and I need to vendor generated sources in each application repository.

My build.sbt file looks like this:

PB.protoSources in Compile := Seq(
  file("vendor/proto/changelog")
)
PB.deleteTargetDirectory := false
PB.targets in Compile := Seq(
  scalapb
    .gen(grpc = true, flatPackage = true) -> baseDirectory.value / "src" / "main" / "scala"
)

When I compile locally (where I have the vendor/proto submodule), I get this error:

Application.scala:10: Application is already defined as object Application
.....

I think src/main/scala gets added twice to sbt source file configuration. How can I fix this ?

Could not find protocbridge.forntend.BridgeApp only on Windows. Works on Linux. ver 0.99.18

Newer versions that don't use python produce error on Windows (10):

Error: Could not find or load main class protocbridge.frontend.BridgeApp --scala_out: protoc-gen-scala: Plugin failed with status code 1. [trace] Stack trace suppressed: run last compile:protocGenerate for the full output. [error] (compile:protocGenerate) protoc returned exit code: 1

java.lang.RuntimeException: protoc returned exit code: 1 at scala.sys.package$.error(package.scala:27) at sbtprotoc.ProtocPlugin$.sbtprotoc$ProtocPlugin$$compile(ProtocPlugin.scala:142) at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.sbtprotoc$ProtocPlugin$$anonfun$$compileProto$1(ProtocPlugin.scala:175) at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1$$anonfun$5.apply(ProtocPlugin.scala:186) at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1$$anonfun$5.apply(ProtocPlugin.scala:185) at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:253) at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:253) at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:267) at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:263) at sbt.Difference.apply(Tracked.scala:224) at sbt.Difference.apply(Tracked.scala:206) at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:263) at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:262) at sbt.Difference.apply(Tracked.scala:224) at sbt.Difference.apply(Tracked.scala:200) at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:262) at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:260) at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.apply(ProtocPlugin.scala:192) at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.apply(ProtocPlugin.scala:167) at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47) at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40) at sbt.std.Transform$$anon$4.work(System.scala:63) at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228) at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228) at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17) at sbt.Execute.work(Execute.scala:237) at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228) at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228) at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159) at sbt.CompletionService$$anon$2.call(CompletionService.scala:28) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) [error] (compile:protocGenerate) protoc returned exit code: 1

Import external proto in other proto

Hi,
I'm testing different configurations based on your example "scalapb-test". In this case, I would like to import external protos in this project. I tested different alternatives to import the proto in demo.proto file, but not working.

syntax = "proto3";

package com.example.common;

import "services/protos/external/more_external/pepe/common.proto";

message Hello {
  int32 a = 1;
  int32 b = 2;
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

message Period {
  string day = 1;
  Person person = 2;
}

This is my common.proto file

syntax = "proto3";

package test.common.protos;

message Person {
    string name = 1;
    string age = 2;
}

I followed the instructions to configure build.sbt using protoSources and includePaths options. Could you please help? I attached the project with the modifications that I did.
scalapb-test-master-importing.zip

Regards

README is out of date

addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.11")

libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin" % "0.6.2"

I was getting unable to find the "com.thesamet" % "sbt-protoc" % "0.99.11" dependency. I was able to work with:

addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.12")

libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin" % "0.6.6"

Just wanted to let you guys know ;)

deserialized old messages have `null` for new Optional field

Steps to help produce issue;

  1. create a simple message with a few fields.
message Answer {
    int32 number = 1;
    string text = 2;
}
  1. Persist one or more of these messages.
  2. Add an optional string to the message definition.
message Answer {
    int32 number = 1;
    string text = 2;
    google.protobuf.StringValue user_id = 3;
}
  1. The generated case class has userId: Option[String] = None; great.
  2. Deserialize and print the messages stored in step 2.

Expected result:
Answer(1, test, None)

Actual result:
Answer(1, test, null)

This causes unexpected bugs (Null Pointer Exceptions) after system upgrades / migrations.
They can be handled by something like Option(answer.userId).flatten but...
This is Scala; we do not like null!

Unresolved dependencies for 0.99.10

Hello,

addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.10")

throws an Error:
unresolved dependency: com.thesamet#sbt-protoc;0.99.10: not found

the same with all other versions

Compiling to Proto3, need Proto2

I have a proto file for proto 2.6.1. It must compile to proto 2.6.

However, when I do a compile, it looks like the generated Java is for proto3 ...

I find this in the generated java

com.google.protobuf.GeneratedMessageV3 

I am getting lots of compiler failures, because GeneratedMessageV3 is not found (which makes sense since I am using proto-java 2.6.1.

In my sbt, I have this...

  PB.targets in Compile := Seq(
    PB.gens.java("2.6.1") -> (sourceManaged in Compile).value
  )

In the proto file, I have...

syntax = "proto2";

Is there something I am doing incorrectly?

protoc-bridge (and so sbt-protoc) does not work with Python 3 on Windows

The error gotten when it was running with python 3 is:

Traceback (most recent call last):
  File "C:\Users\DMCGIL~1\AppData\Local\Temp\protocbridge7979764971266522589.py", line 6, in <module>
    s.sendall(content)
TypeError: a bytes-like object is required, not 'str'

The problem was solved by adding

PB.pythonExe := "C:\\Python27\\python.exe"

to the build.sbt (I'm going to move it into my user .sbt file), since the default python in the PATH was python 3.

Seeing `text file busy` error during protobuf compilation

We're seeing spurious failures on a build server due to the included error (below). This issue was actually reported in the protoc-jar repository here. Seems like a fix was added in this issue_text_file_busy branch.

I saw that this project depends on "protoc-jar" % "3.1.0.2", but the most up to date version is "protoc-jar" % "3.1.0.3". Is there something we can do to use sbt-protoc in our project but use that issue_txt_file_busy branch of protoc-jar? Or do we just have to wait for a fix to come out on protoc-jar and have that rolled into this project?

Any help greatly appreciated!

Caused by: java.io.IOException: Cannot run program "/tmp/protoc697070785121925936.exe": error=26, Text file busy
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
	at com.github.os72.protocjar.Protoc.runProtoc(Protoc.java:84)
	at com.github.os72.protocjar.Protoc.runProtoc(Protoc.java:55)
	at sbtprotoc.ProtocPlugin$$anonfun$protobufGlobalSettings$9$$anonfun$apply$4.apply(ProtocPlugin.scala:56)
	at sbtprotoc.ProtocPlugin$$anonfun$protobufGlobalSettings$9$$anonfun$apply$4.apply(ProtocPlugin.scala:55)
	at protocbridge.ProtocBridge$.runWithGenerators(ProtocBridge.scala:79)
	at protocbridge.ProtocBridge$.run(ProtocBridge.scala:61)
	at sbtprotoc.ProtocPlugin$.executeProtoc(ProtocPlugin.scala:88)
	at sbtprotoc.ProtocPlugin$.sbtprotoc$ProtocPlugin$$compile(ProtocPlugin.scala:112)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1$$anonfun$4.apply(ProtocPlugin.scala:141)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1$$anonfun$4.apply(ProtocPlugin.scala:140)
	at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:235)
	at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:235)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:249)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:245)
	at sbt.Difference.apply(Tracked.scala:224)
	at sbt.Difference.apply(Tracked.scala:206)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:245)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:244)
	at sbt.Difference.apply(Tracked.scala:224)
	at sbt.Difference.apply(Tracked.scala:200)
	at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:244)
	at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:242)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.apply(ProtocPlugin.scala:150)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.apply(ProtocPlugin.scala:136)
	at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
	at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
	at sbt.std.Transform$$anon$4.work(System.scala:63)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
	at sbt.Execute.work(Execute.scala:237)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
	at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: error=26, Text file busy
	at java.lang.UNIXProcess.forkAndExec(Native Method)
	at java.lang.UNIXProcess.<init>(UNIXProcess.java:248)
	at java.lang.ProcessImpl.start(ProcessImpl.java:134)
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
	at com.github.os72.protocjar.Protoc.runProtoc(Protoc.java:84)
	at com.github.os72.protocjar.Protoc.runProtoc(Protoc.java:55)
	at sbtprotoc.ProtocPlugin$$anonfun$protobufGlobalSettings$9$$anonfun$apply$4.apply(ProtocPlugin.scala:56)
	at sbtprotoc.ProtocPlugin$$anonfun$protobufGlobalSettings$9$$anonfun$apply$4.apply(ProtocPlugin.scala:55)
	at protocbridge.ProtocBridge$.runWithGenerators(ProtocBridge.scala:79)
	at protocbridge.ProtocBridge$.run(ProtocBridge.scala:61)
	at sbtprotoc.ProtocPlugin$.executeProtoc(ProtocPlugin.scala:88)
	at sbtprotoc.ProtocPlugin$.sbtprotoc$ProtocPlugin$$compile(ProtocPlugin.scala:112)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1$$anonfun$4.apply(ProtocPlugin.scala:141)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1$$anonfun$4.apply(ProtocPlugin.scala:140)
	at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:235)
	at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:235)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:249)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:245)
	at sbt.Difference.apply(Tracked.scala:224)
	at sbt.Difference.apply(Tracked.scala:206)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:245)
	at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:244)
	at sbt.Difference.apply(Tracked.scala:224)
	at sbt.Difference.apply(Tracked.scala:200)
	at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:244)
	at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:242)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.apply(ProtocPlugin.scala:150)
	at sbtprotoc.ProtocPlugin$$anonfun$sourceGeneratorTask$1.apply(ProtocPlugin.scala:136)
	at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
	at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
	at sbt.std.Transform$$anon$4.work(System.scala:63)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
	at sbt.Execute.work(Execute.scala:237)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
	at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

using custom code generators does not work in 0.6.6

Demonstrated here:
hedron-interactive/troubleshooting@a4bb25c

Observation:
sbt-protoc custom generator support appears to carry a sbt 1.0 version dependency. Being new to sbt and the sbt-protoc plugin I decided to closely follow the example found here: https://github.com/thesamet/sbt-protoc/blob/master/examples/custom-gen/project/MyGenerator.scala. However, my project no longer loads after adding the generator source to my project directory. SBT is unable to resolve the scalapb package. Error captured below for context:

[error] bad symbolic reference. A signature in DescriptorPimps.class refers to term Scalapb
[error] in package com.trueaccord.scalapb which is not available.
[error] It may be completely missing from the current classpath, or the version on
[error] the classpath might be incompatible with the version used when compiling DescriptorPimps.class.
[error] one error found
[error] (compile:compileIncremental) Compilation failed

Caveats:
The issue does not repro in version 0.7.0-rc7. See here:
hedron-interactive/troubleshooting@8c09096

Generating code from 'external' proto files

Currently, when introducing a dependency with the "protobuf" configuration, its proto files get added to externalIncludePath.

This works great when the artifact also contains correctly-generated classes, like is the case when getting com.google.protobuf resources from scalapb-runtime.

On the other hand, it does not work when the artifacts contains the generated files in a different style than desired (or when it contains no generated files at all), for example when trying to use com.google.api.grpc:grpc-google-cloud-pubsub-v1 with ScalaPB.

In that situation, so far I've worked around this by just adding the external include path to the protoSources wholesale (PB.protoSources += PB.externalIncludePath.value)) - but that is of course rather unsophisticated.

What would you think about providing another way to introduce .proto files from external artifacts into the protoSources? Perhaps a "protobuf-src" configuration that fetches the .proto files from an artifact without introducing its classpath?

How to import proto file from subproject

Hi,
I have subprojects with SBT.

lazy val protoSetting = Seq(
  PB.targets in Compile := Seq(
    scalapb.gen() ->  (sourceManaged in Compile).value//(scalaSource in Compile).value / "buffer"
  )
)

lazy val sharedBase = (project in file("sharedBase")).settings(
  scalaVersion := scalaV,
  credentials += Credentials(Path.userHome / ".sbt" / "isCredentials"),
  resolvers ++= standardResolver,
  libraryDependencies ++= standardDeps,
  protoSetting
)

lazy val purchaseDepartment = (project in file("purchaseDepartment")).settings(
  scalaVersion := scalaV,
  credentials += Credentials(Path.userHome / ".sbt" / "isCredentials"),
  resolvers ++= standardResolver,
  libraryDependencies ++= standardDeps,
  protoSetting,
  PB.protoSources in Compile += target.value / "protobuf_external" / "de" / "scalamat" / "event" / "common"
).enablePlugins(DockerPlugin).dependsOn(sharedBase)

Now I have a proto file laying inside the sharedBase. How I can add now this proto to my proto in the purchasedepartment?

Thank you

Unicode arrow compilation warnings in Scala 2.13

In scala 2.13 with -Werror set then compilation of the generated protobuf sources with an error like:

sbt:console-api> compile
[info] Compiling 7 Scala sources to /Users/jason/source/console-api/target/scala-2.13/classes ...
[error] /Users/jason/source/console-api/target/scala-2.13/src_managed/main/example/myapp/helloworld/grpc/GreeterServiceHandler.scala:113:85: The unicode arrow `โ‡’` is deprecated, use `=>` instead. If you still wish to display it as one character, consider using a font with programming ligatures such as Fira Code.
[error]         case Path.Slash(Segment(`prefix`, Path.Slash(Segment(method, Path.Empty)))) โ‡’
[error]                                                                                     ^
[error] No warnings can be incurred under -Werror.
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 5 s, completed 29/11/2019 12:37:03 AM

The arrows were deprecated in scala/scala#7540

Generate protobuf classes from external jar

I have the need to use messages from a third party jar that contains *.proto definitions for their interface.

I do not need to write any *.proto messages myself but only need to generate Scala classes from their jar that contains the message definitions.

How can I do this using sbt-protoc? I attempted to do

PB.protoSources in Compile := Seq((target)(_ / "protobuf-external").value)

As well as add the jar to my library dependencies but that does not work.

Is this a capability of sbt-protoc? I can see the *.proto files in the /target/protobuf_external directory but can't seem to generate them.

Thank you for the help

Generating proto files from multiple sbt projects

Hi,
I have a project with 3 sbt projects inside and I want to generate proto classes based on the proto files defined in every project:

  • shopping-cart-service/cart-api/src/main/protobuf/cart.proto
  • shopping-cart-service/item-api/src/main/protobuf/item.proto
  • shopping-cart-service/price-api/src/main/protobuf/price.proto

When I compile the project, some classes are not generated, sometimes price and cart are generated inside cart project, sometimes cart is not generated. I uploaded a test project in order to provide you the environment where these issues happened.

shopping-cart-service.zip

Could you please help me?

Regards

Unable to create scala classes

I did

PB.targets in Compile := Seq(
  PB.gens.java  -> file(baseDirectory.value+"/schema/java/"),
  scalapb.gen() -> file(baseDirectory.value+"/schema/scala/")
)

to generate scala and java classes but it failed with error Sample\SampleProto.scala:8: SampleProto is already defined as object SampleProto
[error] object SampleProto extends root.scalapb.GeneratedFileObject {
[error] ^
[error] four errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 4 s, completed Jul 31, 2019 4:36:21 PM

Wrong protoc for Unix system

Hi

I'm trying to compile proto files with required version v261 and looks like protoc-jar takes wrong version, here is messages

protoc-jar: protoc version: 2.6.1, detected platform: osx-x86_64 (mac os x/x86_64)
protoc-jar: embedded: bin/2.6.1/protoc-2.6.1-osx-x86_64.exe

As you can see i have Mac osx and protoc takes exe Windows executable version, but it should be binary executable Unix based protoc

Cannot use the plugin alongside other code generating plugins

Looks like there is an issue when a project is using sbt protobuf generators alongside sbt-buildinfo plugin

registry.proto: warning: Import google/protobuf/wrappers.proto but not used.
[info] Compiling protobuf
[info] Protoc target directory: /builds/api/my-project/sub-project/target/scala-2.12/src_managed/main
[info] Compiling 56 Scala sources to /builds/api/my-project/sub-project/target/scala-2.12/classes ...
[error] IO error while decoding /builds/api/my-project/sub-project/target/scala-2.12/src_managed/main/sbt-buildinfo/BuildInfo.scala with UTF-8: /builds/api/my-project/sub-project/target/scala-2.12/src_managed/main/sbt-buildinfo/BuildInfo.scala (No such file or directory)
[error] Please try specifying another one using the -encoding option
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 32 s, completed Jul 2, 2019 9:20:33 PM

proto files in test scope in a multi-module project are not picked up

I have a multi-module project and one module is called core. I am trying to generate code for the proto file inside core/src/test/protobuf but the file is never picked up in test scope (i.e. running test:compile. I have added this to build.sbt running sbt 0.13.16.

lazy val core = Project("core", file("core"))
  .settings(
    ... // other stuff
    PB.targets in Compile := Seq(scalapb.gen(grpc=false) -> (sourceManaged in Compile).value),
    PB.targets in Test := Seq(scalapb.gen(grpc=false) -> (sourceManaged in Test).value)
 )

grpc?

Hello, since I only wanted to use java protobuf with sbt, this plugin seems, perfectly for me.
However as far as I seen, this does not support grpc, is that correct?

it would be great to have grpc support.

Input is shadowed in the --proto_path

[error] proto/svc1/rpc.proto: Input is shadowed in the --proto_path by proto/svc2/rpc.proto. Either use the latter file as your input or reorder the --proto_path so that the former file's location comes first.

We store every protobuf in a single repository, because some services require only few of them I decided to import them like so:

PB.protoSources in Compile := Seq(
  file("vendor/proto/svc1"),
  file("vendor/proto/svc2"),
)

And this fails with the error above. Any solutions for this?

The following is working correctly:

PB.protoSources in Compile := Seq(
  file("vendor/proto/")
)

protoc-gen-jvm

When I tried to execute this command

[C:\Users\26804\AppData\Local\Temp\protocjar5737050678362154077\bin\protoc.exe, --plugin=protoc-gen-jvm_hiyB4lbG=C:\Users\26804\AppData\Local\Temp\protocbridge1055682509143521741.bat, --plugin=protoc-gen-jvm_mUHPcxV5=C:\Users\26804\AppData\Local\Temp\protocbridge4757607570199059927.bat, --plugin=protoc-gen-jvm_u96mpbJk=C:\Users\26804\AppData\Local\Temp\protocbridge4637337314990832430.bat, --java_out=:E:\WebLearning\agent-center\models\model-base\target\scala-2.12\src_managed\main, --jvm_hiyB4lbG_out=:E:\WebLearning\agent-center\models\model-base\target\scala-2.12\src_managed\main, --jvm_mUHPcxV5_out=:E:\WebLearning\agent-center\models\model-base\target\scala-2.12\src_managed\main, --jvm_u96mpbJk_out=:E:\WebLearning\agent-center\models\model-base\target\scala-2.12\src_managed\main, -IE:\WebLearning\agent-center\models\model-base\src\main\protobuf, -IE:\WebLearning\agent-center\models\model-base\target\protobuf_external, -IE:\WebLearning\agent-center\models\model-base\src\main\protobuf, -IE:\WebLearning\agent-center\models\model-base\target\protobuf_external, E:\WebLearning\agent-center\models\model-base\src\main\protobuf\Enums.proto, E:\WebLearning\agent-center\models\model-base\src\main\protobuf\FePermission.proto, E:\WebLearning\agent-center\models\model-base\src\main\protobuf\Messages.proto, E:\WebLearning\agent-center\models\model-base\src\main\protobuf\Perms.proto

SocketException was thrown but I thought the "protoc.exe" was not problem

Exception in thread "main" java.net.SocketException: Connection reset
        at java.net.SocketInputStream.read(SocketInputStream.java:210)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.net.SocketInputStream.read(SocketInputStream.java:127)
        at protocbridge.frontend.BridgeApp.readInputStreamToByteArray(BridgeApp.java:30)
        at protocbridge.frontend.BridgeApp.main(BridgeApp.java:21)
--jvm_hiyB4lbG_out: protoc-gen-jvm_hiyB4lbG: Plugin failed with status code 1.
[error] java.lang.RuntimeException: protoc returned exit code: 1
[error]         at scala.sys.package$.error(package.scala:26)
[error]         at sbtprotoc.ProtocPlugin$.compile(ProtocPlugin.scala:142)
[error]         at sbtprotoc.ProtocPlugin$.compileProto$1(ProtocPlugin.scala:182)
[error]         at sbtprotoc.ProtocPlugin$.$anonfun$sourceGeneratorTask$4(ProtocPlugin.scala:186)
[error]         at sbt.util.FileFunction$.$anonfun$cached$1(FileFunction.scala:73)
[error]         at sbt.util.FileFunction$.$anonfun$cached$4(FileFunction.scala:147)
[error]         at sbt.util.Difference.apply(Tracked.scala:313)
[error]         at sbt.util.Difference.apply(Tracked.scala:293)
[error]         at sbt.util.FileFunction$.$anonfun$cached$3(FileFunction.scala:143)
[error]         at sbt.util.Difference.apply(Tracked.scala:313)
[error]         at sbt.util.Difference.apply(Tracked.scala:288)
[error]         at sbt.util.FileFunction$.$anonfun$cached$2(FileFunction.scala:142)
[error]         at sbtprotoc.ProtocPlugin$.$anonfun$sourceGeneratorTask$1(ProtocPlugin.scala:192)
[error]         at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error]         at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
[error]         at sbt.std.Transform$$anon$4.work(System.scala:67)
[error]         at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
[error]         at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error]         at sbt.Execute.work(Execute.scala:278)
[error]         at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
[error]         at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error]         at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error]         at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]         at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error]         at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error]         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error]         at java.lang.Thread.run(Thread.java:748)
[error] (model-base / Compile / protocGenerate) protoc returned exit code: 1

Upgrade to SBT 1.0.0

Would be very nice. With Scala 2.12.3, sbt.version=1.0.0 and
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.11")
my SBT doesn't find the dependency.

My resolvers:

resolvers ++= Seq(
  "Sonatype Releases" at "https://oss.sonatype.org/content/repositories/releases/",
  "MVN Repository" at "https://mvnrepository.com/artifact/"
)
resolvers += Resolver.sonatypeRepo("snapshots")

sbt plugins customizing PB.targets cannot play nice together in Test

In one project, we are using several plugins that AutoPlugin#require ProtocPlugin to customize PB.targets (akka-grpc & other custom plugins).

AkkaGrpcPlugin (up to 0.7.1) turned out to set PB.targets, making it impossible to make it play well with another plugins without introducing an explicit require dependency between plugins, as detailed in akka/akka-grpc#696.

Unfortunately, moving from set to append to customize PB.targets means that targets from parent configurations end up sticking around because of https://github.com/thesamet/sbt-protoc/blob/09c8eeb/src/main/scala/sbtprotoc/ProtocPlugin.scala#L145, which in most situation isnot wanted, as:

  • PB.targets include configuration-specific output paths, that we don't want to rerun downstream
  • protoc-bridge does not handle the repetition of a given JvmGenerator within the same run - protoc simply hangs, probably because of a race in the FIFOs, although I did not investigate

I have opened akka/akka-grpc#702 to work-around this in AkkaGrpcPlugin, but it's hacky at best, so I am wondering if we could consider reverting #16? That would obviously be a breaking change for clients invoking protobufConfigSettings "late" on children configuration (those with a parent), but it turns out this convenience comes at the cost of less interoperability for other plugins.

For PB.protocOptions, PB.protoSources & PB.includePaths that #16 also touched, one can argue that inheriting values for these keys makes sense since they do not define target/output paths.

Can't use sbt-protoc and sbt-buildinfo together

This is failing test case

xuwei-k@71298a8

[info] [info] Compiling 1 Scala source and 1 Java source to /tmp/sbt_2f480695/basic/target/scala-2.10/classes...
[info] [error] source file '/tmp/sbt_2f480695/basic/target/scala-2.10/src_managed/main/sbt-buildinfo/BuildInfo.scala' could not be found
[info] [error] one error found
[info] [error] (compile:compileIncremental) Compilation failed
[info] [error] Total time: 1 s, completed Dec 27, 2016 5:15:31 AM
[error] x sbt-protoc / basic
[error]    {line 1}  Command failed: compile failed

examples/custom-gen does not work with sbt 0.13.16

[info] Compiling 1 Scala source to /home/travis/build/xuwei-k/sbt-protoc/examples/custom-gen/project/target/scala-2.10/sbt-0.13/classes...
[info] 'compiler-interface' not yet compiled for Scala 2.10.6. Compiling...
[info]   Compilation completed in 8.315 s
[error] bad symbolic reference. A signature in DescriptorPimps.class refers to term Scalapb
[error] in package com.trueaccord.scalapb which is not available.
[error] It may be completely missing from the current classpath, or the version on
[error] the classpath might be incompatible with the version used when compiling DescriptorPimps.class.
[error] one error found
[error] (compile:compileIncremental) Compilation failed

sorry we broke CacheImplicits

I added a new implicit for OffsetDateTime in eed3si9n/sjson-new#76.

This unfortunately will break ProtocPlugin when the next RC comes out:

[error] java.lang.AbstractMethodError: Method sbtprotoc/ProtocPlugin$.sjsonnew$CalendarFormats$_setter_$offsetDateTimeStringIso_$eq(Lsjsonnew/IsoString;)V is abstract
[error] 	at sbtprotoc.ProtocPlugin$.sjsonnew$CalendarFormats$_setter_$offsetDateTimeStringIso_$eq(ProtocPlugin.scala)
[error] 	at sjsonnew.CalendarFormats.$init$(CalendarFormats.scala:34)
[error] 	at sbtprotoc.ProtocPlugin$.<init>(ProtocPlugin.scala:11)
[error] 	at sbtprotoc.ProtocPlugin$.<clinit>(ProtocPlugin.scala)

This is because CacheImplicits is mixed into ProtocPlugin.

Refer generated class files in sub projects

Hi,

I am able to generate scala files from proto message, and able to execute the flow end to end. This is working fine if there is one main project, but I am unable to refer these generated files from subprojects. How can I do that?

Exclude dependencies in protobuf configuration from generated POMs

I followed the example to add external Jars containing .proto files needed for compilation, by adding a snippet like the following:

libraryDependencies ++= Seq(
  "com.google.protobuf" % "protobuf-java" % "3.4.0" % "protobuf"
)

The compilation works. However, when publishing the project to Ivy, library dependencies added to the protobuf configuration are listed as compile dependencies in the generated POM file. I only needed these external Jars to compile the proto files, they are not needed as dependencies of the generated Jar. Is there a way to exclude these external dependencies from the generated POM file when packaging and publishing?

Runtime references to undefined settings if a project that disables ProtocPlugin exists

Something like this

lazy val root = (project in file("."))
  .dependsOn(a, b).settings(commonSettings: _*)

lazy val a = (project in file("sub-a"))
  .dependsOn(b, c).settings(commonSettings: _*)

lazy val b = (project in file("sub-b"))
  .dependsOn(c)
  .settings(commonSettings: _*)

lazy val c = (project in file("sub-c"))
  .disablePlugins(sbtprotoc.ProtocPlugin)

would produce

Runtime references to undefined settings:                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                    
  c/compile:protocIncludePaths from root/test:protocDependentProjectsIncludePaths ((sbtprotoc.ProtocPlugin) ProtocPlugin.scala:96)                                                                                                                                                  
                                                                                                                                                                                                                                                                                    
  c/compile:protocSources from root/test:protocDependentProjectsIncludePaths ((sbtprotoc.ProtocPlugin) ProtocPlugin.scala:96)                                                                                                                                                       
                                                                                                                                                                                                                                                                                    
  c/compile:protocIncludePaths from root/test:protocDependentProjectsIncludePaths ((sbtprotoc.ProtocPlugin) ProtocPlugin.scala:96)                                                                                                                                                  
                                                                                                                                                                                                                                                                                    
  c/compile:protocSources from root/test:protocDependentProjectsIncludePaths ((sbtprotoc.ProtocPlugin) ProtocPlugin.scala:96)                                                                                                                                                       
                                                                                                                                                                                                                                                                                    
  c/compile:protocIncludePaths from root/test:protocDependentProjectsIncludePaths ((sbtprotoc.ProtocPlugin) ProtocPlugin.scala:96)                                                                                                                                                  
                                                                                                                                                                                                                                                                                    
  c/compile:protocSources from root/test:protocDependentProjectsIncludePaths ((sbtprotoc.ProtocPlugin) ProtocPlugin.scala:96)                                                                                                                                                       
                                                                                                                                                                                                                                                                                    
        at sbt.Init$class.Uninitialized(Settings.scala:270)                                                                                                                                                                                                                         
        at sbt.Def$.Uninitialized(Def.scala:10)                                                                                                                                                                                                                                     
        at sbt.Init$class.make(Settings.scala:148)                                                                                                                                                                                                                                  
        at sbt.Def$.make(Def.scala:10)                                                                                                                                                                                                                                              
        at sbt.Load$$anonfun$8.apply(Load.scala:161)                                                                                                                                                                                                                                
        at sbt.Load$$anonfun$8.apply(Load.scala:156)                                                                                                                                                                                                                                
        at sbt.Load$.timed(Load.scala:1025)                                                                  

on latest 0.9.16

Use scalapb-protoc with Dotty

I'm trying to set up a project with Dotty.

Currently my project/protoc.sbt looks like this:

addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.19")

libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.8.3"

I'm using libraries compiled to Scala 2.12 by using withDottyCompat in my build.sbt, as explained in the Dotty docs:

lazy val root = project
    .in(file("."))
    .settings(
        libraryDependencies ++= scalaDeps.map(_.withDottyCompat(scalaVersion.value))
                             ++ javaDeps
    )

Unfortunately, it appears that sbt-protoc is adding runtime dependencies using %%, which makes it pick up the Dotty version (currently 0.13):

[error] (update) sbt.librarymanagement.ResolveException: unresolved dependency:
                 com.thesamet.scalapb#scalapb-runtime_0.13;0.8.3: not found

Error using ScalaPB on OpenBSD

Hi,

I've developed an application on Fedora and I'm now trying to build it on OpenBSD (the target platform), but I get this error :

error occurred while compiling protobuf files: Unsupported platform: protoc-3.5.1-openbsd-x86_64.exe

Is this supposed to happen ? If OpenBSD is really unsupported, is there a way to overwrite the protoc path somehow ?

Thank you

Scala optional type is not supported?

Hi,

Thanks for the great plugin. It looks Scala optional type is not supported? It is not a stopper. Just it will be more convenient if it is supported.

Thanks, Cheng

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.