Android Gradle構建腳本

      網友投稿 888 2022-05-30

      Gradle構建腳本使用Groovy來編寫。默認的構建文件名為build.gradle 。Gradle命令在構建時,會尋找一份名為build.gradle的文件,然后執行。

      在android studio項目中,默認情況下,根目錄有一份build.gradle ,各個module也各有一份。

      在android studio項目里的任意一份build.gradle文件里定義一個hello任務,執行gradle命令時,就會在這些build.gradle文件中尋找所有定義的hello任務,從根目錄開始逐個執行,如:

      在根目錄的build.gradle文件中定義:

      task hello { println 'Hello world root' }

      1

      2

      3

      在app module目錄的build.gradle文件中定義:

      task hello { println 'Hello world app' }

      1

      2

      3

      在build.gradle所在目錄使用gradle命令運行這個task

      juk@Juk-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q hello Hello world root Hello world app

      1

      2

      3

      也可以直接運行項目,然后在build的日志窗口可以看到輸出

      Gradle構建腳本中的Project對象

      Project對象是實現了org.gradle.api.Project接口的對象。在build.gradle這個腳本中, 我們就會使用Project對象與Gradle構建命令打交道。通過它,我們訪問很多Gradle提供的功能特性。

      build.gradle文件與Project對象有一個一對一的關系。在構建初始化時,gradle會為每一個參與到構建中來的項目模塊(module)組裝一個Project對象,具體過程是這樣的:

      首先,為本次構建,創建org.gradle.api.initialization.Settings實例。執行settings.gradle腳本中的內容,并對Settings對象進行配置。它主要聲明一些配置,用于實例化和配置參與構建的Project對象的層次。一個Settings對象對應于一份settings.gradle文件。這一步是在開始構建前完成的。

      使用配置好的Settings對象創建Project實例的層次

      最后,通過執行各個項目(module)的build.gradle配置各自的Project對象。執行的順序,默認情況是從父項目(父module)再到子項目(子module)。

      build.gradle的組成

      一般,一個項目(module)對應一份build.gradle腳本。我們會用build.gradle腳本去配置Project對象。所以 build.gradle的組成就是Project對象的組成。

      Tasks

      一個Project對象基本上就是Tasks對象的集合。每個task都執行一些基本的工作,如編譯類,運行單元測試,壓縮WAR包,生成JavaDoc。每個task都屬于某一個Project對象。Task對象是由TaskContainer對象負責創建的,在腳本中可以直接使用task的名字直接調用。在構建腳本中使用task關鍵字就可以聲明task了:

      task helloTask task helloTask {} task helloTask(type:Delete) task helloTask(type:Delete){} // 創建hello1 task task(hello1) { println "Good morning!1" } // 創建hello2 task task('hello2') { println "Good morning!" } // 創建hello3 task tasks.create(name:'hello3') { println "Good afternoon!" }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      上面這些聲明都是合法的

      一個task是由一系列的行為對象組成的。當task被執行時,它們就會依次被執行。

      給task hello2添加一個依賴

      task hello1 { doLast { println 'Hello world 1' } } task hello2(dependsOn: 'hello1') { doLast { println 'Hello world 2' } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      上面這種方式還可以換成以下這種方式:

      task hello2 { doLast { println 'Hello world 2' } } task hello1 { doLast { println 'Hello world 1' } } hello2.dependsOn hello1

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      依賴還可以這樣來寫:

      task hello2 { doLast { println 'Hello world 2' } } task hello1 { doLast { println 'Hello world 1' } } hello2.dependsOn { tasks.findAll { taskIt -> taskIt.name.startsWith('hello1') } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      運行結果都是:

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q hello2 Hello world 1 Hello world 2

      1

      2

      3

      doLast的意思就是將這個task 行為放到task的行為列表的最后面。

      project.ext.skipStage = 'Hello' task skipTask { doLast { println 'Hello world' } } // 當有這個skipStage屬性時才執行skipTask,沒有時跳過skipTask,因當前面有定義skipStage這個屬性,因此會執行skipTask skipTask.onlyIf{ project.hasProperty('skipStage') }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      還可以通過拋異常的方式來跳過,如上面的代碼可以換成下面的來實現:

      project.ext.skipStage = 'Hello' task skipTask { doLast { println 'Hello world' } } skipTask.doFirst { if(!project.hasProperty('skipStage')){ throw new StopExecutionException() } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      結果都是:

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q skipTask Hello world

      1

      2

      3

      在它要執行task之前,Gradle會經歷不同的階段。首先是配置階段,過后就是執行階段,這個階段它就會執行task的doFirst或doLast閉包里的代碼。

      這里要給大家說明一下, 下面這種task的寫法是OK的:

      task hello { println 'Hello world 1' } hello { println 'Hello world 2' }

      1

      2

      3

      4

      5

      6

      7

      結果:

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q hello Hello world 1 Hello world 2

      1

      2

      3

      4

      Dependencies

      依賴配置應該是大家最熟悉的了。最常見就是下面這些:

      dependencies { // 只能在當前項目(module)使用 implementation 'group:name:version' // 共享 api 'group:name:version' // 單元測試 testImplementation 'group:name:version' // android測試 androidTestImplementation 'group:name:version' ... }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      在腳本就是這樣配置的,它在Project對象中是由DependencyHandler對象管著的。

      Repositories

      指定外部依賴的源,就是告訴gradle去這個倉庫下載我們添加的依賴。

      repositories { google() mavenCentral() }

      1

      2

      3

      4

      指定自己的依賴倉庫,也是用這個

      repositories { maven { url "http://repo.juk.com/maven2" } }

      1

      2

      3

      4

      5

      在腳本中配置的這些會用來配置在Project對象中的RepositoryHandler對象管著的。

      如果你要上傳你壓縮包到maven倉庫,那么你可以在maven插件的uploadArchives task用repositories指定上傳位置

      apply plugin: 'maven' // 要先把maven插件加進來,否則沒有uploadArchives任務 uploadArchives { repositories { mavenDeployer { repository(url: "http://repo.juk.com/maven2") } } }

      1

      2

      3

      4

      5

      6

      7

      8

      Plugins

      其實插件并沒有什么特殊之處,它就是一些task的集合,例如有些插件里有編譯的task,設置源文件的task設置等等。添加插件到項目中來其實就是為了擴充Project對象的能力,讓它能做更多事。android項目的build.gradle就會有如下的插件:

      plugins { id 'com.android.application' id 'kotlin-android' }

      1

      2

      3

      4

      一般來說插件有兩種類型:

      一種是腳本插件,它是一構建腳本,會用于構建過程中。

      另一種是二進制插件,它們是一些實現了插件接口的類,通過程序的方法來控制構建。

      對應的,添加插件也有兩種方式:

      從本地文件系統添加一份腳本

      apply from: 'other.gradle'

      1

      添加二進制插件

      plugins { id 'com.android.application' }

      1

      2

      3

      apply plugin: 'com.android.application'

      1

      首先在build.gradle的開頭引用我們的插件

      apply plugin: HelloPlugin

      1

      然后在build.gradle找一個地方定義我們的插件,如文件末尾:

      class HelloPlugin implements Plugin { @Override void apply(Project project) { project.task("myHelloTask") { doLast { println 'Hello,My first plugin!' } } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      Android Gradle構建腳本

      11

      12

      如你所見,自定義的插件,需要實現Plugin接口,apply方法的參數,就是當前build.gradle腳本對應的Project對象,從我們定義里可以看出我們往Project對象里添加了一個task,名為myHelloTask,我們也可以通過傳進來的project對象去訪問它的東西,如定義的屬性。 我們來運行一下這個task:

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q myHelloTask Hello,My first plugin!

      1

      2

      如何從build.gradle中獲得輸入?我們可以擴展Project對象,然后通過擴展后的對象來實現,具體如下:

      apply plugin: HelloPlugin ... // step 2:使用插件擴展出來的屬性對象設置它的屬性值 myParameter.message = 'Halo Wo' class HelloPlugin implements Plugin { @Override void apply(Project project) { // step 1:在Project對象中擴展一個屬性 myParameter,類型是我們定義的HelloPluginExtension project.extensions.create('myParameter',HelloPluginExtension) project.task("myHelloTask") { doLast { // step 3: 獲取build.gradle輸入的值 println project.myParameter.message } } } } class HelloPluginExtension { def String message = 'hello plugin' }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      運行任務myHelloTask:

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q myHelloTask Halo Wo

      1

      2

      3

      注意:在Gradle的版本中已有很多標準插件,如編程語言插件:java ,scala,assembler, c,cpp

      例如要引用CPP插件:

      apply plugin: cpp

      1

      查看構建信息

      查看Project對象的層次結構

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q projects ------------------------------------------------------------ Root project 'HelloWorld' ------------------------------------------------------------ Root project 'HelloWorld' +--- Project ':app' \--- Project ':houseware' To see a list of the tasks of a project, run gradle :tasks For example, try running gradle :app:tasks

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      查看任務

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q tasks ------------------------------------------------------------ Tasks runnable from root project 'HelloWorld' ------------------------------------------------------------ Android tasks ------------- androidDependencies - Displays the Android dependencies of the project. signingReport - Displays the signing info for the base and test modules sourceSets - Prints out all the source sets defined in this project. Build tasks ----------- assemble - Assemble main outputs for all the variants. assembleAndroidTest - Assembles all the Test applications. build - Assembles and tests this project. buildDependents - Assembles and tests this project and all projects that depend on it. buildKotlinToolingMetadata - Build metadata json file containing information about the used Kotlin tooling buildNeeded - Assembles and tests this project and all projects it depends on. bundle - Assemble bundles for all the variants. clean - Deletes the build directory. ......

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      當然你也可以指定看某個項目的task,如houseware項目的task

      juklinglee@JukLings-MacBook-Pro HelloWorld % /Users/juklinglee/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q :houseware:tasks ------------------------------------------------------------ Tasks runnable from project ':houseware' ------------------------------------------------------------ Android tasks ------------- androidDependencies - Displays the Android dependencies of the project. signingReport - Displays the signing info for the base and test modules sourceSets - Prints out all the source sets defined in this project. Build tasks ----------- assemble - Assemble main outputs for all the variants. assembleAndroidTest - Assembles all the Test applications. build - Assembles and tests this project. ......

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      查看所有屬性值

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q properties ------------------------------------------------------------ Root project 'HelloWorld' ------------------------------------------------------------ AGP_INTERNAL__MIN_PLUGIN_VERSION_CHECK_STARTED: true _internalAndroidGradlePluginDependencyCheckerRegistered: true allprojects: [root project 'HelloWorld', project ':app', project ':houseware'] android.enableJetifier: true android.useAndroidX: true ant: org.gradle.api.internal.project.DefaultAntBuilder@62b07301 antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@3dbfb745 artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@4bbf11cf asDynamicObject: DynamicObject for root project 'HelloWorld' baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@187dbbc2 buildDir: /Users/juklinglee/AndroidStudioProjects/HelloWorld/build buildFile: /Users/juklinglee/AndroidStudioProjects/HelloWorld/build.gradle ......

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      查看編譯環境

      juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q buildEnvironment ------------------------------------------------------------ Root project 'HelloWorld' ------------------------------------------------------------ classpath +--- com.android.tools.build:gradle:7.1.2 | +--- com.android.tools:sdk-common:30.1.2 | | +--- com.android.tools:sdklib:30.1.2 | | | +--- com.android.tools.layoutlib:layoutlib-api:30.1.2 | | | | +--- com.android.tools:common:30.1.2 | | | | | +--- com.android.tools:annotations:30.1.2 | | | | | +--- com.google.guava:guava:30.1-jre | | | | | | +--- com.google.guava:failureaccess:1.0.1 | | |

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      查看某個task的詳細使用信息,如查看build 任務:

      juklinglee@JukLings-MacBook-Pro HelloWorld % /Users/juklinglee/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle help --task build > Configure project :app C/C++: Could not execute cmake at ...... > Task :help Detailed task information for build Paths :app:build :houseware:build Type Task (org.gradle.api.Task) Description Assembles and tests this project. Group build

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      現在,通過查詢我們知道build任務就是用來構建項目的。

      最后,以上內容只是gradle的冰山一角,但是看它的源碼,你將能很好的理解它是怎么工作的。

      Gradle Github地址

      Android Gradle

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Executors 封裝的四種線程池 各自有何特點,如何使用 超詳細 代碼動圖演示
      下一篇:【讀書會第十二期】動畫圖解核心內存區--堆
      相關文章
      亚洲精品狼友在线播放| 日日噜噜噜噜夜夜爽亚洲精品| 国产亚洲综合一区柠檬导航| vvvv99日韩精品亚洲| 亚洲爆乳无码精品AAA片蜜桃| 色天使亚洲综合在线观看| 亚洲制服丝袜第一页| 亚洲AV色吊丝无码| 亚洲日本久久一区二区va| 亚洲香蕉在线观看| 亚洲综合欧美色五月俺也去| 在线观看亚洲AV每日更新无码| 国产亚洲国产bv网站在线| 中中文字幕亚洲无线码| 亚洲国产日韩视频观看| 亚洲色丰满少妇高潮18p| 亚洲国产精品无码久久98| 亚洲av第一网站久章草| 亚洲av无码一区二区三区四区| 亚洲AV无码一区二区三区久久精品 | 亚洲成AV人片在线观看| 亚洲av无码不卡一区二区三区| 久久精品国产亚洲AV麻豆不卡| 亚洲av日韩av无码黑人| 亚洲美女在线观看播放| 亚洲丰满熟女一区二区v| 亚洲www在线观看| 亚洲AV无码片一区二区三区| vvvv99日韩精品亚洲| 久久亚洲av无码精品浪潮| 亚洲国产精品无码专区| 久久丫精品国产亚洲av不卡 | 国产精品久久亚洲一区二区| 亚洲av高清在线观看一区二区| 亚洲日韩在线观看| 国产亚洲精品a在线无码| 亚洲视频在线观看不卡| 亚洲成年网站在线观看| 久久亚洲欧美国产精品| 国产亚洲一区二区三区在线不卡 | 亚洲国产成人久久综合碰碰动漫3d|