自動化構建工具與gradle

自動化構建工具與gradle

一、定義

我們在學習c語言的時候都知道,c語言源程序從源程序到二進制程序,經過了預處理(Preprocessing), 編譯(Compilation), 匯編(Assemble), 鏈接(Linking)的過程,在使用gcc進行編譯時只需要gcc test.c -o test就可以生成,或者復雜點,一步步生成中間代碼:

gcc -e test.c -o test.i
gcc -s test.i -o test.s
gcc  -c test.s -o test.o
gcc test.o -o test

那么復雜一些的工程呢,里面有各種數不勝數的源程序、頭文件,都按模塊、功能分好了類,總不能手工一個個編譯吧,你可能會說:“那就用makefile啊”,沒錯,makefile可以幫助你按照順序編譯程序或者執行一些功能,它其實就是一種自動化構建工具(Build Automation)。

Build tools are programs that automate the creation of executable applications from source code. Building incorporates compiling, linking and packaging the code into a usable or executable form. In small projects, developers will often manually invoke the build process. This is not practical for larger projects, where it is very hard to keep track of what needs to be built, in what sequence and what dependencies there are in the building process. Using an automation tool allows the build process to be more consistent.

自動化構建工具就是自動將源碼生成為可執行文件的工具。

常用的組建自動化工具就有Make、Rake、Cake、MS build、AntGradle等。

原來我一直在用自動化構建工具啊。

二、它們能干什么

一般自動化構建工具有如下的feature:

  • 豐富的插件庫
  • 編譯管理工具
  • 源碼管理工具
  • 各種可用的UI
  • 和主流IDE兼容
  • 并行測試或編譯
  • 依賴管理
  • 版本沖突解決
  • 協同調試工具
  • 增量編譯
  • 最小化重新編譯
  • 自動事件/編譯
  • 框架的自動初始化
  • 代碼和資源的及時更新
  • 構建緩存、可緩存任務
  • 構建指標、性能跟蹤

三、常用自動化構建工具

  • 評價最高的自動化構建工具包括: Gradle, Codeship, TeamCity, and Travis CI.
  • 其他的自動化構建工具包括: Jenkins, CircleCI, Bamboo, and Apache Maven.
評價最高的自動化構建工具

四、關于Gradle

在寫安卓app時,經常因為要引入第三方庫或者修改一些系統信息而修改gradle,有時候build gradle的需要很長時間,這個過程中Gradle干了寫什么?

這一部分主要翻譯自?ukasz Wasylkowski的文章《Understanding Android Gradle build files》,鏈接見文末

1.gradle是什么

Gradle是一個基于Apache Ant和Apache Maven概念的項目自動化建構工具。它使用一種基于Groovy的特定領域語言(DSL)來聲明項目設置,拋棄了基于XML的各種繁瑣配置。 面向Java應用為主。當前其支持的語言限于Java、Groovy和Scala,計劃未來將支持更多的語言。

2.Groovy

  1. 語法

    gradle文件使用groovy腳本語言編寫的,它的語法很容易理解,但需要注意以下幾點:

    • 調用函數時有一個或多個參數不需要括號。

      def printAge(String name, int age) {
          print("$name is $age years old")
      }
      
      def printEmptyLine() {
          println()
      }
      printAge "John", 24 // Will print "John is 24 years old"
      printEmptyLine() // Will print empty line
      
    • 最后一個參數是closure時(lambda),可以寫在括號外面。

      def callWithParam(String param, Closure<String> closure) {
          closure(param)
      }
      
      callWithParam("param", { println it }) // Will print "param"
      callWithParam("param") { println it } // Will print "param"
      callWithParam "param", { println it } // Will print "param"
      
    • 當參數中有定義map的元素時,它們將會被轉化為一個map作為第一個元素,其他參數排在map參數之后。

      def printPersonInfo(Map<String, Object> person) {
          println("${person.name} is ${person.age} years old")
      }
      
      def printJobInfo(Map<String, Object> job, String employeeName) {
          println("$employeeName works as ${job.title} at ${job.company}")
      }
      
      printPersonInfo name: "John", age: 24
      printJobInfo "John", title: "Android developer", company: "Tooploox"
      
  2. closures

    閉包是開放的、匿名的、可以執行的代碼塊,它們有參數、返回值,它們可以被分配給某個對象。

    class WriterOne {
        def printText(str) {
            println "Printed in One: $str"
        }
    }
    
    class WriterTwo {
        def printText(str) {
            println "Printed in Two: $str"
        }
    }
    
    def printClosure = {
        printText "I come from a closure"
    }
    
    printClosure.delegate = new WriterOne()
    printClosure() // will print "Printed in One: I come from a closure
    printClosure.delegate = new WriterTwo()
    printClosure() // will print "Printed in Two: I come from a closure
    

3.關于gradle

  1. 腳本文件

    Gradle主要用到三個腳本文件:

    • build.gradle文件中的build 腳本 . 它們針對Project對象執行;
    • settings.gradle 文件中的settings 腳本, 針對Settings對象執行;
    • init 腳本 用于全局設置(針對 Gradle實例執行)
  2. projects

    gradle中含有一個或多個project,project有task組成,至少存在一個root project,它的里面可能還有subproject。按照慣例,root project主要提供了project布局、通用設置、插件路徑。

4.創建一個基于gradle的Android工程項目

一般的安卓目錄如下:

├── settings.gradle # [1]
├── build.gradle # [2]
├── gradle
│ └── wrapper
└── app
├── gradle.properties # [3]
├── build.gradle # [4]
└── src

[1]這是root project的設置文件,針對setting對象執行

[2]Root project的build設置

[3]App project的的配置文件,針對appSettings

[4]App project’的build設置

1.創建一個gradle項目

新建一個example文件夾,cd到其目錄,然后執行gradle projects,就會發現已經新建好一個gradle project了。

執行結果

2.設置projects層次結構

如果我們想要一個和默認的安卓項目相似的結構,我們需要一個setting.gradle文件,它配置了實例和project實例的層次。

setting.gradle文件中使用 void include(String[] projectPaths) 方法可以添加一個project,我們用它來添加一個app的subproject。

echo "include ':app'" > settings.gradle
gradle projects
執行結果

3構建Android subproject

現在我們將設置root project的build.gradle文件。

我們可以通過apply方法將com.android.application導入到appproject中。

void apply(Closure closure)
void apply(Map<String, ?> options)
void apply(Action<? super ObjectConfigurationAction> action)

mkdir app
echo apply plugin: 'com.android.application' > app/build.gradle
gradle app:tasks

但是輸出了錯誤信息:

出錯信息

錯誤之處找不到'com.android.application'的位置,這很容易理解,因為我們沒有為它指定路徑,我們在root或subproject的build.gradle中通過添加buildscript來設置路徑。

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
    }
}
出錯信息

繼續出錯,沒有指定buildToolsVersion版本,在app的build.gradle添加如下代碼,然后運行:

android {
   buildToolsVersion "25.0.1"
   compileSdkVersion 25
}

android方法定義了buildToolsVersion and compileSdkVersion 兩個方法。

出錯信息

又有報錯了,提示找不到Android SDK,需要在local.properties中定義或者添加環境變量。

我們就在root下新建一個local.properties并寫入SDK的路徑,然后運行:

echo sdk.dir=C\:\\Users\\getia\\AppData\\Local\\Android\\Sdk> local.properties
gradle app:tasks
1544179544125.png

又又報錯了,這次是AndroidManifest.xml,我們在app/src/main目錄下新建AndroidManifest.xml文件并向其中添加以下語句,再次運行:

mkdir app\src
mkdir app\src\main
echo apply plugin: 'com.android.application' > app/src/main/AndroidManifest.xml;
gradle app:tasks
成功了

終于成功了,我流下了沒有技術的眼淚。

4.添加依賴(Dependencies)

dependencies {
    compile 'io.reactivex.rxjava2:rxjava:2.0.4'
    testCompile 'junit:junit:4.12'
    annotationProcessor 'org.parceler:parceler:1.1.6'
}

Dependencies是一個特殊的代碼塊,如果你查看Dependencies的文檔DependencyHandler ,你會發現根本就沒有compile 或者testCompile方法。因為它使用了groovy語言的另一種特性methodMissing,它在沒有找到對應方法名或參數表時調用:當調用了一個沒有定義的方法,如果它的參數大于1個并且這個名字的方法被配置(*)過,那么就根據它的參數數目和類型,調用doAdd方法。

(*) 每一個插件都可以給 dependencies handler添加配置. 比如 java 插件 定義列 compile, compileClasspath, testCompile 和一些其他配置。Android 插件annotationProcessor <variant>Compile, <variant>TestCompile 等配置。

doAdd 方法是私有的, i它可以被 公有方法add調用。 所以我們可以這么來重寫Dependencies代碼塊(*) :

dependencies {
    add('compile', 'io.reactivex.rxjava2:rxjava:2.0.4')
    add('testCompile', 'junit:junit:4.12')
    add('annotationProcessor', 'org.parceler:parceler:1.1.6')

(*) 一般情況下不要這么做

參考文獻

https://www.techopedia.com/definition/16359/build-tool

https://www.trustradius.com/build-automation

https://medium.com/@wasyl/understanding-android-gradle-build-files-e4b45b73cc4c

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容