什么是构建
从源码到可交付的产物,一般的过程如下
源码 -> 编译 -> 构建 -> 出包
源码可能是各个组件的源码,各自编译后,组装再编译,生成最终的产物,这期间,可能又各种依赖关系,也会有各种分支关系,在没有各种构建工具之前,可以写自动化脚本,比如shell或者python,去实现构建,但那样的话,自己的维护成本就十分高了
java构建工具
ant
ant是用java编写的开源构建工具,为java项目提供自动化任务,比如编译源代码、运行单元测试、打包jar、生成javadoc,但是ant本身不提供依赖管理,可以和依赖管理器Ivy集成。
一个构建脚本由三个基本元素组成
- 一个project
- 工程,可以包括多个target
- 多个target
- 目标,可以包括多个task,目标与目标之间可以存在依赖
- 可用的task
- 具体的可执行的代码,比如创建目录、执行编译命令
ant的配置构建的是通过xml文件配置的,以下是举例说明,其实不用解释,仅仅通过英文就应该都知道下面这个ant在干什么了吧
1 | |
缺点:
- xml配置麻烦,会导致构建脚本臃肿
- xml对逻辑语句if-else-then之类的支持不好
- 无法知道构建中由多少个类被编译或者多少个task被执行
- 需要Ivy进行依赖管理
maven
“约定优先于配置”
意味着maven会为项目配置和行为提供有意义的默认值
标准目录结构如下

maven基于构建生命周期的思想,每个项目都确切知道有哪些步骤去执行构建、打包和发布应用程序,包括如下功能
- 编译源码
- 运行单元测试和集成测试
- 组件工件
- 将工件部署到本地仓库
- 将工件部署到远程仓库
其实这从上往下的一整个过程,就可以是一个简单的CI流水线

依赖管理
maven会从构建脚本中提取依赖的外部库,会从远程的Maven Central中下载到本地的缓存中,然后就使用本地的缓存。
maven的构建脚本是pom.xml,

缺点:
- 默认的结构和生命周期可能不是项目
- 为maven写插件过于累赘
- 早期版本会自动更新核心插件
总结
通过分析ant和maven的特性,总结出,一个比较完善的构建工具应该具备如下特性
- 具有表达性、声明式、可维护的构建语言
- 标准化的项目布局和生命周期
- 易用和灵活的定制逻辑
- 支持多个项目组成的项目结构
- 支持依赖管理
- 可以很好的兼容ant和maven
- 可扩展和高效
gradle
特性
- 使用groovy语言做DSL
- 具有表达性的语言和强大的API
- 和其他构建工具的集成
- 社区驱动和公司支持
- 可扩展
- 鲁棒和强大的依赖管理
- 灵活的约定
一个gradle构建脚本,大概如下,每个元素都有一个与java类一对一的映射
1 | |
使用gradle
编写一个build.gradle文件,如下
1 | |
然后在命令行中执行gradle -q hello,就会输出hello,也可以gradle -q h,因为gradle支持task名称缩写
使用gradle -h可以查看gradle支持的选项,这里只说一些常用的
1 | |
简单说
相比我平常更常操作的jenkins pipeline,gradle可以简单的理解成本地版本的jenkinspipeline,二者都是用groovy编写的DSL。