为了更好的阅读本文,请先学习有关maven的生命周期、phase、goal相关知识。可移步我的这篇文章:
【精】讲透Maven-- Build Lifecycle, Phases和 Goals
好的,进入正题:今天我们来学一下自定义maven插件。
在hadoop的源码中,有一个module是hadoop-maven-plugins,如下图:
这个模块主要功能是实现了一个自定义的maven插件,用来帮助执行cmake,编译native的代码并打包成静态库和动态库。
因此本文的目标有两点:
① 熟悉hadoop打包native库的整体过程
② 从①的过程中学习如果自定义一个maven plugin
一、Hadoop打包native库的过程
我们如果需要编译hadoop的native本地库时,会执行如下命令:
mvn clean install -Pdist,native -DskipTests -Dmaven.javadoc.skip
注意在-P后面指定了native这个profile。
因此我们找到了hadoop-common这个module下的pom.xml里的native profile,如下图所示:
接下来我们就拆解这个profile标签里的内容。
profile标签里的build表示了要对此profile进行构建。
build标签里面内部包含了一些plugin,表示执行此build过程需要用到的插件。
每个plugin标签里面会有多个execution,每个execution里面的phase标签和goals标签定义了这个插件的此goal需要绑定到build过程的哪个phase,以及一些配置项。
Ok,了解完大概的pom文件标签结构后,我们来看下插件,注意到有个插件名字叫:hadoop-maven-plugins。这个插件是hadoop自己为了打包动态链接库而实现的一个自定义maven插件。
我们在第二章就来学一下这个插件,然后介绍一下如何自定义maven插件。
二、hadoop-maven-plugins && 自定义Maven Plugin
我先把hadoop-common项目的pom.xml种关于使用hadoop-maven-plugins的代码贴出来,后续分析的时候可以回看做对比。
<plugin>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-maven-plugins</artifactId>
<executions>
<execution>
<id>cmake-compile</id>
<phase>compile</phase>
<goals><goal>cmake-compile</goal></goals>
<configuration>
<source>${basedir}/src</source>
<vars>
<GENERATED_JAVAH>${project.build.directory}/native/javah</GENERATED_JAVAH>
<JVM_ARCH_DATA_MODEL>${sun.arch.data.model}</JVM_ARCH_DATA_MODEL>
<REQUIRE_BZIP2>${require.bzip2}</REQUIRE_BZIP2>
<REQUIRE_SNAPPY>${require.snappy}</REQUIRE_SNAPPY>
<REQUIRE_ZSTD>${require.zstd}</REQUIRE_ZSTD>
<CUSTOM_SNAPPY_PREFIX>${snappy.prefix}</CUSTOM_SNAPPY_PREFIX>
<CUSTOM_SNAPPY_LIB>${snappy.lib} </CUSTOM_SNAPPY_LIB>
<CUSTOM_SNAPPY_INCLUDE>${snappy.include} </CUSTOM_SNAPPY_INCLUDE>
<CUSTOM_ZSTD_PREFIX>${zstd.prefix}</CUSTOM_ZSTD_PREFIX>
<CUSTOM_ZSTD_LIB>${zstd.lib} </CUSTOM_ZSTD_LIB>
<CUSTOM_ZSTD_INCLUDE>${zstd.include} </CUSTOM_ZSTD_INCLUDE>
<REQUIRE_ISAL>${require.isal} </REQUIRE_ISAL>
<CUSTOM_ISAL_PREFIX>${isal.prefix} </CUSTOM_ISAL_PREFIX>
<CUSTOM_ISAL_LIB>${isal.lib} </CUSTOM_ISAL_LIB>
<REQUIRE_OPENSSL>${require.openssl} </REQUIRE_OPENSSL>
<CUSTOM_OPENSSL_PREFIX>${openssl.prefix} </CUSTOM_OPENSSL_PREFIX>
<CUSTOM_OPENSSL_LIB>${openssl.lib} </CUSTOM_OPENSSL_LIB>
<CUSTOM_OPENSSL_INCLUDE>${openssl.include} </CUSTOM_OPENSSL_INCLUDE>
<EXTRA_LIBHADOOP_RPATH>${extra.libhadoop.rpath}</EXTRA_LIBHADOOP_RPATH>
</vars>
</configuration>
</execution>
<execution>
<id>test_bulk_crc32</id>
<goals><goal>cmake-test</goal></goals>
<phase>test</phase>
<configuration>
<binary>${project.build.directory}/native/test_bulk_crc32</binary>
<timeout>1200</timeout>
<results>${project.build.directory}/native-results</results>
</configuration>
</execution>
<execution>
<id>erasure_code_test</id>
<goals><goal>cmake-test</goal></goals>
<phase>test</phase>
<configuration>
<binary>${project.build.directory}/native/erasure_code_test</binary>
<timeout>300</timeout>
<results>${project.build.directory}/native-results</results>
<skipIfMissing>true</skipIfMissing>
<env>
<LD_LIBRARY_PATH>${LD_LIBRARY_PATH}:${isal.lib}:${isal.prefix}:/usr/lib</LD_LIBRARY_PATH>
</env>
</configuration>
</execution>
</executions>
</plugin>
maven官网中有关于开发自定义插件的详细介绍,真的非常详细,网址如下:
https://maven.apache.org/guides/plugin/guide-java-plugin-development.html
它会带你自己写一个your first plugin,几分钟就搞定,可以尝试下。
这里我来介绍一下编写Maven插件的基本步骤,然后再去看hadoop的实现。
- 创建 Maven 项目。插件的功能肯定需要编写 Java 类的,所以插件本身就是一个 Maven 项目。当然,相对于以前研究的 Maven 项目,插件项目有它的特殊点:packaging 必须是 maven-plugin 类型,可以通过 maven-archetype-plugin 快速创建一个 Maven 插件项目。
- 编写插件目标。每个插件都至少包含一个goal,每个goal对应一个独立的 Java 类。这里把这种类叫 Mojo 类(对象)。Mojo 类必须继承 AbstractMojo 父类。
- 设置目标的配置点。大部分 Maven 件和它的目标都是可以配置的。根据需要,可以在编写 Mojo 的时候给它设置好可以配置的参数。
- 编写逻辑代码,实现目标功能。用 Java 代码实现插件的功能。
- 处理错误和日志。当 Mojo 运行的时候发生异常时,需要根据情况控制 Maven 的运行状况,并且用代码实现必要的日志输出,为用户提供必要的提示信息。
- 测试插件。编写测试案例,绑定(或命令行)执行插件。
好,我们直接来看Hadoop怎么实现的。
我们用了cmake-compile这个goal(可参见上面的pom.xml代码)。
<goals><goal>cmake-compile</goal></goals>
所以找到CompileMojo类:
简单的几个注解就搞定。
Map类型的变量也支持,例如:
在pom.xml里就对应这些值:
这是如何传递个性化参数。那执行插件的入口在哪呢? 答案是execute方法。自定义的插件所有的phase都要实现Mojo接口,Mojo接口里有execute方法,是插件的执行入口。如下图所示:
具体到hadoop的CompileMojo类的实现如下:
runCMake方法如下:
当然少不了CMakeList.txt文件(编译C++工程需要用到的,这个需要手动编写)
了解了maven如何自定插件之后,我们以后就能自己开发满足自己项目需求的maven插件了,或者给开源的maven插件提merge request啦!
网友评论