gradle jar 修改 output 路径_构建Gradle项目

8e439085b097df8a7615ee835b2fecd9.png

创建Gradle项目(demo2 --> example1)

  • 创建目录
❯ mkdir example1
❯ cd example1
  • 初始化一个Gradle项目,使用gradle的init命令
❯ gradle init
Starting a Gradle Daemon (subsequent builds will be faster)
​
​
BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed
  • 初始化后的项目结构
├── build.gradle   // 用于配置当前项目的Gradle构建脚本
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar  // gradlew 的可执行JAR包
│       └── gradle-wrapper.properties  // gradlew 的配置属性
├── gradlew  // 基于 unix 的系统的 Gradlew 脚本
├── gradlew.bat  // 基于 windows 的系统的 Gradlew 脚本
└── settings.gradle  // 用于配置 Gradle 构建的 Gradle 设置脚本

创建一个Task

在 Gradle 中定义 Task 的时候,可以指定更多的参数,如下所示:

参数名含义默认值nametask的名字必须指定,不能为空typetask的父类默认值为org.gradle.api.DefaultTask,类型有copy、jar、Delete 等等 可以参考Doc文档overwrite是否替换已经存在的同名taskfalsegrouptask所属的分组名nulldescriptiontask的描述nulldependsOntask依赖的task集合无constructorArgs构造函数参数无

  • 在项目中新建src目录,创建一个myfile.txt的文件
mkdir src
echo "Hello,world" >> src/myfile.txt
  • 在build.gradle文件中,写入以下代码:
task copy(type: Copy, group: "Custom", description: "Copies sources to the dest directory") {
    from "src"
    into "dest"
}
// group 和 description 可以是想要的任何内容
  • 执行创建的 copy 的 task :
❯ ./gradlew copy
> Task :copy
​
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
​
// 通过检查dest目录中现在有一个名为myfile.txt的文件,并且它的内容与src目录中相同文件的内容相匹配,来验证它是否按预期工作。

自定义Task 类型 ( demo --> example2 )

Gradle 中通过 class 关键字创建的 task,默认的父类都是 org.gradle.api.DefaultTask,这里定义了一些 task 的默认行为。看看下面这个例子:

//自定义Task类,必须继承自DefaultTask
class SayHelloTask extends DefaultTask {
    
    String msg = "default name"
    int age = 18        
​
    //构造函数必须用@javax.inject.Inject注解标识
    @javax.inject.Inject
    SayHelloTask(int age) {
        this.age = age
    }
​
    //通过@TaskAction注解来标识该Task要执行的动作
    @TaskAction
    void sayHello() {
        println "Hello $msg ! age is ${age}"
    }
​
}
​
//通过constructorArgs参数来指定构造函数的参数值
task hello1(type: SayHelloTask, constructorArgs: [30])
​
//通过type参数指定task的父类,可以在配置代码里修改父类的属性
task hello2(type: SayHelloTask, constructorArgs: [18]) {
        //配置代码里修改 SayHelloTask 里的字段 msg 的值
    msg = "hjy"
}

gradle 生命周期管理 (demo2 --> example5)

gradle的构建分为初期化/配置/执行三个阶段:

初期化:initialization  --->  配置:configuration  ---->  执行:execution
  • 初始化 : Gradle支持单项目和多项目构建。在初始化阶段,Gradle确定将要参与构建的项目,并为每个项目创建一个Project实例。
  • 配置 : 在这个阶段,项目对象将会被配置。执行作为构建一部分的所有项目的构建脚本。
  • 执行 :Gradle确定要在配置阶段创建和配置的任务子集。子集由传递给gradle命令的任务名称参数和当前目录确定。然后Gradle执行每个选定的任务。

构建的生命周期

在Gradle中,可以通过Task的定义来定制项目自己所需要的方式。

编译: compile --> 测试:test --> 打包:packaging --> 安装:install 代码示例:

//  在 settings.gradle 文件:
println "[Phase: initialization] : settings executed... "
​
//  在 build.gradle 文件中:
​
println "[phase:configuration] build.gradle ..." 
task compile() { 
    group 'customized' 
    description 'compile task' 
    println "[phase:configuration] compile" 
    doFirst { 
        println "[phase:execution] compile :doFirst()" 
    } 
} 
task test { 
    group 'customized' 
    description 'test task' 
    println "[phase:configuration] test" 
    doLast { 
        println "[phase:execution] test:doLast()" 
    } 
} 
task packaging { 
    group 'customized' 
    description 'packaging task' 
    println "[phase:configuration] packaging" 
    doLast { 
        println "[phase:execution] packaging:doLast()" 
    } 
} 
task install { 
    group 'customized' 
    description 'install task' 
    println "[phase:configuration] install" 
    doFirst { 
        println "[phase:execution] install:doFirst()" 
    } 
    doLast { 
        println "[phase:execution] install:doLast()" 
    } 
}
​
​
​
// 命令行执行:
>  gradle tasks
>  gradle compile
> gradle test
​
​
//  多个任务同时执行,命令行执行:
> gradle compile test packaging install
​

补充 doFrist 与 doLast

doFirst 和 doLast 都是 gradle 预留的回调,在执行阶段会被调用,两者的顺序是 doFirst() -> doLast()

Task的增量构建

Gradle 支持一种叫做 up-to-date 检查的功能,也就是常说的增量构建。 Gradle 的 Task 会把每次运行的结果缓存下来,当下次运行时,会检查输出结果有没有变更,如果没有变更则跳过运行,这样可以提高 Gradle 的构建速度。

b4987846bc9a4442931f8d5bee186891.png

图中表示一个 java 编译的 task ,它的输入有2种,一是 JDK 版本号,一是源文件,它的输出结果为 class 文件,只要 JDK 版本号与源文件有任何变动,最终编译出的 class 文件肯定不同的。

当我们执行过一次·编译任务之后,再次运行该task,如果发现他的输入没有任何改动,那么它编译后的结果肯定也是不变的,可以直接从缓存里获取输出,这样 Gradle 会标识该 task 为 UP-TO-DATE,从而跳过该 task 的执行。

实现一个增量构建 (demo2 --> example3)

如何实现一个增量构建呢,至少指定一个输入,一个输出。

可以通过task注解来实现增量构建,这是一种更加灵活方便的方式

  • taskInputs、taskOutputs注解

注解名属性类型描述@Input任意Serializable类型一个简单的输入值@InputFileFile一个输入文件,不是目录@InputDirectoryFile一个输入目录,不是文件@InputFilesIterableFile列表,包含文件和目录@OutputFileFile一个输出文件,不是目录@OutputDirectoryFile一个输出目录,不是文件@OutputDirectoriesMap<String, File>或Iterable输出目录列表@TaskAction-用于标注Task真正执行的action

class SayHelloTask extends DefaultTask {
    //定义输入
    @Input
    String username;
    @Input
    int age
​
    //定义输出
    @OutputDirectory
    File destDir;
​
    @TaskAction
    void sayHello() {
        println "Hello $username ! age is $age"
    }
}
​
task test(type: SayHelloTask) {
    age = 18
    username = "hjy"
    destDir = file("$buildDir/test")
}
​

申请一个插件

Gradle 包括一系列的插件,在 Gradle 插件门户中还有更多的插件。发行版中包含的插件之一是 base 插件。与称为 Zip 的核心类型相结合,您可以使用配置的名称和位置创建项目的 Zip 归档。

  • 使用 plugins 语法将 base 插件添加到构建脚本文件中。确保在文件的顶部添加 plugins{} 块。
plugins {
    id "base"
}
  • 现在添加一个从 src 目录创建 zip 归档的 task 。
task zip(type: Zip, group: "Archive", description: "Archives sources in a zip file"){
    from "src"
    setArchiveName "basic-demo-1.0.zip"
}
​
// base 插件与设置一起工作,在build/distribution文件夹中创建一个名为basic-demo-1.0.zip的归档文件。
  • 在这种情况下,只需运行新的 zip 任务并 查看生成的 zip 文件是否在期望的位置。
❯ ./gradlew zip
> Task :zip
​
​
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

发现可用的 task

tasks 命令列出了可以调用的Gradle任务,包括基本插件添加的任务,以及刚刚添加的定制任务。

❯ ./gradlew tasks
​
​
> Task :tasks
​
​
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
​
​
Archive tasks
-------------
zip - Archives sources in a zip file
​
​
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
clean - Deletes the build directory.
​
​
Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
​
​
Custom tasks
------------
copy - Simply copies sources to a the build directory
​
​
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'basic-demo'.
components - Displays the components produced by root project 'basic-demo'. [incubating]
dependencies - Displays all dependencies declared in root project 'basic-demo'.
dependencyInsight - Displays the insight into a specific dependency in root project 'basic-demo'.
dependentComponents - Displays the dependent components of components in root project 'basic-demo'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'basic-demo'. [incubating]
projects - Displays the sub-projects of root project 'basic-demo'.
properties - Displays the properties of root project 'basic-demo'.
tasks - Displays the tasks runnable from root project 'basic-demo'.
​
​
Verification tasks
------------------
check - Runs all checks.
​
​
Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.
​
​
To see all tasks and more detail, run gradlew tasks --all
​
​
To see more detail about a task, run gradlew help --task <task>
​
​
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
​

Property

发现可用的属性

  • properties 命令告诉项目的属性。
❯ ./gradlew properties
  • 输出很多的。以下是一些可用的属性
Task :properties


------------------------------------------------------------
Root project
------------------------------------------------------------


buildDir: /Users/.../basic-demo/build
buildFile: /Users/.../basic-demo/build.gradle
description: null
group:
name: basic-demo
projectDir: /Users/.../basic-demo
version: unspecified


BUILD SUCCESSFUL

// 默认情况下,项目的名称与文件夹的名称匹配。您还可以指定 group 和 version 属性,但目前它们采用默认值,如 description。
// 默认情况下,buildFile 属性是构建脚本的完全限定路径名,它驻留在 projectDir 中。
  • 也可以更改许多属性。例如,可以尝试将以下代码添加到构建脚本 ( build.gradle ) 文件中,然后重新执行 gradle 属性。
description = "A trivial Gradle build"
version = "1.0"

property 和 gradle.property 文件的使用场景

  • 签名信息
  • 敏感信息(账号、密码等),且很多类共同使用。
  • 可以用来定义一些字段 而这些字段可以被build.gradle文件引用到,在build.gradle中使用VERSION_NAME、 VERSION_CODE、APP_NAME、IS_DEMO 等字段。
  • 很多Plugin都会向Project中加入额外的Property。在使用这些Plugin时,我们需要对这些Property进行赋值。
  • 访问和设定内置属性,可以直接通过属性名进行设定,比如version,但是当出现可能的重名歧义时,通常需要使用限定内容对其歧义进行消除,比如description需要指定是task的description还是project的。

ext 命名空间

Gradle 中很多模型类都提供了特别的属性支持,这些属性会以键值对的形式存储。使用ext命名空间,我们可以方便的添加属性。

//在project中添加一个名为groupId的属性 
project.ext.groupId="tech.easily" 
// 使用ext块添加属性 
ext{ 
    artifactId='EasyDependency' 
    config=[ 
        key:'value' 
    ] 
}

属性文件

项目的根目录下新建一个 gradle.properties 件,并在文件中定义简单的键值对形式的属性。这些属性能够被项目中的 gradle 脚本所访问。

# gradle.properties
# 注意文件的注释是以#开头的
groupId=tech.easily
artifactId=EasyDependency

有的时候,我们可能需要在代码中动态的创建属性文件并读取文件中的属性(比如自定义插件的时候),我们可以使用 java.util.Properties 类。

Gradle 日志

日志

日志是构建工具的主要界面。如果日志太多,真正的警告和问题容易被隐藏。另一方面,如果出了错,你需要找出相关的信息。Gradle 定义了6个日志级别,有两个 Gradle 特定日志级别。这两个级别分别是 QUIET 和 LIFECYCLE. 默认使用后面的这个日志级别,用于报告构建进度。

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

选择一个日志级别

“日志级别的命令行选项”中所示的命令行开关来选择不同的日志级别。“栈跟踪的命令行选项”中,你可以看到影响栈跟踪日志的命令行开关。

选项输出日志级别没有日志选项 LIFECYCLE 及更高- - quietQUIET 及更高- - infoINFO 及更高- - debugDEBUG 及更高选项意义没有栈跟踪选项构建错误(如编译错误)时没有栈跟踪打印到控制台。只有在内部异常的情况下才打印栈跟踪。如果选择 DEBUG 日志级别,则总是输出截取后的栈跟踪信息。--stacktrace 输出截断的栈跟踪。我们推荐使用这一个选项而不是打印全栈的跟踪信息。Groovy 的全栈跟踪非常冗长--full-stacktrace打印全栈的跟踪信息。

编写自己的日志消息

在构建文件,打印日志的一个简单方法是把消息写到标准输出中。Gradle 会把写到标准输出的所有内容重定向到它的日志系统的 QUIET 级别中。

使用标准输出写日志

在构建文件,打印日志的一个简单方法是把消息写到标准输出中。Gradle 会把写到标准输出的所有内容重定向到它的日志系统的 QUIET 级别中。

// build.gradle 文件中

println 'A message which is logged at QUIET level'  

编写自己的日志消息 (demo2 --> example6)

Gradle 还提供了一个 logger 属性给构建脚本,它是一个 Logger 实例。该接口扩展自 SLF4J的 Logger 接口,并添加了几个 Gradle 的特有方法。

// build.gradle 

logger.quiet('An info log message which is always logged.')
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 内部使用 Ant 和 Ivy。它们都有自己的日志系统。Gradle 将其日志输出重定向到 Gradle 的日志系统。从 Ant/Ivy 的日志级别到 Gradle 的日志级别是一对一的映射,除了 Ant/Ivy 的 TRACE 级别之外,它是映射到 Gradle 的 DEBUG 级别的。这意味着默认情况下, Gradle 日志级别将不会显示任何 Ant/Ivy 的输出,除非是错误或警告信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值