maven

其实 java 里面的确有一些不错的东西,比如说 maven。

和 maven 比较的很多次的另一个工具是 ant,这个基本上沿袭了 make 的思路,但是使用了 XML 语法描述编译等等的依赖关系。个人觉得 XML 的选择是一种失败的搞法,因为不适合人来写。但是也有人觉得不错,因为很多时候 IDE 能够帮助我们生成合理的文件。maven 在此之上提出了一种和 repository 结合的做法,它提供了中心的 repository 供项目使用,这意味着项目所依赖的外部资源可以通过 maven 自动的获得。wikipedia 上将 maven 与 ant 做了一个比较细致的比较,

  • maven 假定项目有一定的“固定结构”,而 ant 并没有类似的假设,这是什么意思呢?也就是说 maven 会认为你的 source code 一般放在 src/ 里面,主要的程序在 src/main 而测试在 sr/test,这更像一个 IDE,它不会问你你要把 source code 放在哪里,而是自动的帮你放在那里了,你不按照它的规定来就会很麻烦;ant 却没有这种严格的假定,虽然很多项目也是这样组织代码的,但是 ant 本身并不限制你一定要这样做
  • maven 藉此假定更注重一些 high level 的项目理念,而 ant 仍然停留在 low-level 上各个 target 的依赖关系上。比如 maven 提供了所谓 life cycle 的概念,帮助开发者能比较清楚的了解这个项目的进度;ant 更倾向让编写人员设定不同的目标,让这些目标彼此依赖,藉此表述某种 high level 的概念。这意味着 ant 的语法可能更加简单,因为只涉及 target 的关系,什么都不懂的人看看也许也能写出 ant 的 build.xml;但是很可能不同的项目表述自己的 high-level 概念通过的依赖关系并不一样,因此很难看懂不懂项目直接这些概念的异同。但是对 maven 却不一样,因为它提供的 life cycle 在不同 project 上是一致或者类似的,这样对 maven 有一定了解的人能够很快了解其他的项目的 high-level 概念,尽管新手可能不是太理解这些东西
  • 从这个角度来说 maven 更适合比如与 IDE 整合,它牺牲了一定的“自由度”,换来的是 consistency,降低了不同 project 之间的学习成本

与 maven 类似的衍生工具还有 gradle(首页见此,没有使用 XML 而是用了一种 DSL groovy 来描述项目),scala 的 sbt(首页见此,也是用自己的 DSL)似乎也用了 maven 的 repository。下面我们来看一个简单的例子。我们只需要简单的执行一下

mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

就能生成我们需要的一些结构,并且可以到此目录里面 mvn package 并执行了。由此看来,我们创建一个项目首先可以选择一个合理的 archetype,之后有些什么就是靠编辑对应的 pom.xml 了。其他的一些细节可以参看这里

maven 的 archetype

archetype 的目的就是为某种类型的项目生成一个框架,这使得某些公司可以为自己的规范形成合适的初始态,帮助程序员 follow 规范,常用的一些 archetype 包括

  • maven-archetype-archetype 用来开发 archetype 的 archetype
  • maven-archetype-j2ee-simple 用来开发 j2ee 程序
  • maven-archetype-mojo 开发 maven plugin 的 sample
  • maven-archetype-plugin(-site) 开发 maven plugin (site) 的 archetype
  • maven-archetype-portlet 开发 JSR-268
  • maven-archetype-quickstart 和 maven-archetype-simple 一般通用的 archetype
  • maven-archetype-site(-simple) 开发 site
  • maven-archetype-webapp 开发 web app

从合适的 archetype 出发能减少额外的配置。

maven 的 pom.xml

项目的 pom.xml 继承自一个公共的 super pom.xml,这个 pom 里面比较重要的有

  • modelVersion、name 标记一些常量
  • repositories 表示使用的仓库,pluginsRepositories 表示 plugin 的仓库
  • build 里面是关于源文件路径、测试文件路径、编译出来的目录

下面是个简单的例子

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

如果我们需要产生层次结构,可以用 parent,如

<project>
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-module</artifactId>
  <version>1</version>
</project>

如果并非子目录关系,我们可以用 relativePath,如果我们希望 module 被整合进原先的 project 可以用 modules 将其包括。另外可以用 $ 和花括号表示某些变量的值,常用的有 basedir,还可以在 properties 里面设定一些值。下面是依赖关系的例子,

<project>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

通过 plugin 我们可以增强 mvn 的功能,下面是一个使用 plugin 的例子

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.0.2</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

是一些官方的 plugin,还是很不错的一个 set。

使用 maven 管理 C/C++

这个可以使用 maven-nar-plugin。看起来也沿袭了 maven 那套 repository 的东西,挺有意思,不清楚与现有的 auto-make、cmake 等是否有重大区别。

——————
Now therefore swear to me here by God that you will not deal falsely with me, nor with my son, nor with my son’s son: but according to the kindness that I have done to you, you shall do to me, and to the land wherein you have sojourned.

maven