【精】聊聊Hadoop自定义的maven插件

为了更好的阅读本文,请先学习有关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啦!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容