├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .scala-steward.conf ├── LICENSE ├── README.md ├── build.sbt ├── notes ├── 0.1.markdown ├── 0.2.1.markdown ├── 0.2.2.markdown ├── 0.2.3.markdown ├── 0.2.markdown ├── 0.3.0.markdown ├── 0.3.1.markdown ├── 0.3.2.markdown ├── 0.3.3.markdown ├── 0.4.0.markdown ├── 0.5.0.markdown ├── 0.5.1.markdown ├── 0.5.2.markdown ├── 0.5.3.markdown ├── 0.5.4.markdown ├── 0.5.5.markdown ├── 0.6.0.markdown ├── 0.6.1.markdown ├── 0.6.2.markdown ├── 0.6.3.markdown └── about.markdown ├── project ├── build.properties └── plugins.sbt ├── src ├── main │ └── scala │ │ └── sbtprotobuf │ │ ├── Compat.scala │ │ ├── ProtobufPlugin.scala │ │ └── SbtProtobuf.scala └── sbt-test │ ├── delete │ ├── clear-dir │ │ ├── build.sbt │ │ ├── project │ │ │ └── plugins.sbt │ │ ├── src │ │ │ └── main │ │ │ │ └── protobuf │ │ │ │ └── test.proto │ │ └── test │ └── single-file │ │ ├── build.sbt │ │ ├── project │ │ └── plugins.sbt │ │ ├── src │ │ └── main │ │ │ └── protobuf │ │ │ ├── test.proto │ │ │ └── test2.proto │ │ └── test │ └── sbt-protobuf │ ├── basic │ ├── build.sbt │ ├── project │ │ └── plugins.sbt │ ├── src │ │ └── main │ │ │ └── protobuf │ │ │ ├── test1.proto │ │ │ └── test2.proto │ └── test │ ├── exclude │ ├── build.sbt │ ├── project │ │ └── plugins.sbt │ └── test │ ├── grpc │ ├── A.scala │ ├── build.sbt │ ├── project │ │ └── plugins.sbt │ ├── src │ │ └── main │ │ │ └── protobuf │ │ │ └── greeter.proto │ └── test │ ├── multi-project │ ├── bar │ │ └── src │ │ │ └── main │ │ │ └── protobuf │ │ │ └── test2.proto │ ├── build.sbt │ ├── foo │ │ └── src │ │ │ └── main │ │ │ └── protobuf │ │ │ └── test1.proto │ ├── project │ │ └── plugins.sbt │ └── test │ └── task-scoped │ ├── build.sbt │ ├── project │ └── plugins.sbt │ ├── src │ ├── main │ │ └── protobuf │ │ │ ├── test1.proto │ │ │ └── test2.proto │ └── test │ │ └── protobuf │ │ ├── test3.proto │ │ └── test4.proto │ └── test └── version.sbt /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @eed3si9n @xuwei-k 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | push: 5 | schedule: 6 | - cron: '0 5 * * 1' 7 | jobs: 8 | test: 9 | runs-on: ${{ matrix.os }} 10 | timeout-minutes: 20 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | include: 15 | - java: 8 16 | os: ubuntu-latest 17 | - java: 8 18 | os: windows-latest 19 | - java: 11 20 | os: ubuntu-latest 21 | - java: 17 22 | os: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v4 25 | with: 26 | fetch-depth: 0 27 | - uses: actions/setup-java@v4 28 | with: 29 | java-version: ${{ matrix.java }} 30 | distribution: temurin 31 | cache: sbt 32 | - uses: sbt/setup-sbt@v1 33 | - shell: bash 34 | run: sbt -v $(if [[ "${{matrix.sbt_version}}" != "" ]] ; then echo "^^${{matrix.sbt_version}}" ; fi) test scripted 35 | - shell: bash 36 | run: rm -rf "$HOME/.ivy2/local" || true 37 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: ["master", "main"] 5 | tags: ["*"] 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-22.04 9 | steps: 10 | - uses: actions/checkout@v4 11 | with: 12 | fetch-depth: 0 13 | - uses: actions/setup-java@v4 14 | with: 15 | java-version: 8 16 | distribution: adopt 17 | cache: sbt 18 | - run: sbt -Dsbt.io.jdktimestamps=true ci-release 19 | if: ${{ github.repository_owner == 'sbt' }} 20 | env: 21 | PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} 22 | PGP_SECRET: ${{ secrets.PGP_SECRET }} 23 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 24 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 25 | CI_RELEASE: "^ publishSigned" 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .idea_modules 3 | project/boot 4 | project/target 5 | target 6 | .history 7 | .ensime* 8 | -------------------------------------------------------------------------------- /.scala-steward.conf: -------------------------------------------------------------------------------- 1 | updates.pin = [ 2 | { groupId = "com.google.protobuf", artifactId="protobuf-java", version = "3." } 3 | ] 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sbt-protobuf 2 | A plugin for sbt that transforms `*.proto` files into gazillion-loc Java source files, and potentially to other languages too. 3 | 4 | 5 | ## Usage 6 | 7 | ### Adding the plugin dependency 8 | In your project, create a file for plugin library dependencies `project/plugins.sbt` and add the following line: 9 | 10 | ```scala 11 | addSbtPlugin("com.github.sbt" % "sbt-protobuf" % "0.8.1") 12 | ``` 13 | 14 | The dependency to `"com.google.protobuf" % "protobuf-java"` is automatically added to the `Compile` scope. 15 | The version for `protobuf-java` can be controlled by the setting `ProtobufConfig / version` (set to `3.9.0` by default). 16 | 17 | ### Importing sbt-protobuf settings 18 | To actually "activate" the plugin, its settings need to be included in the build. 19 | 20 | ##### build.sbt 21 | 22 | ```scala 23 | enablePlugins(ProtobufPlugin) 24 | ``` 25 | 26 | 27 | ### Declaring dependencies 28 | #### Artifacts containing both `*.proto` files and java binaries 29 | Assuming an artifact contains both `*.proto` files as well as the binaries of the generated `*.java` files, you can specify the dependency like so: 30 | 31 | ```scala 32 | libraryDependencies += "some.groupID" % "some.artifactID" % "1.0" % ProtobufConfig.name // #1 33 | 34 | libraryDependencies += "some.groupID" % "some.artifactID" % "1.0" // #2 35 | ``` 36 | 37 | Line #1 tells `sbt-protobuf` that the specified artifact contains *.proto files which it needs to extract and add to the `--proto_path` for `protoc`. 38 | Internally the setting `protobufExternalIncludePath` is used to track 3rd party proto files. 39 | 40 | Line #2 adds the artifact to the regular compile classpath. 41 | 42 | The `*.proto` files of dependencies are extracted and added to the `--proto_path` parameter for `protoc`, but are not compiled. 43 | 44 | #### Artifacts in the `protobuf` configuration containing only `*.proto` files 45 | You can specify a dependency on an artifact that contains only `.proto` files in the `protobuf` configuration with a `proto` classifier like so: 46 | ``` 47 | libraryDependencies += ("some.groupID" % "some.artifactID" % "1.0" classifier protoClassifier) % s"${ProtobufConfig.name}->${ProtobufConfig.name}" 48 | ``` 49 | 50 | ### Compiling external proto files 51 | Sometimes it's desirable to compile external proto files (eg. because the library is compiled with an older version of `protoc`). 52 | This can be achieved by adding the following setting: 53 | 54 | ```scala 55 | ProtobufConfig / sourceDirectories += (ProtobufConfig / protobufExternalIncludePath).value 56 | ``` 57 | 58 | ### Compiling gRPC proto files 59 | The following enables gRPC support. 60 | 61 | ```scala 62 | ProtobufConfig / protobufGrpcEnabled := true 63 | ``` 64 | 65 | ### Packaging proto files 66 | `*.proto` files can be included in the jar file by adding the following setting to your build definition: 67 | 68 | ```scala 69 | Compile / unmanagedResourceDirectories += (ProtobufConfig / sourceDirectory).value 70 | ``` 71 | 72 | Alternatively, `*.proto` files can be packaged in a separate jar file in the `protobuf` configuration with a `proto` classifier: 73 | 74 | ```scala 75 | addArtifact(ProtobufConfig / protobufPackage / artifact, ProtobufConfig / protobufPackage) 76 | ``` 77 | 78 | ### Changing the location of the generated java files 79 | By default, the compiled proto files are created in `/target//src_managed/main/compiled_protobuf`. Changing the location to `/src/generated` can be done by adding the following setting to your build definition: 80 | 81 | ```scala 82 | ProtobufConfig / javaSource := ((Compile / sourceDirectory).value / "generated") 83 | ``` 84 | 85 | **WARNING:** The content of this directory is **removed** by the `clean` task. Don't set it to a directory containing files you hold dear to your heart. 86 | 87 | ### Note 88 | 89 | 1. If you encounter compile errors, as ```[...] is already defined as object [...]``` you could change the compile order 90 | as ```compileOrder := CompileOrder.JavaThenScala```,the default is ```mixed```. 91 | 92 | 2. The inner message's name could not be the ```.proto```'s file name.that will cause problem too, you could change the inner message's name or the ```.proto``` file name or add the ```option java_outer_classname = "NewNameNotAsTheFileName";``` to you ```.proto``` file. 93 | 94 | ### Additional options to protoc 95 | All options passed to `protoc` are configured via the `protobufProtocOptions`. To add options, for example to run a custom plugin, add them to this setting key. For example: 96 | 97 | ```scala 98 | ProtobufConfig / protobufProtocOptions ++= Seq("--custom-option") 99 | ``` 100 | 101 | ### Additional target directories 102 | The source directories where the files are generated, and the globs used to identify the generated files, are configured by `ProtobufConfig / protobufGeneratedTargets`. 103 | In case only Java files are generated, this setting doesn't need to change, since it automatically inherits the value of `ProtobufConfig / javaSource`, paired with the glob `*.java`. 104 | In case other types of source files are generated, for example by using a custom plugin (see previous section), the corresponding target directories and source file globs must be configured by adding them to this setting. For example: 105 | 106 | ```scala 107 | ProtobufConfig / protobufGeneratedTargets ++= { 108 | Seq(((Compile / sourceDirectory).value / "generated" / "scala", "*.scala")) 109 | } 110 | ``` 111 | 112 | This plugin uses the `protobufGeneratedTargets` setting to: 113 | - add the generated source directories to `cleanFiles` and `managedSourceDirectories` 114 | - collect the generated files after running `protoc` and return them to SBT for the compilation phase 115 | 116 | ## Scope 117 | All settings and tasks are in the `protobuf` scope. If you want to execute the `protobufGenerate` task directly, just run `protobuf:protobufGenerate`. 118 | 119 | 120 | 121 | ## Settings 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 |
namebuilt-in keydefaultdescription
sourceDirectoryx"src/main/protobuf"Path containing *.proto files.
sourceDirectoriesxsourceDirectoryThis setting is used to collect all directories containing *.proto files to compile
javaSourcex"$sourceManaged/compiled_protobuf"Path for the generated *.java files.
versionx"3.25.3"Which version of the protobuf library should be used. A dependency to "com.google.protobuf" % "protobuf-java" % "$version" is automatically added to libraryDependencies
protobufGrpcVersion"1.62.2"Which version of the gRPC plugin should be used.
protobufGrpcEnabledfalseThe setting to enable gRPC plugin.
protobufProtoc"protoc"The path to the 'protoc' executable.
protobufIncludeFiltersGlob(d.toPath()) / "**" / "*.proto"The list of *.proto glob expressions to include.
protobufExcludeFiltersGlob(d.toPath()) / "google" / "protobuf" / "*.proto"The list of *.proto glob expressions to exclude.
protobufIncludePathsSeq($generated-source, protobufExternalIncludePath)The path for additional *.proto files.
protobufExternalIncludePathtarget/protobuf_externalThe path to which protobuf:libraryDependencies are extracted and which is used as protobuf:protobufIncludePath for protoc
protobufGeneratedTargets(file(java source directory based on ProtobufConfig / javaSource), "*.java")The list of target directories and source file globs for the generated files
198 | 199 | ## Tasks 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 |
namedescription
protobufGeneratePerforms the hardcore compiling action and is automatically executed as a "source generator" in the Compile scope.
protobufUnpackDependenciesExtracts proto files from libraryDependencies into protobufExternalInludePatch
protobufRunProtocA function that executes the protobuf compiler with the given arguments, 217 | returning the exit code. The default implementation runs the executable referenced by the protoc setting.
protobufPackageProduces a jar artifact containing only *.proto files, with a proto classifier
protobufProtocOptions--java_out=[java generated source directory from protobufGeneratedTargets]The list of options passed to the protoc binary
231 | 232 | ## IntelliJ IDEA BSP bug 233 | IntelliJ has a [bug](https://youtrack.jetbrains.com/issue/SCL-19517) 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: 234 | ```scala 235 | Compile / sourceGenerators += Def.task { 236 | // adapt this for your build: 237 | val protoPackage = "org.example.proto.foo" 238 | 239 | val scalaFile = (Compile/sourceManaged).value / "_ONLY_FOR_INTELLIJ.scala" 240 | 241 | IO.write(scalaFile, 242 | s"""package $protoPackage 243 | | 244 | |private class _ONLY_FOR_INTELLIJ 245 | |""".stripMargin) 246 | 247 | Seq(scalaFile) 248 | }.taskValue 249 | ``` 250 | 251 | ## Credits 252 | `sbt-protobuf` is based on [softprops/coffeescripted-sbt](https://github.com/softprops/coffeescripted-sbt) for the sbt-0.10 specific parts and [codahale/protobuf-sbt](https://github.com/codahale/protobuf-sbt) for the protobuf specifics. 253 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | ThisBuild / organization := "com.github.sbt" 2 | 3 | lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "3.25.8" % Runtime // for scala-steward 4 | lazy val grpc = "io.grpc" % "protoc-gen-grpc-java" % "1.62.2" % Runtime // for scala-steward 5 | 6 | def scala212 = "2.12.20" 7 | 8 | lazy val root = (project in file(".")) 9 | .enablePlugins(SbtPlugin) 10 | .settings(nocomma { 11 | name := "sbt-protobuf" 12 | crossScalaVersions := Seq(scala212) 13 | scalaVersion := scala212 14 | pluginCrossBuild / sbtVersion := "1.5.8" 15 | libraryDependencies += protobuf 16 | Compile / sourceGenerators += task { 17 | val source = s"""package sbtprotobuf 18 | | 19 | |private[sbtprotobuf] object SbtProtobufBuildInfo { 20 | | def defaultProtobufVersion: String = "${protobuf.revision}" 21 | | def defaultGrpcVersion: String = "${grpc.revision}" 22 | |} 23 | |""".stripMargin 24 | val f = (Compile / sourceManaged).value / "sbtprotobuf" / "SbtProtobufBuildInfo.scala" 25 | IO.write(f, source) 26 | Seq(f) 27 | } 28 | pomPostProcess := { node => 29 | import scala.xml.{NodeSeq, Node} 30 | val rule = new scala.xml.transform.RewriteRule { 31 | override def transform(n: Node) = { 32 | if (List( 33 | n.label == "dependency", 34 | (n \ "groupId").text == protobuf.organization, 35 | (n \ "artifactId").text == protobuf.name, 36 | ).forall(identity)) { 37 | NodeSeq.Empty 38 | } else { 39 | n 40 | } 41 | } 42 | } 43 | new scala.xml.transform.RuleTransformer(rule).transform(node)(0) 44 | } 45 | scalacOptions := Seq("-deprecation", "-unchecked", "-Xlint", "-Yno-adapted-args") 46 | (Compile / doc / scalacOptions) ++= { 47 | val hash = sys.process.Process("git rev-parse HEAD").lineStream_!.head 48 | Seq( 49 | "-sourcepath", baseDirectory.value.getAbsolutePath, 50 | "-doc-source-url", "https://github.com/sbt/sbt-protobuf/blob/" + hash + "€{FILE_PATH}.scala" 51 | ) 52 | } 53 | licenses += (("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0"))) 54 | homepage := Some(url("https://github.com/sbt/sbt-protobuf")) 55 | pomExtra := { 56 | { 57 | Seq( 58 | ("xuwei-k", "Kenji Yoshida"), 59 | ("eed3si9n", "Eugene Yokota"), 60 | ).map { case (id, name) => 61 | 62 | {id} 63 | {name} 64 | https://github.com/{id} 65 | 66 | } 67 | } 68 | } 69 | scriptedBufferLog := false 70 | scriptedLaunchOpts += s"-Dplugin.version=${version.value}" 71 | }) 72 | -------------------------------------------------------------------------------- /notes/0.1.markdown: -------------------------------------------------------------------------------- 1 | * Making use of more predefined setting keys (eg. `javaSource in protobufConfig`) 2 | * Proto-dependencies must now be declared via the provided configuration (see [README](https://github.com/gseitz/sbt-protobuf/README.md)) 3 | * Only `com.google.protobuf.protobuf-java` in the specified version will be added to the libraryDependencies automatically. All other dependencies must be declared manually in favor of a clearer build definition with less magic (sbt alone has enough of that). 4 | * Minor cleanup and fixes 5 | -------------------------------------------------------------------------------- /notes/0.2.1.markdown: -------------------------------------------------------------------------------- 1 | * `javaSource in protobufConfig` is now automatically added to `managedSources in Compile` 2 | * Actually use the executable specified in the `protoc` setting key. (Charles Reiss) 3 | -------------------------------------------------------------------------------- /notes/0.2.2.markdown: -------------------------------------------------------------------------------- 1 | * `javaSource in protobufConfig` is now automatically added to `managedSourceDirectories in Compile` (fixes [#6](https://github.com/gseitz/sbt-protobuf/pull/6)) 2 | -------------------------------------------------------------------------------- /notes/0.2.3.markdown: -------------------------------------------------------------------------------- 1 | * Spaces in paths weren't properly escaped and caused `protoc` to bail out. (fixes [#6](https://github.com/sbt/sbt-protobuf/issues/12)) 2 | -------------------------------------------------------------------------------- /notes/0.2.markdown: -------------------------------------------------------------------------------- 1 | Externally visible changes: 2 | 3 | * Remove `protoSource` in favor of the built-in key `sourceDirectory`. 4 | * `includePaths` is now a TaskKey. 5 | 6 | Internal changes: 7 | 8 | * Use SBT's built-in [uptodate checking](https://github.com/harrah/xsbt/wiki/Common-Tasks) for the proto-files in `sourceDirectory`. 9 | * Cleanups based on Mark's [review](https://github.com/harrah/xsbt/issues/144). 10 | -------------------------------------------------------------------------------- /notes/0.3.0.markdown: -------------------------------------------------------------------------------- 1 | * Add LICENSE file ([#14](https://github.com/sbt/sbt-protobuf/issues/14)) 2 | * Add 'protobuf-' prefix for all custom settings/tasks ([#16](https://github.com/sbt/sbt-protobuf/issues/16)). 3 | * This release drops support for sbt 0.10.x and 0.11.x 4 | 5 | ---- 6 | 7 | #### NOTICE 8 | 9 | This release **breaks backwards compatibility** in case you were explicitly referring to *sbt-protobuf* specific settings/tasks, either in the shell or passing them as parameters to sbt (e.g. as part of a CI build). 10 | 11 | ---- 12 | -------------------------------------------------------------------------------- /notes/0.3.1.markdown: -------------------------------------------------------------------------------- 1 | * Use protobuf `2.5.0` as the default version ([#17](https://github.com/sbt/sbt-protobuf/issues/17)). 2 | * Allow specifying additional `protoc` options ([#18](https://github.com/sbt/sbt-protobuf/pull/18)). 3 | -------------------------------------------------------------------------------- /notes/0.3.2.markdown: -------------------------------------------------------------------------------- 1 | * Add new settings `protocOptions` and `generatedTargets` ([#19](https://github.com/sbt/sbt-protobuf/issues/19)) 2 | -------------------------------------------------------------------------------- /notes/0.3.3.markdown: -------------------------------------------------------------------------------- 1 | * `externalIncludePath` has been added to `cleanFiles` to explicitly remove the 3rd party proto files. Builds that don't change this setting are not affected. 2 | * External proto files can now be compiled. See the *Compiling external proto files* section in the README for more information. 3 | -------------------------------------------------------------------------------- /notes/0.4.0.markdown: -------------------------------------------------------------------------------- 1 | * Added task `runProtoc`, representing a function that executes the protobuf compiler. 2 | This opens up the possibility to invoke *protoc* via means other than just an executable on the filesystem (eg. via [os72/protoc-jar](https://github.com/os72/protoc-jar)). 3 | -------------------------------------------------------------------------------- /notes/0.5.0.markdown: -------------------------------------------------------------------------------- 1 | - [Add `includeFilter` and `excludeFilter` as a posibility to decide what .proto's to generate](https://github.com/sbt/sbt-protobuf/pull/29) 2 | - [add watchSources setting ](https://github.com/sbt/sbt-protobuf/pull/33) 3 | - [use CanonicalPath instead of AbsolutePath](https://github.com/sbt/sbt-protobuf/pull/35) 4 | - [Drop sbt 0.12.x support](https://github.com/sbt/sbt-protobuf/commit/2a472b21bc8f48b20a89187bb0373ae2178d4989) 5 | -------------------------------------------------------------------------------- /notes/0.5.1.markdown: -------------------------------------------------------------------------------- 1 | - [fix issues with deletion](https://github.com/sbt/sbt-protobuf/pull/20) 2 | - [change default "version in protobufConfig". s/2.5.0/2.6.1](https://github.com/sbt/sbt-protobuf/commit/8c7103dee530eaa4f1783) 3 | - improve README examples 4 | - add some scripted tests. enable travis-ci 5 | -------------------------------------------------------------------------------- /notes/0.5.2.markdown: -------------------------------------------------------------------------------- 1 | - fix [including breaks my build due to ambiguous compile key](https://github.com/sbt/sbt-protobuf/issues/37) 2 | -------------------------------------------------------------------------------- /notes/0.5.3.markdown: -------------------------------------------------------------------------------- 1 | - [change default protobuf version. use 3.0.0](https://github.com/sbt/sbt-protobuf/commit/64bd6ffe4991dede579e321cc239082171813110) 2 | -------------------------------------------------------------------------------- /notes/0.5.4.markdown: -------------------------------------------------------------------------------- 1 | - [sbt 0.13.13](https://github.com/sbt/sbt-protobuf/commit/3bbf2599002dafe7c82bafc102eb7985019587b5) 2 | - [update protobuf-java 3.1.0](https://github.com/sbt/sbt-protobuf/commit/ac7ed5127e6303c3eb770a342f0a56988233acb7) 3 | - [Include scalaBinaryVersion to the cache.](https://github.com/sbt/sbt-protobuf/commit/4eca548b44290423089d48156a5703b6a5b960dc) 4 | - [Failing test case](https://github.com/sbt/sbt-protobuf/commit/3a675c85afd20cbdf21be40cb04deeaa0cf0f1e6) 5 | - [fix typo](https://github.com/sbt/sbt-protobuf/commit/624bb850c94b31cb74ca5d4e2a4a915a3a1971dd) 6 | - [avoid deprecated methods since sbt 0.13.13](https://github.com/sbt/sbt-protobuf/commit/f5b806a4ddfb241244502e8d74e7f1b2fe6a9465) 7 | -------------------------------------------------------------------------------- /notes/0.5.5.markdown: -------------------------------------------------------------------------------- 1 | - [protobuf 3.2.0](https://github.com/sbt/sbt-protobuf/commit/b11e9bfd11400b69455477e9f3e336f8acbcf442) 2 | - [Added task scoping to sbt-protobuf](https://github.com/sbt/sbt-protobuf/pull/43) 3 | -------------------------------------------------------------------------------- /notes/0.6.0.markdown: -------------------------------------------------------------------------------- 1 | - [migrate to AutoPlugin](https://github.com/sbt/sbt-protobuf/commit/c02688aee91e4bb9bb34c7f8f8e7d48f5cb8b77b) 2 | - [protobuf 3.3](https://github.com/sbt/sbt-protobuf/commit/cfde934dd4100eb199f26db0c255391153cef616) 3 | - [Package proto files](https://github.com/sbt/sbt-protobuf/pull/47) 4 | - [add multi-project example](https://github.com/sbt/sbt-protobuf/commit/6bce04a72b323a5abf99753bfdbea80917ce53f6) 5 | -------------------------------------------------------------------------------- /notes/0.6.1.markdown: -------------------------------------------------------------------------------- 1 | - [cross build for sbt 1.0](https://github.com/sbt/sbt-protobuf/commit/b3574f2ba07a0de27dbede836bafbc38f7baa500) 2 | -------------------------------------------------------------------------------- /notes/0.6.2.markdown: -------------------------------------------------------------------------------- 1 | - [cross build for sbt 1.0.0-RC2. capitalized `ProtobufConfig`](https://github.com/sbt/sbt-protobuf/commit/eeb5e6b5f53e74d9085c409bdc75c565748f41b1) 2 | -------------------------------------------------------------------------------- /notes/0.6.3.markdown: -------------------------------------------------------------------------------- 1 | - [protobuf 3.4.0](https://github.com/sbt/sbt-protobuf/commit/26a9d111d1b7352499dc999c5443be70f4d5d5c7) 2 | - [sbt 1.0.1](https://github.com/sbt/sbt-protobuf/commit/a22255e8c2e6408e2916a6095bbe4ac5d2aa42a9) 3 | -------------------------------------------------------------------------------- /notes/about.markdown: -------------------------------------------------------------------------------- 1 | [sbt-protobuf](https://github.com/sbt/sbt-protobuf) is a sbt plugin that transforms *.proto files into gazillion-loc java files. 2 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.11.1 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.11.1") 2 | addSbtPlugin("com.eed3si9n" % "sbt-nocomma" % "0.1.2") 3 | -------------------------------------------------------------------------------- /src/main/scala/sbtprotobuf/Compat.scala: -------------------------------------------------------------------------------- 1 | package sbtprotobuf 2 | 3 | import sbt._ 4 | import Keys._ 5 | import sbt.internal.io.Source 6 | 7 | private[sbtprotobuf] trait Compat { self: ScopedProtobufPlugin => 8 | import self.Keys._ 9 | 10 | protected[this] val Process = scala.sys.process.Process 11 | 12 | protected[this] val setProtoArtifact = (ProtobufConfig / protobufPackage / artifact) := { 13 | val previous: Artifact = (ProtobufConfig / protobufPackage / artifact).value 14 | previous 15 | .withConfigurations(Vector(ProtobufConfig)) 16 | .withClassifier(Some(protoClassifier)) 17 | } 18 | 19 | protected[this] val watchSourcesSetting = 20 | watchSources += new Source((ProtobufConfig / sourceDirectory).value, "*.proto", AllPassFilter) 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/sbtprotobuf/ProtobufPlugin.scala: -------------------------------------------------------------------------------- 1 | package sbtprotobuf 2 | 3 | import sbt._ 4 | import Keys._ 5 | import sbt.Defaults.packageTaskSettings 6 | import java.io.File 7 | import SbtProtobuf._ 8 | 9 | object ProtobufTestPlugin extends ScopedProtobufPlugin(Test, "-test") 10 | 11 | object ProtobufPlugin extends ScopedProtobufPlugin(Compile) { 12 | val autoImport = Keys 13 | } 14 | 15 | class ScopedProtobufPlugin(configuration: Configuration, private[sbtprotobuf] val configurationPostfix: String = "") extends AutoPlugin with Compat { self => 16 | lazy val ProtobufConfig = Configuration.of("ProtobufConfig", "protobuf" + configurationPostfix) 17 | lazy val ProtobufTool = config("protobuf-tool").hide 18 | 19 | override def requires = sbt.plugins.JvmPlugin 20 | 21 | val protoClassifier = "proto" 22 | 23 | object Keys { 24 | val ProtobufConfig = self.ProtobufConfig 25 | @deprecated("will be removed. use ProtobufConfig", "0.6.2") 26 | val protobufConfig = ProtobufConfig 27 | 28 | val protobufIncludePaths = taskKey[Seq[File]]("The paths that contain *.proto dependencies.") 29 | val protobufSources = taskKey[Seq[File]]("Protobuf files") 30 | val protobufIncludeFilters = settingKey[Seq[Glob]]("Include filters") 31 | val protobufExcludeFilters = settingKey[Seq[Glob]]("Exclude filters") 32 | val protobufUseSystemProtoc = settingKey[Boolean]("Use the protoc installed on the machine.") 33 | val protobufProtoc = settingKey[String]("The path+name of the protoc executable if protobufUseSystemProtoc is enabled.") 34 | val protobufRunProtoc = taskKey[Seq[String] => Int]("A function that executes the protobuf compiler with the given arguments, returning the exit code of the compilation run.") 35 | val protobufExternalIncludePath = settingKey[File]("The path to which protobuf:libraryDependencies are extracted and which is used as protobuf:includePath for protoc") 36 | val protobufGeneratedTargets = settingKey[Seq[(File,String)]]("Targets for protoc: target directory and glob for generated source files") 37 | val protobufGenerate = taskKey[Seq[File]]("Compile the protobuf sources.") 38 | val protobufUnpackDependencies = taskKey[UnpackedDependencies]("Unpack dependencies.") 39 | val protobufProtocOptions = taskKey[Seq[String]]("Additional options to be passed to protoc") 40 | val protobufPackage = taskKey[File]("Produces a proto artifact, such as a jar containing .proto files") 41 | val protobufGrpcEnabled = settingKey[Boolean]("Enable gRPC plugin") 42 | val protobufGrpcVersion = settingKey[String]("gRPC version") 43 | 44 | @deprecated("will be removed. use enablePlugins(ProtobufPlugin)", "0.6.0") 45 | def protobufSettings = self.projectSettings 46 | } 47 | 48 | import Keys._ 49 | 50 | override def projectConfigurations: Seq[Configuration] = ProtobufConfig :: Nil 51 | 52 | // global scoping can be used to provide the default values 53 | override lazy val globalSettings: Seq[Setting[_]] = Seq( 54 | protobufUseSystemProtoc := false, 55 | protobufGeneratedTargets := Nil, 56 | protobufProtocOptions := Nil, 57 | protobufIncludeFilters := Nil, 58 | protobufExcludeFilters := Nil, 59 | protobufGrpcEnabled := false, 60 | protobufGrpcVersion := SbtProtobufBuildInfo.defaultGrpcVersion, 61 | ) 62 | 63 | override lazy val projectSettings: Seq[Setting[_]] = inConfig(ProtobufConfig)(Seq[Setting[_]]( 64 | sourceDirectory := { (configuration / sourceDirectory).value / "protobuf" }, 65 | sourceDirectories := (sourceDirectory.value :: Nil), 66 | protobufSources := { 67 | val dirs = sourceDirectories.value 68 | val includes = protobufIncludeFilters.value 69 | val excludes = protobufExcludeFilters.value 70 | dirs.flatMap { dir => 71 | val allFiles = (dir ** "*").get.map(_.toPath()) 72 | allFiles 73 | .filter(x => includes.exists(_.matches(x))) 74 | .filterNot(x => excludes.exists(_.matches(x))) 75 | .map(_.toFile()) 76 | } 77 | }, 78 | protobufIncludeFilters ++= { 79 | val dirs = sourceDirectories.value 80 | dirs.map(d => Glob(d.toPath()) / "**" / "*.proto") 81 | }, 82 | protobufExcludeFilters ++= { 83 | val dirs = sourceDirectories.value 84 | val excludes = excludeFilter.value 85 | excludes match { 86 | case NothingFilter | HiddenFileFilter => Nil 87 | case f: ExactFilter => dirs.map(d => Glob(d.toPath()) / f.matchName) 88 | case filter => sys.error(s"unsupported excludeFilter $filter. migrate to ProtobufConfig / protobufExcludeFilters") 89 | } 90 | }, 91 | protobufExcludeFilters ++= { 92 | val dirs = sourceDirectories.value 93 | dirs.map(d => Glob(d.toPath()) / "google" / "protobuf" / "*.proto") 94 | }, 95 | javaSource := { (configuration / sourceManaged).value / "compiled_protobuf" }, 96 | protobufExternalIncludePath := (target.value / "protobuf_external"), 97 | protobufProtoc := "protoc", 98 | protobufRunProtoc := { 99 | // keep this if-expression top-level for selective functor 100 | if (protobufUseSystemProtoc.value) { 101 | val s = streams.value 102 | args => Process(protobufProtoc.value, args).!(s.log) 103 | } else { 104 | val s = streams.value 105 | val ur = update.value 106 | val protoc = withFileCache(s.cacheDirectory.toPath()) { () => 107 | extractFile(ur, protocArtifactName) 108 | } 109 | args => Process(protoc.toAbsolutePath.toString, args).!(s.log) 110 | } 111 | }, 112 | version := SbtProtobufBuildInfo.defaultProtobufVersion, 113 | 114 | protobufGeneratedTargets += Tuple2((ProtobufConfig / javaSource).value, "*.java"), // add javaSource to the list of patterns 115 | 116 | protobufProtocOptions ++= { // if a java target is provided, add java generation option 117 | (ProtobufConfig / protobufGeneratedTargets).value.find(_._2.endsWith(".java")) match { 118 | case Some(targetForJava) => Seq(s"--java_out=${targetForJava._1.getCanonicalPath}") 119 | case None => Nil 120 | } 121 | }, 122 | protobufProtocOptions ++= { 123 | if (protobufGrpcEnabled.value) { 124 | val s = streams.value 125 | val ur = update.value 126 | val grpcCli = withFileCache(s.cacheDirectory.toPath()) { () => 127 | extractFile(ur, protocGenGrpcJavaArtifactName) 128 | } 129 | ((ProtobufConfig / protobufGeneratedTargets).value.find(_._2.endsWith(".java")) match { 130 | case Some(targetForJava) => Seq(s"--java_rpc_out=${targetForJava._1.getCanonicalPath}") 131 | case None => Nil 132 | }) ++ Seq( 133 | s"--plugin=protoc-gen-java_rpc=${grpcCli}" 134 | ) 135 | } else Nil 136 | }, 137 | managedClasspath := { 138 | Classpaths.managedJars(ProtobufConfig, classpathTypes.value, update.value) 139 | }, 140 | 141 | protobufUnpackDependencies := unpackDependenciesTask.value, 142 | 143 | protobufIncludePaths := ((ProtobufConfig / sourceDirectory).value :: Nil), 144 | protobufIncludePaths += protobufExternalIncludePath.value, 145 | 146 | protobufGenerate := sourceGeneratorTask.dependsOn(protobufUnpackDependencies).value, 147 | )) ++ inConfig(ProtobufConfig)( 148 | packageTaskSettings(protobufPackage, packageProtoMappings) 149 | ) ++ Seq[Setting[_]]( 150 | watchSourcesSetting, 151 | configuration / sourceGenerators += (ProtobufConfig / protobufGenerate).taskValue, 152 | cleanFiles ++= (ProtobufConfig / protobufGeneratedTargets).value.map{_._1}, 153 | cleanFiles += (ProtobufConfig / protobufExternalIncludePath).value, 154 | configuration / managedSourceDirectories ++= (ProtobufConfig / protobufGeneratedTargets).value.map{_._1}, 155 | libraryDependencies += ("com.google.protobuf" % "protobuf-java" % (ProtobufConfig / version).value), 156 | libraryDependencies += protocDependency((ProtobufConfig / version).value) % ProtobufTool, 157 | libraryDependencies ++= { 158 | if (protobufGrpcEnabled.value) { 159 | Seq(protocGenGrpcJavaDependency(protobufGrpcVersion.value) % ProtobufTool) 160 | } else Nil 161 | }, 162 | ivyConfigurations ++= List(ProtobufConfig, ProtobufTool), 163 | setProtoArtifact 164 | ) 165 | 166 | case class UnpackedDependencies(dir: File, files: Seq[File]) 167 | 168 | private[this] def executeProtoc(protocCommand: Seq[String] => Int, schemas: Set[File], includePaths: Seq[File], protocOptions: Seq[String], log: Logger) : Int = 169 | try { 170 | val incPath = includePaths.map("-I" + _.getCanonicalPath) 171 | protocCommand(incPath ++ protocOptions ++ schemas.map(_.getCanonicalPath)) 172 | } catch { case e: Exception => 173 | throw new RuntimeException(s"error occurred while compiling protobuf files: ${e.getMessage}", e) 174 | } 175 | 176 | private[this] def compile( 177 | protocCommand: Seq[String] => Int, 178 | schemas: Set[File], 179 | includePaths: Seq[File], 180 | protocOptions: Seq[String], 181 | generatedTargets: Seq[(File, String)], 182 | log: Logger, 183 | ) = { 184 | val generatedTargetDirs = generatedTargets.map(_._1) 185 | generatedTargetDirs.foreach{ targetDir => 186 | IO.delete(targetDir) 187 | targetDir.mkdirs() 188 | } 189 | 190 | if(!schemas.isEmpty){ 191 | log.info(s"compiling ${schemas.size} protobuf files to ${generatedTargetDirs.mkString(",")}") 192 | log.debug("protoc options:") 193 | protocOptions.map("\t"+_).foreach(log.debug(_)) 194 | schemas.foreach(schema => log.info(s"Compiling schema ${schema}")) 195 | 196 | val exitCode = executeProtoc(protocCommand, schemas, includePaths, protocOptions, log) 197 | if (exitCode != 0) 198 | sys.error(s"protoc returned exit code: ${exitCode}") 199 | 200 | log.info("Compiling protobuf") 201 | generatedTargetDirs.foreach{ dir => 202 | log.info(s"Protoc target directory: ${dir.absolutePath}") 203 | } 204 | 205 | (generatedTargets.flatMap{ot => (ot._1 ** ot._2).get}).toSet 206 | } else { 207 | Set[File]() 208 | } 209 | } 210 | 211 | private[this] def unpack(deps: Seq[File], extractTarget: File, log: Logger): Seq[File] = { 212 | IO.createDirectory(extractTarget) 213 | deps.flatMap { dep => 214 | val seq = IO.unzip(dep, extractTarget, "*.proto").toSeq 215 | if (!seq.isEmpty) log.debug("Extracted " + seq.mkString("\n * ", "\n * ", "")) 216 | seq 217 | } 218 | } 219 | 220 | private[this] def sourceGeneratorTask = 221 | Def.task { 222 | val out = streams.value 223 | val schemas = protobufSources.value.toSet[File].map(_.getAbsoluteFile) 224 | // Include Scala binary version like "_2.11" for cross building. 225 | val cacheFile = out.cacheDirectory / s"protobuf_${scalaBinaryVersion.value}" 226 | val runProtoc = protobufRunProtoc.value 227 | val includePaths = (ProtobufConfig / protobufIncludePaths).value 228 | val options = (ProtobufConfig / protobufProtocOptions).value 229 | val targets = (ProtobufConfig / protobufGeneratedTargets).value 230 | val cachedCompile = FileFunction.cached(cacheFile, inStyle = FilesInfo.lastModified, outStyle = FilesInfo.exists) { (in: Set[File]) => 231 | compile( 232 | protocCommand = runProtoc, 233 | schemas = schemas, 234 | includePaths = includePaths, 235 | protocOptions = options, 236 | generatedTargets = targets, 237 | log = out.log) 238 | } 239 | cachedCompile(schemas).toSeq 240 | } 241 | 242 | private[this] def unpackDependenciesTask = Def.task { 243 | val extractTarget = (ProtobufConfig / protobufExternalIncludePath).value 244 | val extractedFiles = unpack((ProtobufConfig / managedClasspath).value.map(_.data), extractTarget, streams.value.log) 245 | UnpackedDependencies(extractTarget, extractedFiles) 246 | } 247 | 248 | private[this] def packageProtoMappings = 249 | Def.task { 250 | protobufSources.value.map { 251 | case x => (x, x.getName) 252 | } 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /src/main/scala/sbtprotobuf/SbtProtobuf.scala: -------------------------------------------------------------------------------- 1 | package sbtprotobuf 2 | 3 | import java.nio.file.Path 4 | import sbt._ 5 | import sbt.librarymanagement.DependencyFilter 6 | 7 | object SbtProtobuf { 8 | val protocArtifactName = "protoc" 9 | val protocGenGrpcJavaArtifactName = "protoc-gen-grpc-java" 10 | 11 | def protocDependency(v: String): ModuleID = 12 | ("com.google.protobuf" % protocArtifactName % v) 13 | .artifacts(Artifact( 14 | name = protocArtifactName, 15 | `type` = "exe", 16 | extension = "exe", 17 | classifier = detectClassifier, 18 | )) 19 | 20 | def protocGenGrpcJavaDependency(v: String): ModuleID = 21 | ("io.grpc" % protocGenGrpcJavaArtifactName % v) 22 | .artifacts(Artifact( 23 | name = protocGenGrpcJavaArtifactName, 24 | `type` = "exe", 25 | extension = "exe", 26 | classifier = detectClassifier, 27 | )) 28 | 29 | def detectClassifier: String = { 30 | val x86_64 = "x86_64" 31 | val arch = sys.props.get("os.arch") match { 32 | case Some("aarch64") => "aarch_64" 33 | case Some("amd64") => x86_64 34 | case Some(arch) => arch 35 | case _ => x86_64 36 | } 37 | if (scala.util.Properties.isMac){ 38 | s"osx-$arch" 39 | } else if (scala.util.Properties.isWin){ 40 | s"windows-$arch" 41 | } else { 42 | s"linux-$arch" 43 | } 44 | } 45 | 46 | /** 47 | * Set the executable flag to true, and cache it. 48 | */ 49 | def withFileCache(cacheDirectory: Path)(f: () => Path): Path = { 50 | val g = FileFunction.cached( 51 | cacheDirectory.toFile() / "cache", 52 | inStyle = FilesInfo.hash, 53 | outStyle = FilesInfo.exists, 54 | ) { (in: Set[File]) => 55 | val out = cacheDirectory.toFile() / in.head.getName 56 | IO.copyFile(in.head, out) 57 | out.setExecutable(true) 58 | Set(out) 59 | } 60 | g(Set(f().toFile())).head.toPath() 61 | } 62 | 63 | /** 64 | * Extract a file with given name from the given UpdateReport. 65 | */ 66 | def extractFile(ur: UpdateReport, artifactName: String): Path = { 67 | val df: DependencyFilter = 68 | configurationFilter(name = "protobuf-tool") && 69 | artifactFilter(name = artifactName) 70 | ur.matching(df) match { 71 | case Vector(x) => x.toPath() 72 | case xs => sys.error(s"$artifactName was not found: $xs") 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/sbt-test/delete/clear-dir/build.sbt: -------------------------------------------------------------------------------- 1 | enablePlugins(ProtobufPlugin) 2 | 3 | scalaVersion := "2.10.7" 4 | -------------------------------------------------------------------------------- /src/sbt-test/delete/clear-dir/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/delete/clear-dir/src/main/protobuf/test.proto: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | message test{ 4 | required int32 thing = 1; 5 | } 6 | -------------------------------------------------------------------------------- /src/sbt-test/delete/clear-dir/test: -------------------------------------------------------------------------------- 1 | > protobuf:protobufGenerate 2 | $ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test.java 3 | $ delete src/main/protobuf/test.proto 4 | > protobuf:protobufGenerate 5 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test.java 6 | -------------------------------------------------------------------------------- /src/sbt-test/delete/single-file/build.sbt: -------------------------------------------------------------------------------- 1 | enablePlugins(ProtobufPlugin) 2 | 3 | scalaVersion := "2.10.7" 4 | -------------------------------------------------------------------------------- /src/sbt-test/delete/single-file/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/delete/single-file/src/main/protobuf/test.proto: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | message test{ 4 | required int32 thing = 1; 5 | } 6 | -------------------------------------------------------------------------------- /src/sbt-test/delete/single-file/src/main/protobuf/test2.proto: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | message test2{ 4 | required int32 thing = 1; 5 | } 6 | -------------------------------------------------------------------------------- /src/sbt-test/delete/single-file/test: -------------------------------------------------------------------------------- 1 | > protobuf:protobufGenerate 2 | $ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test.java 3 | $ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test2.java 4 | $ delete src/main/protobuf/test.proto 5 | > protobuf:protobufGenerate 6 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test.java 7 | $ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test2.java 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/basic/build.sbt: -------------------------------------------------------------------------------- 1 | enablePlugins(ProtobufPlugin) 2 | 3 | scalaVersion := "2.10.7" 4 | 5 | crossScalaVersions += "2.11.12" 6 | 7 | libraryDependencies += "com.google.protobuf" % "protobuf-java" % (ProtobufConfig / version).value % ProtobufConfig.name 8 | 9 | ProtobufConfig / excludeFilter := "test1.proto" 10 | 11 | (Compile / unmanagedResourceDirectories) += (ProtobufConfig / sourceDirectory).value 12 | 13 | TaskKey[Unit]("checkJar") := { 14 | val jar = (Compile / packageBin).value 15 | IO.withTemporaryDirectory{ dir => 16 | val files = IO.unzip(jar, dir, "*.proto") 17 | val expect = Set("test1.proto", "test2.proto").map(dir / _) 18 | assert(files == expect, s"$files $expect") 19 | } 20 | } 21 | 22 | // https://github.com/sbt/sbt-protobuf/issues/37 23 | compile / mainClass := Some("whatever") 24 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/basic/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/basic/src/main/protobuf/test1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | message test1{ 6 | int32 thing = 1; 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/basic/src/main/protobuf/test2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | // https://github.com/google/protobuf/blob/v3.0.0/src/google/protobuf/timestamp.proto 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | 9 | message test2{ 10 | google.protobuf.Timestamp time = 1; 11 | } 12 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/basic/test: -------------------------------------------------------------------------------- 1 | > compile 2 | 3 | # test for https://github.com/sbt/sbt-protobuf/pull/29 4 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test1.java 5 | -$ exists target/scala-2.10/classes/test/Test1.class 6 | 7 | # https://github.com/sbt/sbt-protobuf/tree/v0.5.0#declaring-dependencies 8 | $ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test2.java 9 | $ exists target/scala-2.10/classes/test/Test2.class 10 | 11 | > clean 12 | 13 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test2.java 14 | 15 | > compile 16 | > ++ 2.11.12 17 | > compile 18 | $ exists target/scala-2.11/src_managed/main/compiled_protobuf/test/Test2.java 19 | 20 | > checkJar 21 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/exclude/build.sbt: -------------------------------------------------------------------------------- 1 | enablePlugins(ProtobufPlugin) 2 | version := "0.1.0-SNAPSHOT" 3 | name := "exclude-test" 4 | scalaVersion := "2.13.13" 5 | 6 | libraryDependencies ++= Seq( 7 | "com.google.protobuf" % "protobuf-java" % (ProtobufConfig / version).value % ProtobufConfig, 8 | ) 9 | 10 | ProtobufConfig / sourceDirectories += (ProtobufConfig / protobufExternalIncludePath).value 11 | 12 | TaskKey[Unit]("checkJar") := { 13 | val jar = (Compile / packageBin).value 14 | IO.withTemporaryDirectory{ dir => 15 | val files = IO.unzip(jar, dir) 16 | val expect = Set(dir / "META-INF" / "MANIFEST.MF") 17 | assert(files == expect, s"""actual = $files, 18 | expected = $expect""") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/exclude/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/exclude/test: -------------------------------------------------------------------------------- 1 | > checkJar 2 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/grpc/A.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | class A { 4 | val stub = GreeterGrpc.newBlockingStub(???) 5 | } -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/grpc/build.sbt: -------------------------------------------------------------------------------- 1 | enablePlugins(ProtobufPlugin) 2 | version := "0.1.0-SNAPSHOT" 3 | name := "grpc" 4 | scalaVersion := "2.13.13" 5 | protobufGrpcEnabled := true 6 | 7 | libraryDependencies ++= Seq( 8 | "javax.annotation" % "javax.annotation-api" % "1.3.2", 9 | "io.grpc" % "grpc-netty" % protobufGrpcVersion.value, 10 | "io.grpc" % "grpc-protobuf" % protobufGrpcVersion.value, 11 | "io.grpc" % "grpc-stub" % protobufGrpcVersion.value, 12 | "com.google.protobuf" % "protobuf-java" % (ProtobufConfig / version).value % ProtobufConfig, 13 | ) 14 | 15 | ProtobufConfig / sourceDirectories += (ProtobufConfig / protobufExternalIncludePath).value 16 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/grpc/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/grpc/src/main/protobuf/greeter.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package example; 4 | 5 | service Greeter { 6 | // Sends a greeting 7 | rpc SayHello (HelloRequest) returns (HelloReply) {} 8 | } 9 | 10 | message HelloRequest { 11 | string name = 1; 12 | } 13 | 14 | message HelloReply { 15 | string message = 1; 16 | } 17 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/grpc/test: -------------------------------------------------------------------------------- 1 | > compile 2 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/multi-project/bar/src/main/protobuf/test2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | import "test1.proto"; 6 | 7 | message Test2{ 8 | Test1 test1 = 1; 9 | } 10 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/multi-project/build.sbt: -------------------------------------------------------------------------------- 1 | val commonSettings = Seq( 2 | scalaVersion := "2.11.12" 3 | ) 4 | 5 | val foo = project.settings( 6 | commonSettings 7 | ).enablePlugins(ProtobufPlugin) 8 | 9 | val bar = project.settings( 10 | commonSettings, 11 | (ProtobufConfig / protobufIncludePaths) += (foo / ProtobufConfig / sourceDirectory).value 12 | ).dependsOn(foo).enablePlugins(ProtobufPlugin) 13 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/multi-project/foo/src/main/protobuf/test1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | message Test1{ 6 | int32 thing = 1; 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/multi-project/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/multi-project/test: -------------------------------------------------------------------------------- 1 | > compile 2 | $ exists bar/target/scala-2.11/src_managed/main/compiled_protobuf/test/Test2OuterClass.java 3 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/build.sbt: -------------------------------------------------------------------------------- 1 | import sbtprotobuf.ProtobufTestPlugin.{Keys => PBT} 2 | 3 | scalaVersion := "2.10.7" 4 | 5 | crossScalaVersions += "2.11.12" 6 | 7 | enablePlugins(ProtobufPlugin, ProtobufTestPlugin) 8 | 9 | (PBT.ProtobufConfig / version) := (ProtobufConfig / version).value 10 | 11 | libraryDependencies += "com.google.protobuf" % "protobuf-java" % (ProtobufConfig / version).value % ProtobufConfig.name 12 | 13 | libraryDependencies += "com.google.protobuf" % "protobuf-java" % (PBT.ProtobufConfig / version).value % PBT.ProtobufConfig.name 14 | 15 | (PBT.ProtobufConfig / PBT.protobufRunProtoc) := (ProtobufConfig / protobufRunProtoc).value 16 | 17 | ProtobufConfig / excludeFilter := "test1.proto" 18 | 19 | PBT.ProtobufConfig / excludeFilter := "test3.proto" 20 | 21 | (Compile / unmanagedResourceDirectories) += (ProtobufConfig / sourceDirectory).value 22 | 23 | (Test / unmanagedResourceDirectories) += (PBT.ProtobufConfig / sourceDirectory).value 24 | 25 | TaskKey[Unit]("checkJar") := { 26 | val compileJar = (Compile / packageBin).value 27 | val testJar = (Test / packageBin).value 28 | 29 | IO.withTemporaryDirectory{ dir => 30 | val files = IO.unzip(compileJar, dir, "*.proto") 31 | val expect = Set("test1.proto", "test2.proto").map(dir / _) 32 | val testfiles = IO.unzip(testJar, dir, "*.proto") 33 | val testexpect = Set("test3.proto", "test4.proto").map(dir / _) 34 | assert(files == expect, s"$files $expect") 35 | assert(testfiles == testexpect, s"$testfiles $testexpect") 36 | } 37 | } 38 | 39 | // https://github.com/sbt/sbt-protobuf/issues/37 40 | compile / mainClass := Some("whatever") 41 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | { 2 | val pluginVersion = System.getProperty("plugin.version") 3 | if(pluginVersion == null) 4 | throw new RuntimeException("""|The system property 'plugin.version' is not defined. 5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) 6 | else addSbtPlugin("com.github.sbt" % "sbt-protobuf" % pluginVersion) 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/src/main/protobuf/test1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | message test1{ 6 | int32 thing = 1; 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/src/main/protobuf/test2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | // https://github.com/google/protobuf/blob/v3.0.0/src/google/protobuf/timestamp.proto 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | 9 | message test2{ 10 | google.protobuf.Timestamp time = 1; 11 | } 12 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/src/test/protobuf/test3.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | message test3{ 6 | int32 thing = 1; 7 | } 8 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/src/test/protobuf/test4.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | // https://github.com/google/protobuf/blob/v3.0.0/src/google/protobuf/timestamp.proto 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | 9 | message test4{ 10 | google.protobuf.Timestamp time = 1; 11 | } 12 | -------------------------------------------------------------------------------- /src/sbt-test/sbt-protobuf/task-scoped/test: -------------------------------------------------------------------------------- 1 | > compile 2 | 3 | # test for https://github.com/sbt/sbt-protobuf/pull/29 4 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test1.java 5 | -$ exists target/scala-2.10/classes/test/Test1.class 6 | 7 | # https://github.com/sbt/sbt-protobuf/tree/v0.5.0#declaring-dependencies 8 | $ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test2.java 9 | $ exists target/scala-2.10/classes/test/Test2.class 10 | 11 | # Ensure task is scoped 12 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test3.java 13 | -$ exists target/scala-2.10/classes/test/Test3.class 14 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test4.java 15 | -$ exists target/scala-2.10/classes/test/Test4.class 16 | 17 | # Ensure that test classes weren't generated yet 18 | -$ exists target/scala-2.10/src_managed/test/compiled_protobuf/test/Test3.java 19 | -$ exists target/scala-2.10/test-classes/test/Test3.class 20 | -$ exists target/scala-2.10/src_managed/test/compiled_protobuf/test/Test4.java 21 | -$ exists target/scala-2.10/test-classes/test/Test4.class 22 | 23 | > clean 24 | 25 | -$ exists target/scala-2.10/src_managed/main/compiled_protobuf/test/Test2.java 26 | 27 | > compile 28 | > ++ 2.11.12 29 | > compile 30 | $ exists target/scala-2.11/src_managed/main/compiled_protobuf/test/Test2.java 31 | 32 | # Ensure test-scoped classes are generated with respect to test-scoped settings 33 | > test 34 | -$ exists target/scala-2.11/src_managed/test/compiled_protobuf/test/Test3.java 35 | -$ exists target/scala-2.11/test-classes/test/Test3.class 36 | $ exists target/scala-2.11/src_managed/test/compiled_protobuf/test/Test4.java 37 | $ exists target/scala-2.11/test-classes/test/Test4.class 38 | 39 | > clean 40 | -$ exists target/scala-2.11/src_managed/test/compiled_protobuf/test/Test4.java 41 | 42 | > compile 43 | > test 44 | 45 | > checkJar 46 | -------------------------------------------------------------------------------- /version.sbt: -------------------------------------------------------------------------------- 1 | // So that publishLocal doesn't continuously create new versions 2 | def versionFmt(out: sbtdynver.GitDescribeOutput): String = { 3 | val snapshotSuffix = 4 | if (out.isSnapshot()) "-SNAPSHOT" 5 | else "" 6 | out.ref.dropPrefix + snapshotSuffix 7 | } 8 | def fallbackVersion(d: java.util.Date): String = s"HEAD-${sbtdynver.DynVer timestamp d}" 9 | ThisBuild / version := dynverGitDescribeOutput.value.mkVersion(versionFmt, fallbackVersion(dynverCurrentDate.value)) 10 | ThisBuild / dynver := { 11 | val d = new java.util.Date 12 | sbtdynver.DynVer.getGitDescribeOutput(d).mkVersion(versionFmt, fallbackVersion(d)) 13 | } 14 | --------------------------------------------------------------------------------