将协议缓冲区集成到Maven2构建中

42
我正在一个已有的、相当基本的Maven 2项目中尝试使用Protocol Buffers。目前,每次需要更新我的生成源时,我都要调用一个shell脚本。显然,这很麻烦,因为我希望在每次构建之前自动生成源代码。希望不需要使用可耻的hackery方法来实现。
因此,我的问题有两个方面:
1. 不太可能:是否有"Maven 2 Protocol Buffers插件"可以自动完成上述功能?有一个Google Code上的分支, 该作者似乎已经尝试实现这样的插件。不幸的是,它未通过代码审查或合并到protobuf主干。因此,该插件的状态是未知的。
2. 可能更现实:如果没有真正的插件,我该如何从我的Maven 2构建中调用protoc?我想我可能能够将现有的shell脚本连接到antrun调用或类似的东西中。
最好分享个人经验。

这是一个7年前的问题,大多数答案已经过时(除了一个)。较新的问题已经链接。例如:https://dev59.com/6lkS5IYBdhLWcg3wECqU 和 http://stackoverflow.com/questions/40575671/automatically-re-generated-source-update-on-edit-in-eclipse-with-maven-m2e - Paul Verest
9个回答

44
您可以在Protocol Buffers存储库中的Protocol Buffers Compiler Maven Plug-In主题以及Protocol Buffers讨论组中找到有关该插件的一些信息。 我的理解是它可用但缺少测试。 您可以尝试使用它。
或者,您可以直接使用antrun插件(从上述主题中剪切片段)。
 <build>
   <plugins>
     <plugin>
       <artifactId>maven-antrun-plugin</artifactId>
       <executions>
         <execution>
           <id>generate-sources</id>
           <phase>generate-sources</phase>
           <configuration>
             <tasks>
               <mkdir dir="target/generated-sources"/>
               <exec executable="protoc">
                 <arg value="--java_out=target/generated-sources"/>
                 <arg value="src/main/protobuf/test.proto"/>
               </exec>
             </tasks>
             <sourceRoot>target/generated-sources</sourceRoot>
           </configuration>
           <goals>
             <goal>run</goal>
           </goals>
         </execution>
       </executions>
     </plugin>
   </plugins>
 </build>

 <dependencies>
   <dependency>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-java</artifactId>
     <version>2.0.3</version>
   </dependency>
 </dependencies>

1
我发现这个答案很满意,包括用于protobuf插件,该插件似乎不受maven插件支持。然而,我建议不要使用sourceRoot,因为它已被弃用(请参见http://maven.apache.org/plugins/maven-antrun-plugin/run-mojo.html#sourceRoot),而是依赖于build-helper-maven-plugin(请参见http://mojo.codehaus.org/build-helper-maven-plugin/usage.html)。这对于使我的协议项目和其他依赖项在m2eclipse中正确运行是必要的。 - Thomas Dufour
@Thomas,你能否在pastie.org上创建一个pom文件,以便不使用sourceRoot? - TJR
4
您还可能想在<exec>标签中添加failonerror选项,以便在proto文件中出现错误时停止构建。即 <exec failonerror="true" executable="protoc"> - George Hawkins
最新版本是2.5.0。要使用当前版本的protoc,您必须使用2.5.0。 - morpheus05
我对Maven还比较陌生,因此这个问题可能有点无意义,但是如果我有很多.proto文件,我是否必须像您在test.proto中所做的那样一个一个地将它们添加到此脚本中?就像如果我有两个proto文件,我应该这样写,对吗? <arg value="target/proto/Empty.proto"/> <arg value="target/proto/ComponentState.proto"/> - user4964330
它对我不起作用,并产生以下结果:[exec] /home/usr/workspace_runtime_x/x.messages/proto/ros/RosTime.proto: 文件未在使用--proto_path(或-I)指定的任何路径中。您必须指定一个包含此文件的--proto_path。请注意,proto_path必须是.proto文件名称的精确前缀--protoc太蠢了,无法确定两个路径(例如绝对和相对)何时等效(这比您想象的更难)。 - Schütze

23

被接受的答案鼓励我使用谷歌提供的插件。我将问题中提到的分支合并到2.2.0源代码的检出中,构建、安装/部署了插件,并能够按以下方式在我的项目中使用它:

  <build>
    <plugins>
      <plugin>
        <groupId>com.google.protobuf.tools</groupId>
        <artifactId>maven-protoc-plugin</artifactId>
        <version>0.0.1</version>
        <executions>
          <execution>
            <id>generate-sources</id>
            <goals>
              <goal>compile</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
              <protoSourceRoot>${basedir}/src/main/protobuf/</protoSourceRoot>
              <includes>
                <param>**/*.proto</param>
              </includes>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <protocExecutable>/usr/local/bin/protoc</protocExecutable>
        </configuration>
      </plugin>
    </plugins>
  </build>

注意:我将插件的版本更改为0.0.1(没有-SNAPSHOT),以便它可以进入我的非快照第三方Nexus存储库。你的情况可能会有所不同。重点是,一旦不再需要费力才能让它运行起来,这个插件就可以使用了。

9
请将该插件发布到Maven Central。此外,是否有一种编程方式可以调用protoc而不是寻找可执行文件?在许多平台上生成protoc非常麻烦,包括Mac OS X。 - inder

21

被接受的解决方案在处理多个.proto文件时无法扩展。我必须自己想出解决方法:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <id>compile-protoc</id>
                    <phase>generate-sources</phase>
                    <configuration>
                        <tasks>
                            <mkdir dir="${generated.sourceDirectory}" />
                            <path id="proto.path">
                                <fileset dir="src/main/proto">
                                    <include name="**/*.proto" />
                                </fileset>
                            </path>
                            <pathconvert pathsep=" " property="proto.files" refid="proto.path" />
                            <exec executable="protoc" failonerror="true">
                                <arg value="--java_out=${generated.sourceDirectory}" />
                                <arg value="-I${project.basedir}/src/main/proto" />
                                <arg line="${proto.files}" />
                            </exec>
                        </tasks>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
</build>

如何指定 protoc.exe 文件的位置。我的构建失败了,因为无法找到 protoc。protoc 是由 PB 2.4.1 依赖项添加到 pon.xml 中提供的吗? - Rajat Gupta
不,protoc是协议缓冲区编译器,需要安装在构建所在的计算机上并包含在该计算机的路径中。有关更多信息,请参阅https://code.google.com/apis/protocolbuffers/docs/proto.html#generating(特别是有关生成类的部分)。 - chrisbunney

10

还有一个由Igor Petruk创建的出色插件叫做protobuf-maven-plugin,该插件现在已经在中央仓库中,并且与Eclipse(建议使用m2e-1.1)非常兼容。


1
Igor的插件文档在这里(http://igor-petruk.github.com/protobuf-maven-plugin/usage.html)。如果您将`.proto`文件放在`src/main/protobuf`中,则会在`target/generated-sources/protobuf`中获得输出。但是,您仍需要在`PATH`上安装`protoc`才能使其正常工作。 - Brad

4
有一个Maven protobuf插件。 https://www.xolstice.org/protobuf-maven-plugin/usage.html 最小配置:
 <plugin>
    <groupId>org.xolstice.maven.plugins</groupId>
    <artifactId>protobuf-maven-plugin</artifactId>
    <version>0.5.0</version>
    <configuration>
      <protocExecutable>/usr/local/bin/protoc</protocExecutable>
    </configuration>
    <executions>
      <execution>
        <goals>
          <goal>compile</goal>
          <goal>test-compile</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

4

我刚刚更新了maven插件,使其与2.2.0版本兼容——更新后的pom文件已附在代码审查bug中。

以下是自行构建插件的说明:

svn co http://protobuf.googlecode.com/svn/branches/maven-plugin/tools/maven-plugin
cd maven-plugin
wget -O pom.xml 'http://protobuf.googlecode.com/issues/attachment?aid=8860476605163151855&name=pom.xml'
mvn install

您可以使用上述的Maven配置。

4

我刚刚尝试了一个非官方但非常新的(v 0.1.7)分支,来自 https://github.com/dtrott/maven-protoc-plugin ,幸运的是它很好用,这要感谢 David Trott。我测试了几个 Maven 模块,其中一个包含 DTO 风格的消息,另一个依赖于它们的服务。我借鉴了 MaxA 在2009年10月16日发布的插件配置,我的 PATH 上有 protoc,然后我添加了

<temporaryProtoFileDirectory>${basedir}/target/temp</temporaryProtoFileDirectory>

紧接在

<protocExecutable>protoc</protocExecutable>.

真正好的是,我所要做的就是在服务模块上声明一个普通的依赖项,指向 DTO 模块。该插件能够通过找到与 DTO 模块一起打包的 proto 文件来解析 proto 文件的依赖关系,将它们提取到临时目录并在为服务生成代码时使用。而且,它聪明地不会在服务模块中打包生成的 DTO 类的第二份副本。


0

我认为使用antrun来调用非Maven步骤是普遍接受的解决方案。

您也可以尝试maven-exec-plugin


我在使用antrun时遇到了两个问题:(1)它的目的是为了方便从Ant迁移或集成。但我既不打算迁移,也不需要集成。因此,在这种情况下使用它几乎会被视为误用。(2)我只是想要生成一个外部操作系统进程。仅为此目的而拉入整个Ant似乎有些过度。在这种情况下,maven-exec-plugin听起来更加轻量级和合适。 - Max A.
我同意这有点过度,但有时它可以提供一种简单的方法来完成非Maven的任务。 - matt b
有趣的是,Google的人使用Maven来构建protobuf的Java部分,所以想要使用一个Maven插件来编译我的.proto源码并没有什么“非Maven”的问题。我相信一旦他们把事情处理好了,这个流程就会变得更加容易。现在真正需要做的就是将这个插件放入Google的存储库或中央存储库中。 - Max A.

0

我从David Trott的插件中fork了出来,现在它可以编译多种语言,这使得它更加实用。请查看github项目这里以及有关将其与maven构建集成的教程这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接