Gradle 需要运行在一个 Java 环境里,因此安装Gradle前需要先安装JDK
安装一个 Java JDK 或者 JRE. 而且 Java 版本必须至少是 6 以上. Gradle 自带 Groovy 库,
所以没必要安装 Groovy. 任何已经安装的 Groovy 会被 Gradle 忽略.
扩充教程
Max OX: 假设您下载好的 Gradle 文件在 /Users/UFreedom/gradle 目录
1. vim ~/.bash_profile2.添加下面内容: export GRADLE_HOME = /Users/UFreedom/gradle export export PATH= PATH: GRADLE_HOME/bin
3.source ~/.brash_profile 实际配置中,您需要将上面的目录换成您的 Gradle 文件在系统中的目录.
我们可以通过在控制台输入 gradle 命令来运行Gradle. 通过 gradle -v 命令来检测Gradle是否已经正确安装. 如果正确安装,会输出Gradle版本信息以及本地的配置环境 ( groovy 和 JVM 版本等). 显示的版本信息应该与您所下载的 gradle 版本信息相匹配. 如:
因此Gradle Wrapper即可认为是对Gradle进行封装,简单的理解(Gradle Wrapper = Gradle + 相关的集成、运行脚本文件)。
Gradle Wrapper的使用与Gradle略微不同,他的指令为:
这里需要说明的是,Gradle Wrapper初始状态是不包含Gradle文件,而是以配置的方式让你可以方便的进行操作。如配置Gradle的下载路径:
distributionUrl = https\://services.gradle.org/distributions/gradle-3.1-all.zip
当第一次执行gradlew命令是,会检查本地是否存在对应的Gradle版本,如果不存在则会先下载对应版本。这个在“Gradle在Android中的应用”中的Gradle版本升级中提到过。
Gradle的安装我们在前面的章节提到过了,用gradle -v确认安装成功就可以继续接下来的工作了。
使用gradle tasks可以看到,Gradle自带的(目前可用的)Task基本都是一些类似帮助使用的。
新建一个Hello Gradle目录(D:\Hello Gradle),然后cmd窗口进入到改目录,先执行gradle init命令,可以看到自动生成Gradle相关的文件即目录,如下:
(.gradle = gradle脚本缓存文件 )
我们可以通过gradle -h命令来查看,在执行task命令时还可以做哪些特定的操作
我们在HelloGradle\build.gradle中添加一下内容:
task compile << {
println 'compiling source'
}
task compileTest(dependsOn: compile) << {
println 'compiling unit tests'
}
task test1(dependsOn: [compile, compileTest]) << {
println 'running unit tests'
}
task dist(dependsOn: [compile, test1]) << {
println 'building the distribution'
}
这里有个重要的概念,就是这个dependsOn,如我们执行compileTest时,会先执行依赖的compile这个Task。这个在任务的定义及使用过程中非常常见且重要。
现在我们看一下执行gradle dist这个任务的结果:
由于每个任务仅会被调用一次,所以调用gradle test test与调用gradle test效果是相同的.
格式: gradle [option…] [task…]
–profile
参数可以收集一些构建期间的信息(如构建时间)并保存到 build/reports/profile 目录下. 并且会以构建时间命名这些文件.
最后,说一个比较重要的点,Gradle执行任务时,可以简化任务名,比如我们的dist任务(Task),就可以使用 gradle di,或者驼峰式的,如执行compileTask:gradle cT
黑窗口(cmd)在交互体验上难免欠缺,所以Gradle也是提供了图形化界面,用gradle -gui启动
如果我们从自己的Gradle项目目录中启动这个图形界面,我们应该会看到任务树。可以看到我们之前定义的4个任务:
就是一个命令的收藏夹。
将命令填入到gradle输入框. 就可以直接执行单个的Gradle命令.
设置界面
该章节,准备用 Gradle 来构建运行 hello world 程序,体会一下不用任何 IDE ,只用 Gradle (构建工具)是咋回事,然后我们再继续核心概念的介绍。 为了方便起见,我们选择JAVA项目而不是Android项目。
由上个章节可以看出,Gradle init的目录结构还不是我们想要的Java的结构,其实也比较好理解,我们知道Gradle是独立存在的,所以要创建Java项目,我们必须借用Java Plugin(关于插件的内容后面将会介绍)。
清空目录下的内容(或新建一个空目录),然后使用命令gradle init –type java-library,这里我们指定了类型为Java,因此初始化完我们可以看到目录结构的变化:
我们可以看到多了一个src目录,以及build.gradle文件的变化(之前的文件是个空内容):
// Apply the java plugin to add support for Java
apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code
dependencies {
// The production code uses the SLF4J logging API at compile time
compile 'org.slf4j:slf4j-api:1.7.21'
// Declare the dependency for your favourite test framework you want to use in your tests.
// TestNG is also supported by the Gradle Test task. Just change the
// testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
// 'test.useTestNG()' to your build script.
testCompile 'junit:junit:4.12'
}
我们可以看到在src/main/java下已经自动生成一个Library.java的文件,暂时不管这个。新建一个Main.java,并让他打印一句“Hello World”,保存后运行gradle build进行编译(构建):
//Main.java
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
可以看到多了一个build目录,该目录下存放的即为gradle构建完产生的Main.class文件、HelloGradle.jar以及一些report文件等。
为了可以正常运行项目,需要在build.gradle里面添加插件application ,并且制定入口(mainClassName),然后执行gradle run即可,结果见下图:
以上步骤,我们完全依靠Gradle(及相关插件)便完成了项目创建、编译、运行的过程。可以看到:
1. Gradle插件非常重要,正如我们之前提到的Gradle的设计理念“Gradle只负责一些最基础的任务,而特性化的功能都交于插件来封装与实现。”
2. 这个过程Gradle做的工作大概有:利用JDK将.java编译(javac)成.class,最终根据指定的入口运行(java).class文件。
3. 当然Gradle还有很多重要的功能,其中非常重要的依赖管理,将在后面进行介绍。
我们可以同过添加gradle.properties文件来给Gradle添加一些附加配置。gradle.properties可以在项目目录下(针对当前项目),或者 gradle user home((window)/Users/”your pc_name”/.gradle)目录下。我们在说到统一依赖管理的时候有提到这个文件,可以利用他进行一些全局性的属性配置。先看几个Gradle自带的属性:
Gradle Daemon
我们可以通过使用Dradle Daemon[‘diːmən]来减少Gradle的启动时间,他是一个后台常驻进程(3个小时不被调用会自动结束),会在你下一次执行builds之前的空闲时间中做一些预处理工作,如缓存项目结构、文件等信息。 Gradel Daemon将在Gradle3.0+的版本中默认开启,也可以在项目的gradle.properties中添加:
org.gradle.daemon = true
Parallel Project Execution
当你项目中有多个子module时,这个配置显得尤为重要,同样可以在项目的gradle.properties中添加:
org.gradle.parallel = true
Configure projects on demand
按需配置(Configuration ondemand)只对任务相关的项目进行配置,这在大型多项目编译过程中非常有用,能够大幅度的减少不必要的配置时间。
附:提高构建速度的配置
# The Gradle daemon aims to improve the startup and execution time of Gradle.
# When set to true the Gradle daemon is to run the build.
#我们可以通过使用Dradle Daemon来减少Gradle的启动时间,他是一个后台常驻进程,会在你下一次执行builds之前的空闲时间中做一些预处理工作,
#如缓存项目结构、文件等信息。Gradel Daemon将在Gradle3.0+的版本中默认开启
org.gradle.daemon=true
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
#http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
#(并行模式)当你项目中有多个子module时,这个配置显得尤为重要
org.gradle.parallel=true
# Enables new incubating mode that makes Gradle selective when configuring projects.
# Only relevant projects are configured which results in faster builds for large multi-projects.
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand
# 按需配置(Configuration ondemand)只对任务相关的项目进行配置,这在大型多项目编译过程中非常有用,能够大幅度的减少不必要的配置时间。
org.gradle.configureondemand=true
另外,还有比较常见的用法,即利用该文件来配置网络代理,如:
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=userid
systemProp.http.proxyPassword=password
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost
我们知道Gradle是在Ant与Maven的基础上优化而来的,而Maven在Ant的基础上进行改进的。对于Ant,他主要是处理打包构建的流程,其用Task进行工作的设计被Gradle继承与完善,但是他不支持依赖管理这一功能,这也是使用Eclipse(采用Ant)时,需要使用第三方包总是需要我们自己手动添加jar包。当然,这章我们主要讲Maven,因为他更接近Gradle,并且我们在上传jar或aar包(至Maven仓库)时,需要采用Maven插件,这就要求我们需要去了解相关的知识。
一个项目所有的配置都放置在 POM 文件中:定义项目的类型、名字,管理依赖关系,定制插件的行为等等(我们可以理解为,POM文件对于Maven就相当于.build文件对于Gradle中。Pom中的配置语言是xml,build中的是Groovy)。一下看一个简单示例:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.mycompany.helloworldgroupId>
<artifactId>helloworldartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>jarpackaging>
<name>helloworldname>
<url>http://maven.apache.orgurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
project>
Maven的习惯是通过 groupID(一般是组织的域名倒写,遵循Java package的命名习惯)+ artifactId(库本身的名称) + version(版本)来定义坐标, packaging用来表示包的类型,如jar或aar等。有了 maven 坐标,我们就可以用它来指定我们的项目所依赖的其他项目,插件,或者父项目。一般 maven 坐标写成如下的格式:
groupId:artifactId:packaging:version
像我们的例子就会写成:
com.mycompany.helloworld: helloworld: jar: 1.0-SNAPSHOT
前面我们说过,maven 坐标能够确定一个项目。换句话说,我们可以用它来解决依赖关系。在 POM 中,依赖关系是在 dependencies 部分中定义的。在上面的 POM 例子中,我们用 dependencies 定义了对于 junit 的依赖:
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
这个例子很简单,但是实际开发中我们会有复杂得多的依赖关系,因为被依赖的 jar 文件会有自己的依赖关系。那么我们是不是需要把那些间接依赖的 jar 文件也都定义在POM中呢?答案是不需要,因为 maven 提供了传递依赖的特性。
所谓传递依赖是指 maven 会检查被依赖的 jar 文件,把它的依赖关系纳入最终解决的依赖关系链中。依赖关系会存在一份POM文件中,在添加(下载)jar包的时候同时会下载POM文件,这样 maven 就能检查 junit 的依赖关系,把它所需要的依赖也包括进来。
在 POM 的 dependencies 部分中,scope 决定了依赖关系的适用范围。我们的例子中 junit 的 scope 是 test,那么它只会在执行 compiler:testCompile and surefire:test 目标的时候才会被加到 classpath 中,在执行 compiler:compile 目标时是拿不到 junit 的。scope 的默认值是 compile,即任何时候都会被包含在 classpath 中,在打包的时候也会被包括进去。
Gradle和Maven在依赖管理上几乎差不多,核心的概念是一样的,只不过Gradle语法更精简,如上面的依赖等价于:testCompile ‘junit:junit:4.12’,并且多了一些更灵活的自定义配置。
maven_vs_gradle
在Maven中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。Maven在某个统一的位置存储所有项目的共享的构件,这个统一的位置,我们就称之为仓库,简单说:仓库就是存放依赖和插件的地方。(Gradle沿用了Maven仓库的使用)
Maven仓库分为两类:本地仓库和远程仓库(在远程仓库中又分成了3种:中央仓库 、 私服 、 其它公共库)
- 本地仓库
本地仓库,顾名思义,就是Maven在本地存储构件的地方。maven的本地仓库,在安装maven后并不会创建,它是在第一次执行maven命令的时候才被创建。maven本地仓库的默认位置:无论是Windows还是Linux,在用户的目录下都有一个.m2/repository/的仓库目录,这就是Maven仓库的默认位置。
远程仓库
这个章节讲Maven仓库,主要是为了介绍Maven远程仓库。
中央仓库
说到远程仓库就先从最核心的中央仓库开始,中央仓库是默认的远程仓库,maven在安装的时候,自带的就是中央仓库的配置。中央仓库包含了绝大多数流行的开源Java(Android)构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java(Android)项目依赖的构件都可以在这里下载到。
在Android Studio中默认采用的中央(Maven)仓库为jcenter,之前默认为mavenCentral(似乎这个名字更直观),简单理解jcenter在效能、使用、安全上都优于mavenCentral这个就行。
私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。我们还可以把一些无法从外部仓库下载到的构件上传到私服上。
Maven私服的 个特性:
当前主流的maven私服:
以上讲完Maven的相关特性后,我们来看看其在Gradle的应用。如,上传构件至Artifactory仓库(对于Artifactory在服务器中配置相关我们这里就不介绍了):
我们知道,在Gradle中,特性功能都是由插件来实现的,因此这个也必然需要我们添加相应的插件。
buildscript {
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.1.1"
}
}
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
//服务端地址
def PUBLICAT_REPO_URL='your_url'
//仓库账号密码
def artifactory_username='username'
def artifactory_password='password'
//定位依赖
//Maven的习惯是通过 groupID(一般是组织的域名倒写,遵循Java package的命名习惯)+ artifactId(库本身的名称) + version(版本)来定义坐标
def ARTIFACT_ID = 'com-example-groupname'
def GROUP_ID = 'com.example.groupname'
def VERSION_NAME = '1.0.0'
现在我们需要利用maven-publish配置我们需要上传的内容
publishing {
publications {
//aar构件配置
aar(MavenPublication) {
groupId GROUP_ID
version = VERSION_NAME
artifactId ARTIFACT_ID
// Tell maven to prepare the generated "* .aar" file for publishing
// 指定我们需要上传的内容:outputs里的*-release.aar文件
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
}
//往pom文件中写入相关依赖(依赖传递)
pom.withXml {
def dependencies = asNode().appendNode('dependencies')
configurations.getByName("_releaseCompile").getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', it.moduleName)
dependency.appendNode('version', it.moduleVersion)
}
}
}
}
我们需要利用com.jfrog.artifactory 插件来指定artifact发布到的库。
artifactory {
//仓库地址
contextUrl = PUBLICAT_REPO_URL
publish {
repository {
//上传至指定的仓库(可以理解为指定目录)
repoKey = 'libs-release-local'
//仓库账号、密码
username = artifactory_username
password = artifactory_password
}
defaults {
// Tell the Artifactory Plugin which artifacts should be published to Artifactory.
publications('aar')
publishArtifacts = true
// Properties to be attached to the published artifacts.
properties = ['qa.level': 'basic', 'dev.team': 'core']
// Publish generated POM files to Artifactory (true by default)
publishPom = true
}
}
}
gradle generatePomFileForAarPublication artifactoryPublish -p *