您的位置:首页 > 产品设计 > UI/UE

GradleUserGuide中文版 16)Ant插件 17)Logging 18)Daemon 19)Plugins

2016-05-05 12:33 465 查看

16.3 Ant的属性与引用

有许多方法可以设定 Ant 属性, 可以通过Ant任务使用属性. 可以直接在
AntBuilder
的实例设置属性。Ant的属性也可以作为一个可改变的
Map
. 也可以使用Ant的任务属性:

16.13.设置Ant属性

build.gradle

ant.buildDir = buildDir
ant.properties.buildDir = buildDir
ant.properties['buildDir'] = buildDir
ant.property(name: 'buildDir', location: buildDir)


build.xml

<echo>buildDir = ${buildDir}</echo>


许多任务会在执行时设置属性.下面有几种方法来获取属性值,可以直接从
AntBuilder
实例获得属性, 如下所示, ant的属性仍然是作为一个
map
:

16.14.获取Ant属性

build.xml

<property name="antProp" value="a property defined in an Ant build"/>


build.gradle

println ant.antProp
println ant.properties.antProp
println ant.properties['antProp']


设置一个ant引用的方法:

16.15.设置一个Ant引用

build.gradle

ant.path(id: 'classpath', location: 'libs')
ant.references.classpath = ant.path(location: 'libs')
ant.references['classpath'] = ant.path(location: 'libs')


build.xml

<path refid="classpath"/>


获取Ant引用的方法:

16.16. 获取一个Ant引用

build.xml

<path id="antPath" location="libs"/>


build.gradle

println ant.references.antPath
println ant.references['antPath']


16.4 API

Ant 集成是由 AntBuilder 提供的

17 Logging

Log 是构建的主要”UI”工具. 如果日志太过冗长, 那么真正的警告和问题会隐藏其中, 另一方面, 如果出错了, 你又需要搞清楚相关错误信息.

Gradle 提供了6个等级的 log, 如表17.1. Logs Level所示. 列出了常见的, 还有两个是 Gradle 特定级别的日志, 被称为QUIET和LIFECYCLE.

后者是默认的, 并用于报告生成进度.

表17.1.Logs Level

Level用途
ERROR错误信息
QUIET重要消息信息
WARNING警告信息
LIFECYCLE进度消息信息
INFO信息消息
DEBUG调试信息

17.1 Choosing a log level

可以在命令行中选择如表 17.2.Log 等级命令行选项所示的选项选择不同的日志级别.

如表 17.3.堆栈信息选项中所示的选项来选择堆栈信息.

表17.2.Log 等级命令行选项

选项输出日志等级
no logging optionsLIFECYCLE及更高
-q or –quietQUIET及更高
-i or –infoINFO及更高
LIFECYCLE进度消息信息
-d or –debugDEBUG及更高(所有日志信息)
表 17.3.堆栈信息选项

选项含义
No stacktrace options无堆栈踪迹输出到控制台的情况下生成错误信息(如编译错误) , 仅在内部异常时打印堆栈信息.如果选择DEBUG日志等级,总会打印截断堆栈信息
-s or –stacktrace打印截断堆栈信息, 推荐这个而不是full stacktrace , Groovy的full stacktrace非常详细.(由于底层的动态调用机制。然而其中通常不包含代码错误的相关信息)
-S or –full-stacktrace打印全部堆栈信息

17.2 编写自己的日志信息

用于记录构建文件的简单方法是将消息写入标准输出. Gradle可重定向任何东西写入到标准输出到它的log系统作为
QUITE
级别的log.

17.1.使用标准输出写入log信息

build.gradle

println 'A message which is logged at QUIET level'


还提供了一个logger属性来构建脚本,这是Logger的一个实例. 这个接口继承自
SLF4J
接口并且加入了一F些Gradle的具体方法.

下面是如何在构建脚本中使用此方法的例子:

17.2.写入自己的log信息

build.gradle

logger.error('An error log message.')
logger.warn('A warning log message.')
logger.lifecycle('A lifecycle info log message.')
logger.info('An info log message.')
logger.debug('A debug log message.')
logger.trace('A trace log message.')


还可以在构建中将其他类直接挂接到Gradle的log系统中(例如
buildSrc
目录下的类).只使用
SLF4J logger
, 使用这个
logger
的方式与构建脚本提供的
logger
方式相同.

17.3.使用SLF4J写入log信息

build.gradle

import org.slf4j.Logger
import org.slf4j.LoggerFactory

Logger slf4jLogger = LoggerFactory.getLogger('some-logger')
slf4jLogger.info('An info log message logged using SLF4j')


17.3 从外部工具和库记录日志

在内部, Gradle 使用 Ant 和 lvy , 都有自己的 log 系统, Gradle 重定向日志输出到 Gradle 日志系统. 除了Ant/lvy的
TRACE
级别的日志, 映射到Gradle的
DEBUG
级别, 其余的都会有一个1:1的映射从 Ant/lvy 的日志等级到 Gradle 的日志等级. 这

意味着默认的 Gradle 日志级别将不会显示任何的 Ant /lvy 的输出, 除非它是一个错误或警告.

有许多工具仍然使用标准输出记录,默认的, Gradle将标准输出重定向到
QUIET
的日志级别和标准错误的
ERROR
级别. 该行为是可配置的. 该项目对象提供了一个LoggerManager, 当对构建脚本进行评估的时候, 允许改变标准输出或错误重定向的日志级别。

17.4.配置标准输出捕获

build.gradle

logging.captureStandardOutput LogLevel.INFO
println 'A message which is logged at INFO level'


任务同样提供了LoggingManager去更改任务执行过程中的标准输出或错误日志级别。

17.5.为任务配置标准输出捕获

build.gradle

task logInfo {
logging.captureStandardOutput LogLevel.INFO
doFirst {
println 'A task message which is logged at INFO level'
}
}


Gradle同样提供了
Java Util Logging
,
Jakarta Commons Logging
Log4j logging
的集成工具.

使用这些工具包编写的构建的类的记录的任何日志消息都将被重定向到Gradle的日志记录系统。

17.4 改变Gradle的记录内容

可以用自己的内容取代大部分UI记录. e.g. 如果想以某种方式定制UI, 如:记录更多或更少的信息,或更改log的格式. 可以使用Gradle.useLogger()方法替换日志.

可从一个构建脚本或初始化脚本,或通过嵌入API替换.

注意,这会完全禁用Gradle的默认输出.

下面的初始化脚本改变任务执行和完成构建后日志的输出.

例 17.6.定制Gradle logs

init.gradle

useLogger(new CustomEventLogger())

class CustomEventLogger extends BuildAdapter implements TaskExecutionListener {

public void beforeExecute(Task task) {
println "[$task.name]"
}

public void afterExecute(Task task, TaskState state) {
println()
}

public void buildFinished(BuildResult result) {
println 'build completed'
if (result.failure != null) {
result.failure.printStackTrace()
}
}
}


输出

> gradle -I init.gradle build

[compile]

compiling source

[testCompile]

compiling test source

[test]

running unit tests

[build]

build completed

你的
logger
可以实现下面列出的任何监听器接口. 仅当它实现接口时被替换, 其他接口保持不变。

可以在Section 56.6, “Responding to the lifecycle in the build script”中找到更多相关信息.

BuildListener

ProjectEvaluationListener

TaskExecutionGraphListener

TaskExecutionListener

TaskActionListener

18 The Gradle Daemon

18.1 什么是 Gradle 的守护进程

守护进程是一个运行后台进程, 非交互式用户直接控制的在计算机程序

Gradle 守护进程是一个后台进程, 它运行着繁重的任务, 然后在构建等待下一次任务之间保持自身存在. 这使得数据和代码在下一次构建前已经准备好, 并存入内存中. 这显著的提高了后续构建的性能. 启用Gradle守护进程是一种节约构建时间的廉价方式.

强烈建议在所有开发机器上启用Gradle的守护进程. 但是不推荐在持续集成和构建服务器环境下启用守护进程(参见 Section 18.3, “When should I not use the Gradle Daemon?”).

Gradle自动管理守护进程.如果构建环境配置为利用后台程序, 如果在没有可用守护进程, 就会自动启动一个守护进程, 或者使用现有的空闲的兼容守护进程.

如果一个守护进程在3个小时内没有使用, 它将会自我终结. 一旦配置开发环境为使用的守护进程, 守护进程通常是隐形的, 容易被遗忘的.

18.2 管理和配置

18.2.1 如何启动Gradle的守护进程

在使用Gradle命令行接口时,
--daemon
--no-daemon
命令行选项调用在单个构建时选择启用或禁用后台守护进程. 通常, 允许后台守护进程在一个环境中(例如一个用户账户)更为方便, 可以使所有构建使用守护进程, 而不需要记住
--daemon
开关.

有两种推荐的方式使守护进程持续与环境:

1. 通过环境变量 - 给
GRADLE_OPTS
环境变量添加
-Dorg.gradle.daemon=true
标识

2. 通过属性文件 - 给
<<GRADLE_USER_HOME>>/gradle.properties
文件添加
org.gradle.daemon=true


注意:
<<GRADLE_USER_HOME>>
默认为
<<USER_HOME>>/.gradle
,
<<USER_HOME>>为当前用户home目录
,这个位置可以通过
-g
-gradle-user-home
命令行选项,以及由
GRADLE_USER_HOME
环境变量
org.gradle.user.home
JVM系统属性配置。

这两种方法有同样的效果, 使用哪一个是由个人喜好. 大多数Gradle用户选择第二个方式,给gradle.properties并添加条目.

在Windows中,该命令将使当前用户启用守护:

(if not exist "%HOMEPATH%/.gradle" mkdir "%HOMEPATH%/.gradle") && (echo foo >> "%HOMEPATH%/.gradle/gradle.properties")


在类Unix操作系统,以下的Bash shell命令将使当前用户启用守护进程:

touch ~/.gradle/gradle.properties && echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties


一旦以这种方式在构建环境中启用了守护进程,所有的构建将隐含一个守护进程.

18.2.2 如何禁用Gradle的守护进程

一般Gradle守护进程默认不启用. 然而,一旦它被启用, 有时希望对某些项目或某些构建禁用守护进程.

--no-daemon
命令行选项可用于强制守护进程不能用于该构建. 这很少使用, 但是在调试具有一定的构建或Gradle插件问题时, 有时会很有用.在构建环境中,此命令行选项具有最高优先级.

18.2.3 怎样抑制“please consider using the Gradle Daemon”消息

Gradle可能会在构建结束时发出建议您使用Gradle守护进程的末尾警告. 为了避免这个警告, 可以通过上述的这些方法使用守护进程, 或者明确禁用守护进程. 可以通过上述的
--no daemon
的命令行选项明确禁用守护进程,或使用上述的
org.gradle.deamon
的值设置为
false
代替
true
.

因为不建议在持续集成构建中使用守护进程, 如果
CI
环境变量已存在, Gradle不会发出此消息.

18.2.4 为什么会在机器上出现不只一个守护进程

有几个原因Gradle会创建一个新的守护进程代替使用一个已存在的守护进程. 如果守护进程没有闲置,* 兼容*, 则会启动一个新的守护进程.

空闲的守护进程是当前未执行构建或做其他有用的工作.

兼容的守护进程是一个可以(或者可以达到)满足要求的编译环境的要求。Java安装程序运行的构建是构建环境方面的一个例子。构建运行时所需的JVM系统属性是另一个例子。

一个已经运行的Java进程可能不能满足所需的构建环境的某些方面。如果守护进程由Java7启动,但要求的环境要求为Java8, 则守护进程是不兼容的,必须另外启动。

再者,在运行的JVM不能改变一个运行时的某些性能。如内存分配(如-Xmx1024m),默认文本编码运行的JVM中,默认的语言环境,等等一个JVM不能改变的运行环境。

“Required build environment”通常在构建客户端 (如Gradle命令行, IDE等)方面隐含构建环境, 并明确通过命令行选项设置. 参见Chapter 20,The Build Environment有关如何指定和控制构建环境的详细信息.

以下JVM系统属性是有效不变的. 如果需求编译环境需要这些属性, 不同的守护进程JVM在下列属性中有不同的值时, 守护进程不兼容.

+ file.encoding

+ user.language

+ user.country

+ user.variant

+ com.sun.management.jmxremote

下列JVM属性,通过启动参数控制,也是有效不变的. 在需求构建环境和守护进程环境的对应属性必须按顺序完全匹配, 才可兼容.

+ 最大堆大小(即 -Xmx JVM参数)

+ 最小堆大小(即 -Xms JVM参数)

+ 引导类路径(即 -Xbootclasspath JVM参数)

+ “assertion”状态(即 -ea 参数)

所需的Gradle版本是需求构建环境的另一个方面. 守护进程被耦合到特定Gradle运行时, 多个正在运行的守护进程产生的原因是使用使用不同版本的Gradle会在会话过程中处理多个项目.

18.2.5 守护进程占用多大内存并且能不能给它更大的内存?

如果需求构建环境没有指定最大堆内存, 守护进程会使用多达1G的堆内存. 它将会使用默认的JVM的最小堆内存. 1G内存足够应付大多数构建. 有数百个子项的构建, 大量配置或者源码需求, 或者要求有更好的表现, 则需要更多内存.

为了提高守护进程可以使用的内存,指定相应的标志作为需求构建环境的一部分, 请参见Chapter 20. The Build Environment的详细信息.

18.2.6 如何停止守护进程

守护进程会在闲置3小时后自动终止. 如果想在这之前停止守护进程, 也可以通过操作系统运行
gradle --stop
命令终止后台进程.
--stop
选项会要求所有运行相同版本的守护进程终止.

18.2.7 守护进程何时会出错

许多工程设计已经加入守护进程使得守护进程在日常的开发中变得更加健壮, 透明. 无论如何, 守护进程偶尔也会损坏或者枯竭.

一个Gradle构建执行源自多个来源的任意代码. 即使Gradle本身与守护进程的设计是经过严格的测试的, 但是用户的构建脚本, 或第三方插件可以通过诸如内存泄露, 或腐化全局声明等缺陷来动摇守护进程.

另外, 也可以通过构建时进行不正确的资源释放, 也可能会动摇守护进程(构建环境正常). 在在Microsoft Windows下是一个特别尖锐的问题, 在程序读写文件后关闭失败的处理是非常随意的.

如果出现守护进程不稳定情况, 可以简单的终止. 回顾一下
--no-daemon
的选项可以用于构建阻止使用守护进程, 这对于检验一个问题的罪魁祸首是不是守护进程很有帮助.

18.3 什么时候不使用Gradle守护进程

建议在开发环境中使用Gradle的守护进程, 不建议在持续集成环境和构建服务器环境中使用守护进程.

守护进程可以更快的构建, 这对于一个正坐在椅子前构建项目的人来说非常重要. 对于CI构建来说, 稳定性和可预见性是最重要的. 为每个构建运行时用一个新的, 完全孤立于以前的版本的程序, 更加可靠。

18.4 工具和集成开发环境

Gradle工具API(参见Chapter.65.Embedding Gradle), 用于IDEs和其他工具整合Gradle,总是使用Gradle守护进程执行构建. 如果你是从IDE内部执行构建, 那么是在使用守护进程, 而且不需要在环境中允许Gradle守护进程.

但是,除非已明确启用的Gradle守护进程在环境中, 你在命令行中的构建不会使用Gradle守护进程。

18.5 守护进程如何使构建速度更快

Gradle守护进程是一个常驻构建进程. 在两个构建之间的空闲期间会等待着下次构建. 与每个构建加载Gradle到内存相比, 对于多个构建只需要加载一次Gradle到内存具有明显的好处. 这本身就是对性能的显著优化, 但是不止这些.

现代JVM的显著优化是运行时代码优化. e.g. 热点(HotSpot)(由Oracle提供并作为OpenJDK的基础的JVM实现)适用于优化运行时代码.

优化是渐进的,而不是瞬间的。也就是说,代码在运行期间逐步优化,这意味着后续版本纯粹是基于这个优化过程变得更快. HotSpot实验表明, 它需要5至10某处构建以优化至稳定. 在一个守护进程的第一个构建和第十之间感知的编译时间的差异可以说是相当巨大的.

守护程序还允许更有效地在内存中缓存整个构建。e.g. 需要构建(如插件,构建脚本)的类可以在内存中进行的构建。同样,Gradle可保持在内存中缓存的构建数据的诸如的任务输入和输出的哈希值,用于增量构建。

18.5.1 未来可能的改进

目前,守护使构建速度更快有效地支持在内存中缓存和由JVM优化使代码更快。在未来的Gradle版本中,守护进程将变得更加聪明,预先完成工作。

e.g. 在编辑完构建脚本后就开始下载依赖生成是将要运行的假设下后立即和新改变或添加的依赖性是必需的。

有许多方式使得在未来的版本的gradle的gradle守护进程。

19 Gradle Plugins

Gradle 的核心为真实世界提供了自动化.

所有的实用特性, 类似编译java源码的能力, 是由插件提供的. 插件添加了新的任务(如:JavaCompile), 域对象(如:SourceSet), 公约(如:Java资源位置是
src/main/java
)以及来自其他插件延伸核心对象和对象。

19.1 插件的作用

应用插件到项目允许插件来扩展项目的能力。它可以做的事情:

* 扩展Gradle模型(如:添加可配置新的DSL元素)

* 按照惯例配置项目(如:添加新的任务或配置合理的默认值)

* 应用特定的配置(如:增加组织库或执行标准)

通过应用插件, 而不是向项目构建脚本添加逻辑, 可以收获很多好处.

应用插件:

* 促进重用和减少维护在多个项目类似的逻辑的开销

* 允许更高程度的模块化,提高综合性和组织

* 封装必要的逻辑,并允许构建脚本尽可能是声明性地

19.2 插件的类型

在Gradle中一般有两种类型的插件,脚本插件和二进制插件.

脚本插件是额外的构建脚本, 它会进一步配置构建,通常实行声明的方式操纵的构建. 尽管可以外部化并且从远程位置访问,它们通常还是会在构建内部中使用.

二进制插件是实现了Plugin接口的类,并且采用编程的方式来操纵构建.二进制插件可以驻留在构建脚本,项目层级内或外部的插件jar.

19.3 应用插件

插件需要声明被应用,通过[Project.apply()](https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:apply(java.util.Map)方法完成.

应用的插件是idempotent, 即相同的插件可以应用多次. 如果插件先前以被应用, 任何后来的应用是安全的, 不会有任何影响的.

19.3.1 脚本插件

21.1. Applying a script plugin

build.gradle

apply from: 'other.gradle'


脚本插件可以从本地文件系统或在远程位置的脚本中应用.文件系统的位置是相对于项目目录, 而远程脚本位置的是由一个
HTTP URL
指定的.多个脚本插件(两种形式之一)可以被应用到给定的构建。

19.3.2 二进制插件

21.2. Applying a binary plugin

build.gradle

apply plugin: 'java'


插件可以使用插件ID应用. 插件的id作为给定的插件的唯一标识符. 核心插件注册一个可以用作插件的id的短名称.

在上述情况下, 可以使用简称
java
的插件以应用JavaPlugin. 社区插件, 一方面会使用一个完全合格的形式的插件id(如
com.github.foo.bar
), 但还是有一些传统的插件可能仍然使用很短的,不合格的格式.

不使用一个插件的id,插件也可以通过简单地指定类来应用插件:

21.3. Applying a binary plugin by type

build.gradle

apply plugin: JavaPlugin


在上面的例子中, JavaPlugin是指JavaPlugin, 此类不是严格需要导入
org.gradle.api.plugins
包中的所有自动导入构建脚本(附录E,现有的IDE支持,以及如何没有它应付).

此外,这是没有必要追加的. class可识别一个类常量,因为它是在Java中。

19.3.2.1 二进制插件的位置

一个插件是一个简单的实现了插件接口的类. Gradle提供的核心插件作为其分布的一部分.

因此, 需要做的仅仅是应用上述的插件. 然而, 非核心二进制插件需要到构建类路径才能应用它们. 这可以以多种方式,包括以下方式实现:

* 定义插件作为构建脚本中内嵌类的声明.

* 定义插件为在项目中buildSrc目录下的一个源文件.(参见Section 62.4, “Build sources in the buildSrc project”)

* 包含来自外部jar定义的构建脚本依赖插件(参见Section 21.4, “Applying plugins with the buildscript block”)

* 包含插件DSL语言组成的插件门户网站(Section 21.5, “Applying plugins with the plugins DSL”)

更多信息参见Chapter 61, Writing Custom Plugins

19.4 使用构建脚本块应用插件

项目可以通过添加向构建脚本中加入插件的类路径然后在应用插件, 添加作为外部JAR文件的二进制插件.

外部jar可以使用
buildscrip{}
块添加到构建脚本类路径就像Section 62.6, “External dependencies for the build script”中描述的一样.

21.4. Applying a plugin with the buildscript block

build.gradle

buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1"
}
}

apply plugin: "com.jfrog.bintray"


—TBC—

—YCR—
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: