Bootstrap

ReactNative进阶(十四):初探 Gradle

一、前言

世界中主要有三大构建工具:、和。经过几年的发展,几乎销声匿迹、也日薄西山,而的发展则如日中天。

功能主要分为五点:依赖管理系统、多模块构建、一致的项目结构、一致的构建模型和插件机制。我们可以从这五个方面来分析优于的先进之处。

二、依赖管理系统

为世界引入了一个新的依赖管理系统。在世界,可以用、、组成的(坐标)唯一标识一个依赖。任何基于构建的项目自身也必须定义这三项属性,生成的包可以是包,也可以是包或者包。一个典型的依赖引用如下所示:


    junit
    junit
    4.12
    test


    org.springframework
    spring-test

从上面可以看出当引用一个依赖时,可以省略掉,这样在获取依赖时会选择最新的版本。而存储这些组件的仓库有远程仓库和本地仓库之分。远程仓库可以使用世界公用的仓库,也可以使用自建私有仓库;本地仓库则在本地计算机上。通过安装目录下的文件可以配置本地仓库的路径,以及采用的远程仓库地址。

在设计的时候基本沿用了的这套依赖管理体系。不过它在引用依赖时还是进行了一些改进。首先引用依赖方面变得非常简洁。

dependencies {
    compile 'org.hibernate:hibernate-core:3.6.7.Final'
    testCompile ‘junit:junit:4.+'
}

第二,和对依赖项的有所不同。在世界中,一个依赖项有6种,分别是(默认)、、、、、。而将其简化为了4种:。

那么,如果想在使用类似于的怎么办?别着急,由于语言的强大表现力,我们可以轻松编写代码来实现类似于的概念。

第三,支持动态的版本依赖。在版本号后面使用号的方式可以实现动态的版本管理。

第四,在解决依赖冲突方面的实现机制更加明确。使用和进行依赖管理时都采用的是传递性依赖;而如果多个依赖项指向同一个依赖项的不同版本时就会引起依赖冲突。处理这种依赖关系往往是噩梦一般的存在。而在解决依赖冲突方面相对来说比较明确。

三、多模块构建

在和微服务的浪潮下,将一个项目分解为多个模块已经是很通用的一种方式。在中需要定义作为一组的聚合。在该中可以使用标签来定义一组子模块。不会有什么实际构建产出。而中的配置以及依赖配置都会自动继承给子。

也支持多模块构建。而在的中可以使用和代码块来分别定义里面的配置是应用于所有项目还是子项目。对于子模块的定义是放置在文件中的。在的设计当中,每个模块都是的对象实例。而在parent 中通过或可以对这些对象进行各种操作。这无疑比要灵活的多。

比如在的中有以下代码:

allprojects {
    task hello << { task -> println "I'm $task.project.name" }
}

执行命令会依次打印出以及各个的项目名称。这种强大的能力能让对各个模块具有更强的定制化。

四、一致的项目结构

在时代,大家创建项目目录时比较随意,然后通过配置指定哪些属于,那些属于等。而在设计之初的理念就是(约定大于配置)。其制定了一套项目目录结构作为标准的项目结构。

也沿用了这一标准的目录结构。如果在项目中使用了标准的项目结构,那么在中也无需进行多余的配置,只需在文件中包含,系统会自动识别、、等相应资源。不过作为上的构建工具,也同时支持、等源代码的构建,甚至支持、、语言的混合构建。虽然通过一些插件(比如)也能达到相同目的,但配置方面显然要更优雅一些。

五、一致的构建模型

为了解决中对项目构建活动缺乏标准化的问题,特意设置了标准的项目构建周期,其默认的构建周期如下所示:


  validate
  initialize
  generate-sources
  process-sources
  generate-resources
  process-resources
  compile
  process-classes
  generate-test-sources
  process-test-sources
  generate-test-resources
  process-test-resources
  test-compile
  process-test-classes
  test
  prepare-package
  package
  pre-integration-test
  integration-test
  post-integration-test
  verify
  install
  deploy

而这种构建周期也是最为人诟病的地方。因为将项目的构建周期限制的太死,你无法在构建周期中添加新的,只能将插件绑定到已有的上。而现在项目的构建过程变得越来越复杂,而且多样化,显然对这种复杂度缺少足够的应变能力。

比如你想在项目构建过程中进行一项压缩所有的任务,那么就要绑定到现有的某个上,而显然貌似放在哪个都不太合适。而且这些都是串行的,整个执行下来是一条线,这也限制了的构建效率。而在构建模型上则非常灵活。在世界里可以轻松创建一个task,并随时通过语法建立与已有task的依赖关系。甚至对于项目的构建来说,是通过名为的插件来包含了一个对项目的构建周期,这等于本身直接与项目构建周期是解耦的。

六、插件机制

和设计时都采用了插件机制。但显然更胜一筹。主要原因在于是基于进行配置。所以其配置语法太受限于。即使实现很小的功能都需要设计一个插件,建立其与配置的关联。比如想在中执行一条命令,其配置如下:


  org.codehaus.mojo
  exec-maven-plugin
  1.2
  
    
      drop DB => db_name
      pre-integration-test
      
        exec
      
      
        curl
        
          -s
          -S
          -X
          DELETE
          http://${db.server}:${db.port}/db_name
        
      
    
  

而在中则一切变得非常简单。

task dropDB(type: Exec) {
 commandLine ‘curl’,’-s’,’s’,’-x’,’DELETE’,"http://${db.server}:{db.port}/db_name"
}

在创建自定义插件方面,和的机制都差不多,都是继承自插件基类,然后实现要求的方法。

从以上五个方面可以看出和的主要差异。的设计核心被更加发扬光大,而的配置即代码又超越了。

在中任何配置都可以作为代码被执行的,也可以随时使用已有的脚本(是中的一等公民)、、来辅助完成构建任务的编写。

这种采用本身语言实现的对本身语言项目进行构建管理的例子比比皆是。比如和、和、和…..而之所以使用语言实现,是因为比语言更具表现力,其语法特性更丰富,又兼具函数式的特点。这几年兴起的语言(比如)都属于强类型的语言,兼具面向对象和函数式的特点。

另外,的命令行也比的要强大的多。

七、拓展阅读