Maven自动编译Protocol Buffers

来源:互联网 发布:linux c 高并发服务器 编辑:程序博客网 时间:2024/06/18 05:11

本文主要解决maven自动编译.proto文件的问题

难题

  • 多平台protoc:团队中有人使用mac 有人使用windows开发,编译使用的protoc是二进制程序,根据不同操作系统有不同的版本。
  • 按需编译:有一些模块(module)包含有proto目录,需要编译其中的.proto文件。另一些模块不包含proto目录,不需要编译。
  • 跨模块引用:有一些模块需要引用到其他模块的proto目录。

下载protoc到本地

定义全局属性:保持版本和路径一致

<protobuf.input.directory>${project.basedir}/src/main/proto</protobuf.input.directory><protobuf.output.directory>src/main/gen-java</protobuf.output.directory><protobuf.protoc.path>${settings.localRepository}/protoc</protobuf.protoc.path><protobuf.version>3.2.0</protobuf.version>

引用protobuf-API:编译成的.java文件需要依赖这些库文件

<dependency>    <groupId>com.google.protobuf</groupId>    <artifactId>protobuf-java</artifactId>    <version>${protobuf.version}</version></dependency>

识别系统类型:区分Windows/Linux/OS X 不同系统,区分32/64-bit,识别结果会写入到变量里面

<build>    <extensions>        <!-- provides os.detected.classifier (i.e. linux-x86_64, osx-x86_64) property -->        <extension>            <groupId>kr.motd.maven</groupId>            <artifactId>os-maven-plugin</artifactId>            <version>1.4.1.Final</version>        </extension>    </extensions></build>

自动下载protoc到本地目录

<!-- copy protoc binary into build directory --><plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-dependency-plugin</artifactId>    <version>2.10</version>    <executions>        <execution>            <id>copy-protoc</id>            <phase>generate-sources</phase>            <goals>                <goal>copy</goal>            </goals>            <configuration>                <artifactItems>                    <artifactItem>                        <groupId>com.google.protobuf</groupId>                        <artifactId>protoc</artifactId>                        <version>${protobuf.version}</version>                        <classifier>${os.detected.classifier}</classifier>                        <type>exe</type>                        <overWrite>false</overWrite>                        <outputDirectory>${protobuf.protoc.path}</outputDirectory>                    </artifactItem>                </artifactItems>            </configuration>        </execution>    </executions></plugin>

编译.proto文件

  • 使用maven-antrun的if语法,可以判断目录是否存在。如果目录存在,才开始编译工作。
  • 在命令行调用protoc文件的时候,可以加入多个-I参数引用多个路径。
  • 这里我们利用maven-antrun的propertyregex 工具,进行字符串替换。需要跨模块引用时,只需覆写protobuf.input.directory属性,多个目录之间用分号间隔。
<propertyregex property="proto.include"        input="${protobuf.input.directory}"        regexp=";"        replace=" -I"        defaultvalue="${protobuf.input.directory}"        global="true" />

注意:
1. 插件依赖: if语法需要依赖插件ant-contrib:ant-contrib
2. 插件依赖: propertyregex工具需要引用 org.apache.ant:ant-apache-regexp
3. propertyregex 在匹配失败(regexp一个都没有匹配到)的时候,不会设置property;因此需要加入defaultvalue 设置成源串。

最后我们写成插件就是这样子:

<plugin>    <artifactId>maven-antrun-plugin</artifactId>    <dependencies>        <dependency>            <groupId>ant-contrib</groupId>            <artifactId>ant-contrib</artifactId>            <version>1.0b3</version>            <exclusions>                <exclusion>                    <groupId>ant</groupId>                    <artifactId>ant</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.apache.ant</groupId>            <artifactId>ant-apache-regexp</artifactId>            <version>1.8.2</version>        </dependency>        <dependency>            <groupId>org.apache.ant</groupId>            <artifactId>ant-nodeps</artifactId>            <version>1.8.1</version>        </dependency>    </dependencies>    <executions>        <execution>            <id>compile-protoc</id>            <phase>generate-sources</phase>            <configuration>                <tasks>                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>                    <available property="isExist" file="src/main/proto" type="dir"/>                    <if>                        <equals arg1="${isExist}" arg2="true"/>                        <then>                            <property name="protoc.filename"                                      value="protoc-${protobuf.version}-${os.detected.classifier}.exe"/>                            <property name="protoc.filepath"                                      value="${protobuf.protoc.path}/${protoc.filename}"/>                            <propertyregex property="proto.include"                                           input="${protobuf.input.directory}"                                           regexp=";"                                           replace=" -I"                                           defaultvalue="${protobuf.input.directory}"                                           global="true" />                            <chmod file="${protoc.filepath}" perm="ugo+rx"/>                            <path id="proto.path">                                <fileset dir="src/main/proto">                                    <include name="**/*.proto"/>                                </fileset>                            </path>                            <mkdir dir="src/main/gen-java"/>                            <pathconvert pathsep=" " property="proto.files" refid="proto.path"/>                            <exec executable="${protoc.filepath}" failonerror="true">                                <arg value="--java_out=${protobuf.output.directory}"/>                                <arg value="-I${proto.include}"/>                                <arg line="${proto.files}"/>                            </exec>                        </then>                    </if>                </tasks>                <sourceRoot>${protobuf.output.directory}</sourceRoot>            </configuration>            <goals>                <goal>run</goal>            </goals>        </execution>    </executions></plugin>

加入到source

把新生成的gen-java目录加入到项目的source集合中,一起参与编译。

<!-- add generated proto buffer classes into the package --><plugin>    <groupId>org.codehaus.mojo</groupId>    <artifactId>build-helper-maven-plugin</artifactId>    <version>1.7</version>    <executions>        <execution>            <id>add-classes</id>            <phase>generate-sources</phase>            <goals>                <goal>add-source</goal>            </goals>            <configuration>                <sources>                    <source>${protobuf.output.directory}</source>                </sources>            </configuration>        </execution>    </executions></plugin>

解决protobuf-API版本冲突

有的时候,我们会遇到protobuf版本冲突。
比如,我们的工程用到protobuf3.2版本,而引用到的一些库用到了protobuf 2.5版本。两个版本的一些api冲突,可能造成意想不到的问题。我们可以利用shade插件,把protobuf-API全部替换成私有的包名,避免命名冲突。

<!--  shade protobuf to avoid version conflicts --><plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-shade-plugin</artifactId>    <version>2.4.2</version>    <executions>        <execution>            <phase>package</phase>            <goals>                <goal>shade</goal>            </goals>            <configuration>                <relocations>                    <relocation>                        <pattern>com.google.protobuf</pattern>                        <shadedPattern>${project.groupId}.${project.artifactId}.shaded.protobuf</shadedPattern>                    </relocation>                </relocations>            </configuration>        </execution>    </executions></plugin>

在项目中,需要把

import com.google.protobuf.*;

替换成

import groupId.artifactId.shaded.protobuf.*;

参考:Compiling Protocol Buffers Sources in Maven

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 诚薪贷 什么是薪易贷 帮友贷公司 薪酬排行榜 薪酬制度 薪酬设计 医生薪酬 宽带薪酬 薪酬专员 毕业生薪酬排行榜 应付职工薪酬属于什么科目 薪酬结构设计 融创薪酬等级表 应付职工薪酬明细科目 合伙人薪酬及利润分配 薪酬管理制度 高校薪酬排行榜 中建七局薪酬标准2018 职工薪酬包括哪些内容 职工薪酬会计分录 天职国际薪酬表 湖南自考薪酬管理 薪酬福利管理 薪酬管理的原则 薪酬管理论文 薪酬管理名词解释 上市公司员工薪酬标准 2018京东员工级别和薪酬表一览 恒大地产2018年薪酬等级表 总经理助理一般什么薪酬水平 京东员工级别和薪酬2018 材料学就业前景及薪酬 薪金卡 信诚薪金宝 遇女薪金 薪金卡好还是储蓄卡好 平安普惠薪金贷 薪金卡和普通银行卡的区别 薪金贷app下载 工资薪金税前扣除标准