thesamet / sbt-protoc

SBT plugin for generating code from Protocol Buffer using protoc
Apache License 2.0
168 stars 51 forks source link

Add ability to opt-out of automatic source generation #268

Closed ciuncan closed 2 years ago

ciuncan commented 2 years ago

In my project, I am trying to keep the generated sources version controlled, and only generate them when there is a change to proto files. I managed to get akka grpc and protobuf message definitions output in a separate source folder. But when I compile they get regenerated each time.

Currently as I see in the source code, PB.generate is being referenced as an addition to sourceGenerators. As far as I know, the task objects are opaque and there is no way to remove them once they are added.

https://github.com/thesamet/sbt-protoc/blob/master/src/main/scala/sbtprotoc/ProtocPlugin.scala#L352-L357

This could be a setting that will not add PB.generate to sourceGenerators so that I can manually invoke sbt protocGenerate to refresh my generated source files.

thesamet commented 2 years ago

Hi @ciuncan , recent versions of sbt-protoc only regenerate sources when the protos change. The detection is based on timestamp caching. When you force it to regenerate but the generated Scala sources are the same, SBT uses it own cache. However, if you want source generation to happen manually, you can do this through a setting introduced in your own project. The example below shows how to do it in a multi-project build, but this can be similarly done in a single project build:

val enableProtoGen = settingKey[Boolean]("foo")

val myproj = project.in(file("myproj"))
    .settings(
        Compile / PB.targets := (if (enableProtoGen.value) Seq(
          scalapb.gen() -> (sourceManaged in Compile).value / "scalapb"
        ) else Seq.empty),

        libraryDependencies ++= Seq(
          "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "proto
buf",
        ),
        enableProtoGen := false
    )

This will inhibit source generation by default, since PB.targets will be empty. Whenever you want to generate, type the following in sbt:

set myproj/eneableProtoGen := true
protocGenerate

Hope this helps!

ciuncan commented 2 years ago

Hi @thesamet , that is exactly what I wanted to achieve, thank you!

I added the boolean setting key and added following to my project settings, as I couldn't directly use scalapb.gen() since I am benefiting from AkkaGrpcPlugin's settings, it already sets PB.targets:

Compile / PB.targets := (if (enableProtoGen.value) (Compile / PB.targets).value else Seq.empty)

This works for me. If you don't feel like this adding this kind of toggle setting benefits many users, feel free to close this issue.

thesamet commented 2 years ago

Glad to hear you made it work with Akka gRPC. I'll defer on adding an option for the time being - this isn't frequently needed as the recommended usage pattern is to generate on compile.