從移動應用到微服務,從小型創業公司到大企業,Gradle幫助團隊更快地構建,自動化並交付更好的軟件。
本例子將建立一個簡單的Gradle項目,僅經過命令行調用一些基本的Gradle命令,主要目的是瞭解Gradle如何管理項目
注:個人電腦系統是win10系統,因此相關命令行用的是cmdhtml
java version "1.8.0_171" Java(TM) SE Runtime Environment (build 1.8.0_171-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
------------------------------------------------------------ Gradle 4.4 ------------------------------------------------------------ Build time: 2017-12-06 09:05:06 UTC Revision: cf7821a6f79f8e2a598df21780e3ff7ce8db2b82 Groovy: 2.4.12 Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017 JVM: 1.8.0_171 (Oracle Corporation 25.171-b11) OS: Windows 10 10.0 amd64
新建BasicDemo文件,進入BasicDemo目錄java
E:\Java>md BasicDemo E:\Java>cd BasicDemo E:\Java\BasicDemo>
執行 init 任務(Task)android
E:\Java\BasicDemo>gradle init BUILD SUCCESSFUL in 1s 2 actionable tasks: 2 executed
任務執行後,查看初始化後默認的工程結構web
E:\Java\BasicDemo>tree/F 卷 project 的文件夾 PATH 列表 卷序列號爲 AF21-D274 E:. │ build.gradle │ gradlew │ gradlew.bat │ settings.gradle │ ├─.gradle │ ├─4.4 │ │ ├─fileChanges │ │ │ last-build.bin │ │ │ │ │ ├─fileHashes │ │ │ fileHashes.bin │ │ │ fileHashes.lock │ │ │ │ │ └─taskHistory │ │ taskHistory.bin │ │ taskHistory.lock │ │ │ └─buildOutputCleanup │ buildOutputCleanup.lock │ cache.properties │ outputFiles.bin │ └─gradle └─wrapper gradle-wrapper.jar gradle-wrapper.properties
簡單介紹下:
1.build.gradle:項目配置腳本,用於配置當前項目中的任務
2.gradle-wrapper.jar:Gradle Wrapper可執行文件JAR
3.gradle-wrapper.properties:Gradle Wrapper配置屬性
4.gradlew:用於基於Unix的系統的Gradle Wrapper腳本
5.gradlew.bat:適用於Windows的Gradle Wrapper腳本
6.settings.gradle:用於配置哪些項目參與構建的設置配置腳本api
build.gradle數組
/* * This build file was generated by the Gradle 'init' task. * * This generated file contains a commented-out sample Java project to get you started. * For more details take a look at the Java Quickstart chapter in the Gradle * user guide available at https://docs.gradle.org/4.4/userguide/tutorial_java_projects.html */ /* // 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.25' // 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' } */
當前build.gradle沒有任何可執行的腳本,只有一個應用java插件的模板腳本,腳本是被註釋了的
setting.gradle閉包
/* * This settings file was generated by the Gradle 'init' task. * * The settings file is used to specify which projects to include in your build. * In a single project build this file can be empty or even removed. * * Detailed information about configuring a multi-project build in Gradle can be found * in the user guide at https://docs.gradle.org/4.4/userguide/multi_project_builds.html */ /* // To declare projects as part of a multi-project build use the 'include' method include 'shared' include 'api' include 'services:webservice' */ rootProject.name = 'BasicDemo'
只有一句rootProject.name是設置項目名字的併發
E:\Java\BasicDemo>gradlew tasks Starting a Gradle Daemon (subsequent builds will be faster) > Task :tasks ------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------ Build Setup tasks ----------------- init - Initializes a new Gradle build. wrapper - Generates Gradle wrapper files. Help tasks ---------- buildEnvironment - Displays all buildscript dependencies declared in root project 'BasicDemo'. components - Displays the components produced by root project 'BasicDemo'. [incubating] dependencies - Displays all dependencies declared in root project 'BasicDemo'. dependencyInsight - Displays the insight into a specific dependency in root project 'BasicDemo'. dependentComponents - Displays the dependent components of components in root project 'BasicDemo'. [incubating] help - Displays a help message. model - Displays the configuration model of root project 'BasicDemo'. [incubating] projects - Displays the sub-projects of root project 'BasicDemo'. properties - Displays the properties of root project 'BasicDemo'. tasks - Displays the tasks runnable from root project 'BasicDemo'. 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 8s 1 actionable task: 1 executed
gradlew tasks至關於讓gradle執行本項目的tasks任務,該任務會列出全部的task,有上面的內容能夠知道:
在Build Setup 任務組裏面有init,wrapper兩個task,Help任務組裏面有buildEnvironment,components等任務,每項任務後面有介紹。app
因此這些任務是通用的,不論是什麼項目都會有這些基本的Task框架
Gradle提供了用於經過基於Groovy或Kotlin的DSL建立和配置任務的API。一個項目一般包括多個任務組,每一個任務組裏的每一個任務都執行一些基本操做。經過這些任務的組合,依賴構成了一個項目的好比說編譯,打包,調式等過程,實際上IDEA那些按鈕最終執行的也是這些任務
Gradle附帶一個能夠在本身的項目中配置的任務庫,因此咱們能夠利用這些任務庫來定義本身想實現的任務
例子:複製文件,將src文件夾裏的文件複製到dest文件夾中
步驟:
E:\Java\BasicDemo>md src
2.在src目錄下放一個文件,好比myfile.txt
E:\Java\BasicDemo>cd src E:\Java\BasicDemo\src>type nul>myfile.txt
3.在build.gradle定義copy這個任務
task copy(type: Copy, group: "Custom", description: "Copies sources to the dest directory"){ from "src" into "dest" }
4.在看看如今該項目有沒有我定義的copy任務
E:\Java\BasicDemo>gradlew tasks > Task :tasks ------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------ Build Setup tasks ----------------- init - Initializes a new Gradle build. wrapper - Generates Gradle wrapper files. Custom tasks ------------ copy - Copies sources to the dest directory Help tasks ---------- buildEnvironment - Displays all buildscript dependencies declared in root project 'BasicDemo'. components - Displays the components produced by root project 'BasicDemo'. [incubating] dependencies - Displays all dependencies declared in root project 'BasicDemo'. dependencyInsight - Displays the insight into a specific dependency in root project 'BasicDemo'. dependentComponents - Displays the dependent components of components in root project 'BasicDemo'. [incubating] help - Displays a help message. model - Displays the configuration model of root project 'BasicDemo'. [incubating] projects - Displays the sub-projects of root project 'BasicDemo'. properties - Displays the properties of root project 'BasicDemo'. tasks - Displays the tasks runnable from root project 'BasicDemo'. 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 1s 1 actionable task: 1 executed
能夠看到在Custom tasks已經有copy這個任務了
5.最後執行copy任務,看是否是真的有效果
E:\Java\BasicDemo>gradlew copy BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed E:\Java\BasicDemo>tree/F 卷 project 的文件夾 PATH 列表 卷序列號爲 AF21-D274 E:. │ build.gradle │ gradlew │ gradlew.bat │ settings.gradle │ ├─.gradle │ ├─4.4 │ │ ├─fileChanges │ │ │ last-build.bin │ │ │ │ │ ├─fileHashes │ │ │ fileHashes.bin │ │ │ fileHashes.lock │ │ │ │ │ └─taskHistory │ │ taskHistory.bin │ │ taskHistory.lock │ │ │ └─buildOutputCleanup │ buildOutputCleanup.lock │ cache.properties │ outputFiles.bin │ ├─dest │ myfile.txt │ ├─gradle │ └─wrapper │ gradle-wrapper.jar │ gradle-wrapper.properties │ └─src myfile.txt
能夠看到,src目錄下的文件已經複製到dest文件夾裏了,證實自定義的copy任務是可行的
成千上萬的任務怎麼管理,不可能都放在一塊兒吧,因此gradle用插件來集成一些具備特定功能的任務集合,好比要構建Android應用程序就要用com.android.application這個插件,構建java應用要用java這個插件,目前gradle裏面已經有不少現成的插件了,能夠 https://plugins.gradle.org瞭解一下。其實不少開源框架附帶有配套的gradle插件,你要是以爲不夠自定義,本身也能夠造一個
應用base插件
base插件裏有一個Zip核心類型,咱們能夠用它來作一些文件壓縮操做
1.在builde.gradle添加應用插件的腳本
... plugins { id "base" } ...
2.定義zip任務,將src文件壓縮爲basic-demo-1.0.zip
task zip(type: Zip, group: "Archive", description: "Archives sources in a zip file") { from "src" setArchiveName "basic-demo-1.0.zip" }
3.執行zip任務
E:\Java\BasicDemo>gradlew zip BUILD SUCCESSFUL in 1s 1 actionable task: 1 up-to-date E:\Java\BasicDemo>tree/F 卷 project 的文件夾 PATH 列表 卷序列號爲 AF21-D274 E:. │ build.gradle │ gradlew │ gradlew.bat │ settings.gradle │ ├─.gradle │ ├─4.4 │ │ ├─fileChanges │ │ │ last-build.bin │ │ │ │ │ ├─fileHashes │ │ │ fileHashes.bin │ │ │ fileHashes.lock │ │ │ │ │ └─taskHistory │ │ taskHistory.bin │ │ taskHistory.lock │ │ │ └─buildOutputCleanup │ buildOutputCleanup.lock │ cache.properties │ outputFiles.bin │ ├─build │ └─distributions │ basic-demo-1.0.zip │ ├─dest │ myfile.txt │ ├─gradle │ └─wrapper │ gradle-wrapper.jar │ gradle-wrapper.properties │ └─src myfile.txt
能夠看到build/distributions目錄下有basic-demo-1.0.zip這個壓縮文件,證實插件應用成功
執行gradlew tasks這句命令,能夠查看當前項目可用的Task,包括基本插件添加的和你本身定義添加的
Gradle還爲您的構建提供了一個豐富的,基於Web的視圖,稱爲構建掃描。
例子:在剛纔的zip任務後面加上--scan
E:\Java\BasicDemo>gradlew zip --scan BUILD SUCCESSFUL in 1s 1 actionable task: 1 up-to-date Publishing a build scan to scans.gradle.com requires accepting the Terms of Service defined at https://scans.gradle.com/terms-of-service. Do you accept these terms? [yes, no] yes Gradle Cloud Services license agreement accepted. Publishing build scan... https://gradle.com/s/gfdgkrh3xihcu
而後進https://gradle.com/s/gfdgkrh3...,填入你的郵箱,而後會發一封郵件給你,郵件裏就有構建分析連接,界面以下圖:
頗有檔次,那些大廠,有本身成熟的自動化流程才用這個功能吧
1.初始化項目BasicJava
新建BasicJava文件夾,使用gradle init命令
2.build.gradle添加java和application插件
apply plugin: 'java' apply plugin: 'application' repositories { jcenter() } //main函數所在路徑 mainClassName = 'com.newtrekwang.basicjava.App' dependencies { compile 'org.slf4j:slf4j-api:1.7.25' testCompile 'junit:junit:4.12' }
java插件裏有不少與java程序相關的構建任務;application插件有運行程序的任務;repositories設置依賴倉庫來源,常見的就是jcenter();dependencies設置程序依賴的第三方庫,構建的時候會從依賴倉庫去下載,好比上面就依賴了slf4f和junit
3.執行gradlew tasks,看看有哪些任務
E:\Java\BasicJava>gradlew tasks > Task :tasks ------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------ Application tasks ----------------- run - Runs this project as a JVM application Build tasks ----------- assemble - Assembles the outputs of this project. build - Assembles and tests this project. buildDependents - Assembles and tests this project and all projects that depend on it. buildNeeded - Assembles and tests this project and all projects it depends on. classes - Assembles main classes. clean - Deletes the build directory. jar - Assembles a jar archive containing the main classes. testClasses - Assembles test classes. Build Setup tasks ----------------- init - Initializes a new Gradle build. wrapper - Generates Gradle wrapper files. Distribution tasks ------------------ assembleDist - Assembles the main distributions distTar - Bundles the project as a distribution. distZip - Bundles the project as a distribution. installDist - Installs the project as a distribution as-is. Documentation tasks ------------------- javadoc - Generates Javadoc API documentation for the main source code. Help tasks ---------- buildEnvironment - Displays all buildscript dependencies declared in root project 'BasicJava'. components - Displays the components produced by root project 'BasicJava'. [incubating] dependencies - Displays all dependencies declared in root project 'BasicJava'. dependencyInsight - Displays the insight into a specific dependency in root project 'BasicJava'. dependentComponents - Displays the dependent components of components in root project 'BasicJava'. [incubating] help - Displays a help message. model - Displays the configuration model of root project 'BasicJava'. [incubating] projects - Displays the sub-projects of root project 'BasicJava'. properties - Displays the properties of root project 'BasicJava'. tasks - Displays the tasks runnable from root project 'BasicJava'. Verification tasks ------------------ check - Runs all checks. test - Runs the unit tests. 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 1s 1 actionable task: 1 executed
4.新建Java源碼包和編寫Java源碼
│ └─src └─main └─java └─com └─newtrekwang └─basicjava App.java
java插件默認以src/main/java目錄下做爲源碼存放路徑,你也能夠在build.gradle裏設置源碼路徑
App.java
package com.newtrekwang.basicjava; public class App{ public static void main(String[] args){ System.out.println("hello world"); } }
記得在build.gradle裏設置好入口函數的位置,我這裏就是mainClassName = 'com.newtrekwang.basicjava.App'
5.執行gradle run 運行Java程序
E:\Java\BasicJava>gradlew run > Task :run hello world BUILD SUCCESSFUL in 1s 2 actionable tasks: 1 executed, 1 up-to-date
在build.gradle裏添加jar設置,java插件自帶jar任務,必需要配置manifest,不然打出來的jar包沒有入口函數不能執行。
jar{ baseName = 'BasicJava' version = '2.0' manifest { attributes 'Main-Class': 'com.newtrekwang.basicjava.App' } }
執行gradlew jar ,而後就能夠在build/libs目錄下看到生成的jar文件了
執行jar文件
E:\Java\BasicJava\build\libs>java -jar BasicJava-2.0.jar hello world
構建Android應用程序主要是要用com.android.tools.build:gradle這個庫裏的com.android.application插件
由於Android Studio在建立項目的時候已經爲咱們生成了相關的文件夾和基本的腳本文件,因此咱們直接用AS建立一個Android工程
好比我建立了個Test工程:
實際上這個目錄結構與前面的BasicDemo很相似,能夠看做就是在BasicDemo上擴展的,只不過用到的Gradle插件不一樣,因此文件夾結構也就有所不一樣。
由於Android項目通常是多模塊的,就是一個項目能夠有多個應用模塊或者依賴模塊,因此根目錄的build.gradle裏的內容通常與多模塊的公共配置有關
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.1.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }
包含buildscript和allproject兩個塊,還有個clean任務,buildscript配置腳本的來源和腳本類路徑,repositories設置腳本倉庫地址,dependencies設置依賴那個庫,好比這裏用的是com.android.tools.build:gradle:3.1.2,由於子模塊要用application這個插件,不設置的話會獲取不到這個插件。allprojects設置整個工程和子模塊的依賴倉庫來源,常見的就是google()和jcenter()
gradle腳本大量用到了groovy的閉包語法,閉包能夠當方法參數,並且調用方法能夠不用加點,不用加圓括號,不熟悉的同窗能夠先去練下groovy閉包
好比
allprojects { repositories { google() jcenter() } }
其實是執行了project對象的allprojects方法,傳入了
{ repositories { google() jcenter() } }
這個閉包,而後閉包裏又調用了project對象的repositories方法,傳入了
{ google() jcenter() }
這個閉包,而後這個閉包裏調用了RepositoryHandler對象的google()和jcenter()這兩個方法(閉包是能夠改代理的,因此repositories方法的實現確定是改了閉包的代理的,由於默認的project對象沒有google(),jcenter()這兩個方法)
include ':app'
配置項目包含哪些模塊,好比這裏有個app模塊,那就把app這個文件夾添加上去
apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "com.newtrekwang.test" minSdkVersion 18 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0-alpha3' implementation 'com.android.support.constraint:constraint-layout:1.1.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }
首先應用了com.android.application這個插件,而後在相應的android,dependencies方法中經過閉包設置各類配置,依賴,具體指的是啥,這裏暫時不展開敘述。
AS有個gradle工具窗口,從中能夠查看全部的任務,這裏是兩個分組,一個總工程Test的,一個app模塊的,再展開就能看到具體的task了,而且點擊能夠執行任務
模仿結果:定義一個com.newtrekwang.application插件,能夠配置相似以下的腳本,而後腳本運行後打印出全部的配置信息。主要目的是瞭解Android插件的執行流程,爲何能夠這樣配置
android { compileSdkVersion 28 defaultConfig { applicationId "com.newtrekwang.test" minSdkVersion 18 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
1.爲了快速構建,用IDEA新建一個gradle工程,build.gradle應用groovy和maven插件。
build.gradle
apply plugin: 'groovy' apply plugin: 'maven' group 'com.newtrekwang.androidtools' version '1.0.0' repositories { mavenCentral() } dependencies { compile gradleApi() compile localGroovy() } uploadArchives { repositories { mavenDeployer { //本地的Maven地址設置爲D:\\ProgramData\\repository repository(url: 'file:D:\\ProgramData\\repository') } } }
setting.gradle
rootProject.name = 'androidtools'
工程目錄:
1.在/src/main/groovy裏面編寫插件源碼,結構相似Java工程
由於android塊裏有defaultConfig塊和buildTypes塊,defaultConfig塊裏都是字段,因此定義一個Config類,buildTypes塊裏是數組,因此定義一個BuildType放單元素裏的字段
Config.groovy
package com.newtrekwang.androidtools class Config { String applicationId int minSdkVersion int targetSdkVersion int versionCode String versionName String testInstrumentationRunner @Override public String toString() { return "Config{" + "applicationId='" + applicationId + '\'' + ", minSdkVersion=" + minSdkVersion + ", targetSdkVersion=" + targetSdkVersion + ", versionCode=" + versionCode + ", versionName='" + versionName + '\'' + ", testInstrumentationRunner='" + testInstrumentationRunner + '\'' + '}'; } }
BuildType.groovy
class BuildType { String name Boolean minifyEnabled String fileName1 String fileName2 def proguardFiles(fileName1,fileName2){ this.fileName1 = fileName1 this.fileName2 = fileName2 } def minifyEnabled(minifyEnabled){ this.minifyEnabled = minifyEnabled } def getDefaultProguardFile(s){ return s } BuildType(name){ this.name = name } @Override public String toString() { return "BuildType{" + "name='" + name + '\'' + ", minifyEnabled=" + minifyEnabled + ", fileName1='" + fileName1 + '\'' + ", fileName2='" + fileName2 + '\'' + '}'; } }
Androrid.groovy
package com.newtrekwang.androidtools import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.model.ObjectFactory class Android { Integer compileSdkVersion NamedDomainObjectContainer<BuildType> buildTypes Config config // 使閉包可以給compileSdkVersion賦值 def compileSdkVersion(compileSdkVersion) { this.compileSdkVersion = compileSdkVersion } // 嵌套集合對象容器 Android(NamedDomainObjectContainer<BuildType> buildTypes) { this.buildTypes = buildTypes } // 注入對象工廠 def setConfig(ObjectFactory objectFactory) { config = objectFactory.newInstance(Config.class) } // 使閉包配置生效,給config設置配置值 def defaultConfig(Closure closure) { closure.delegate = config closure() } // 固定用法,使buildTypes閉包配置生效 def buildTypes(Closure closure) { buildTypes.configure closure } @Override public String toString() { return "Android{" + "compileSdkVersion=" + compileSdkVersion + ", buildTypes=" + buildTypes + ", config=" + config + '}'; } }
2.再resources/META-INF/gradle-plugins裏面添加插件配置文件,個人插件名叫myapplication.因此文件名爲myapplication.properties
implementation-class=com.newtrekwang.androidtools.MyAndroidPlugin
裏面的內容是設置插件類的位置的
3.執行uploadArchives,打包插件爲jar包併發布再指定路徑
4.驗證插件
爲了區分開來,我新建了另外一個項目TestPlugin,專門用來測試插件,目錄結構以下
build.gradle
buildscript{ repositories{ mavenCentral() maven { // 插件jar所在倉庫位置 url 'file:D:\\ProgramData\\repository' } } dependencies { // 依賴路徑 classpath 'com.newtrekwang.androidtools:androidtools:1.0.0' } }
app/build.gradle
apply plugin :'myapplication' android { compileSdkVersion 28 defaultConfig { applicationId "com.newtrekwang.test" minSdkVersion 18 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile("proguard-android.txt"), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile("proguard-android.txt"), 'proguard-rules.pro' } } }
app裏的build.gradle徹底模仿Android插件的配置樣子,插件名改成個人myapplication
配置完畢,同步下工程,會發現有printConfig任務
最後執行printConfig任務
能夠看到控制檯打印了全部配置信息,驗證完畢,達到模仿效果