This is an automated email from the ASF dual-hosted git repository. He-Pin pushed a commit to branch fix/maven-protopaths-imports in repository https://gitbox.apache.org/repos/asf/pekko-grpc.git
commit b4167cd98e328e2c57b28f6068a27a22817d5701 Author: 虎鸣 <[email protected]> AuthorDate: Fri Jul 3 04:06:57 2026 +0800 fix: pass all protoPaths as -I import params to protoc in Maven plugin Motivation: When using Maven, only the current protoDir was passed as -I to protoc. This prevented proto files from importing definitions in other configured protoPaths (e.g. unpacked artifact dependencies). sbt and Gradle already supported this use case. Modification: Extract normalize helper and normalizedProtoPaths lazy val. Remove protoDir parameter from executeProtoc and instead pass all normalizedProtoPaths as -I include paths. Update Maven docs to document the artifact dependency workflow. Result: All configured protoPaths are now passed as -I to protoc, enabling proto imports from artifact dependencies in Maven builds. Tests: sbt "maven-plugin / compile" — success References: Fixes akka/akka-grpc#1300, Fixes akka/akka-grpc#686, Refs akka/akka-grpc#1768 --- docs/src/main/paradox/buildtools/maven.md | 51 ++++++++++++++++++++-- .../pekko/grpc/maven/AbstractGenerateMojo.scala | 37 +++++++++------- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/docs/src/main/paradox/buildtools/maven.md b/docs/src/main/paradox/buildtools/maven.md index 01b66304..7d9354c2 100644 --- a/docs/src/main/paradox/buildtools/maven.md +++ b/docs/src/main/paradox/buildtools/maven.md @@ -77,10 +77,53 @@ which is a relative path to the project basedir. The below configuration overrid In gRPC it is common to make the version of the protocol you are supporting explicit by duplicating the proto definitions in your project. -When using @ref[sbt](sbt.md) as a build system, we also support loading your -proto definitions from a dependency classpath. This is not yet supported -for Maven and @ref[Gradle](gradle.md). If you are interested in this feature -it is tracked in issue [#152](https://github.com/akka/akka-grpc/issues/152). +When using @ref[sbt](sbt.md) or @ref[Gradle](gradle.md) as a build system, we also support loading your +proto definitions from a dependency classpath. + +For Maven, you can achieve a similar result by using the `maven-dependency-plugin` to unpack the +proto files from a dependency and then adding the unpacked directory as a `protoPath`: + +`pom.xml` +: ```xml + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>unpack-proto</id> + <phase>generate-sources</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>com.example</groupId> + <artifactId>my-protos</artifactId> + <version>1.0.0</version> + <type>jar</type> + <outputDirectory>${project.build.directory}/protos-dep</outputDirectory> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.pekko</groupId> + <artifactId>pekko-grpc-maven-plugin</artifactId> + <version>${pekko.grpc.version}</version> + <configuration> + <protoPaths> + <protoPath>src/main/protobuf</protoPath> + <protoPath>${project.build.directory}/protos-dep</protoPath> + </protoPaths> + </configuration> + </plugin> + ``` + +All configured `protoPaths` are passed as `-I` import parameters to `protoc`, allowing proto files +in your project to import definitions from the unpacked artifact. ## JDK 8 support diff --git a/maven-plugin/src/main/scala/org/apache/pekko/grpc/maven/AbstractGenerateMojo.scala b/maven-plugin/src/main/scala/org/apache/pekko/grpc/maven/AbstractGenerateMojo.scala index 5f8bedb7..ea7c0a06 100644 --- a/maven-plugin/src/main/scala/org/apache/pekko/grpc/maven/AbstractGenerateMojo.scala +++ b/maven-plugin/src/main/scala/org/apache/pekko/grpc/maven/AbstractGenerateMojo.scala @@ -129,21 +129,27 @@ abstract class AbstractGenerateMojo @Inject() (buildContext: BuildContext) exten def addGeneratedSourceRoot(generatedSourcesDir: String): Unit + // https://maven.apache.org/plugin-developers/common-bugs.html#Resolving_Relative_Paths + def normalize(protoPath: String): File = { + val protoFile = new File(protoPath) + if (!protoFile.isAbsolute()) { + new File(project.getBasedir(), protoPath).toPath().normalize().toFile() + } else { + protoFile + } + } + + lazy val normalizedProtoPaths: Seq[File] = { + import scala.jdk.CollectionConverters._ + protoPaths.asScala.map(normalize).toSeq + } + override def execute(): Unit = { val chosenLanguage = parseLanguage(language) var directoryFound = false - protoPaths.forEach { protoPath => - // verify proto dir exists - // https://maven.apache.org/plugin-developers/common-bugs.html#Resolving_Relative_Paths - val protoDir = { - val protoFile = new File(protoPath) - if (!protoFile.isAbsolute()) { - new File(project.getBasedir(), protoPath).toPath().normalize().toFile() - } else { - protoFile - } - } + + normalizedProtoPaths.foreach { protoDir => if (protoDir.exists()) { directoryFound = true // generated sources should be compiled @@ -218,15 +224,16 @@ abstract class AbstractGenerateMojo @Inject() (buildContext: BuildContext) exten private[this] def executeProtoc( protocCommand: Seq[String] => Int, schemas: Set[File], - protoDir: File, protocOptions: Seq[String], targets: Seq[Target]): Int = try { - val incPath = "-I" + protoDir.getCanonicalPath + val protocIncludePaths = normalizedProtoPaths.map { includePath => + "-I" + includePath.getCanonicalPath + } protocbridge.ProtocBridge.execute( ProtocRunner.fromFunction((args, _) => protocCommand(args)), targets, - Seq(incPath) ++ protocOptions ++ schemas.map(_.getCanonicalPath), + protocIncludePaths ++ protocOptions ++ schemas.map(_.getCanonicalPath), artifact => throw new RuntimeException( s"The version of sbt-protoc you are using is incompatible with '${artifact}' code generator. Please update sbt-protoc to a version >= 0.99.33")) @@ -265,7 +272,7 @@ abstract class AbstractGenerateMojo @Inject() (buildContext: BuildContext) exten getLog.info("Compiling protobuf") val (out, err, exitCode) = captureStdOutAndErr { - executeProtoc(protocCommand, schemas, protoDir, protocOptions, generatedTargets) + executeProtoc(protocCommand, schemas, protocOptions, generatedTargets) } if (exitCode != 0) { err.split("\n\r").map(_.trim).map(parseError).foreach { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
