Gradle與Makefile構建工具的對比

隨着Android Studio的普及,愈來愈多的Android開發者也要開始瞭解和學習Gradle這款強大的代碼構建工具了。咱們在學習和了解一項新事物的時候,最快速的方法每每是與已知的事物進行比較,對於熟悉Makefile編譯機制的Linux程序員而言,認識和掌握Gradle最好的方法莫過於比較它們之間的區別了,本文不許備詳細介紹Gradle的方方面面,而是但願經過與Makefile的對比幫助Gradle初學者更快速地理解Gradle的基礎和原理。java

 

Makefile是一種管理和編譯 Linux C/C++ 項目的工具,而Gradle也是一種代碼構建工具,只不過是針對Java語言的,它一樣能夠經過一些配置文件和腳原本完成代碼的依賴、第三方庫的引入、編譯的自動化配置等功能。android

 

首先說說Makefile,它是由一個個"規則"組成,每一個"規則"都是由"目標"、"依賴"、"命令"構成, 一個最簡單的Makefile以下所示:程序員

 

1
2
3
4
5
6
7
8
9
.PHONY: clean
 
all: hello
 
hello: hello.c
     gcc -o hello hello.c
 
clean:
     rm  hello

 

這裏有三個"目標",分別是: "all","hello","clean"bash

 

當執行"make"命令時,編譯器會默認查找目標"all" ,若是沒有"all"則會查找Makefile文件的第一個目標。本示例中有"all"目標,它依賴"hello"目標,所以編譯器會轉而先構建"hello"目標,構建前, 編譯器會先檢測"hello"目標是否須要更新(經過判斷"hello"文件與它所依賴的源文件"hello.c"的修改時間),若是須要,則執行後面的命令,而須要編譯的源文件則是經過手動或者相關函數的方式添加到編譯命令的參數中去的。app

 

這就是makefile最核心的構建思想,經過一個個"目標"、"依賴"、"命令"來完成整個項目的關聯和編譯。那麼,咱們也根據這一思想來看看Gradle是怎麼實現的。maven

 

1. Gradle是怎麼識別源文件的 ?函數

 

Gradle是採起了一種"約定優於配置"的思想來完成這一點的,它經過"Plugin"來約定項目的目標和源文件的佈局,例如: Java Plugin 定義的源文件佈局如圖所示:工具

 

wKioL1Xdnk2QXnWeAAEXQAiYhPc987.jpg

 

由該圖能夠很清楚地看到,Java Plugin 直接約定好了源文件的目錄結構,在Gradle中,通常把這些源碼目錄的配置叫作"SourceSet",同理,Android提供的Android Plugin一樣也定義了本身的源文件佈局,還加入瞭如 jni, AndroidManifest.xml 等目錄和文件。對於Gradle項目而言,須要在每一個代碼模塊的"build.gradle"文件中定義使用哪種Plugin, 例如:佈局

 

1
2
3
4
5
6
7
8
// 普通的Java項目
apply plugin:  'java'
 
//Android  Application
apply plugin:  'com.android.application'
 
//Android  Library
apply plugin:  'com.android.library'

 

2. Gradle是如何識別編譯目標的 ?學習

 

在Gradle中,與Makefile的"目標"相對應的概念是"任務",即"task",Gradle的構建過程,就是執行一條一條"task"任務的過程, 一樣,一個"task"也是能夠依賴另外一個"task"的,這樣,經過這種依賴關係,就能夠將整個項目中各個"task"連接到一塊兒了。

 

與Makefile中手寫目標的方式不一樣,Gradle將全部的"task"的定義所有交給Plugin來完成,因爲每一種工程類型(Java項目、Android項目等),其構建過程都是大同小異的,所以爲每一種類型的項目定義好了一種通用的Plugin,之後同類型的項目就能夠直接使用該Plugin了,很是的靈活和方便。

 

當咱們在項目中執行"gradle build"命令時,能夠看到該項目使用的Plugin具體定義了哪些"task",例如一個典型的Java Plugin定義的"task"以下所示:

 

1
2
3
4
5
6
7
8
9
10
11
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
: test
:check
:build

 

固然,雖然同是Android類型的工程,但不一樣的項目畢竟仍是有配置上的差別,所以,Gradle的Plugin中也能夠定義和導出一些特定的"元素"用於傳遞用戶自定義的配置信息,例如: Google提供的 "com.android.application" Plugin 就定義了一個"android"元素,開發者能夠在build.gradle中配置該元素的細節,好比定義一些: "項目的ID"、"sdk的版本"、"是否混淆"等等,例如:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
android {
 
     compileSdkVersion 21
     buildToolsVersion  "21.1.1"
 
     defaultConfig {
         applicationId  "com.jhuster.test"
         minSdkVersion 15
         targetSdkVersion 21
         versionCode 1
         versionName  "1.0.0"
      }
}

 

3. Gradle命令怎麼用 ?

 

gradle命令與make命令相似,都是用來執行編譯/清理任務的,make命令默認查找當前目錄下的Makefile文件,而且開始構建命令參數中所指定的"目標",例如:

 

1
2
$ make  all
$ make  clean

 

一樣,gradle命令也是相似的用法,例如:

 

1
2
3
4
$gradle build         // 構建和打包整個項目
$gradle clean         // 清除以前的構建
$gradle  test          // 執行測試
$gradle compileJava   // 編譯java

 

4. Gradle是如何引入第三方庫的 ?

 

對於Makefile而言,一般須要將第三方庫的源碼下載下來,編譯爲庫後,放入到工程目錄下,而後修改Makefile文件,在gcc/g++的編譯連接參數中引用該第三方庫的,例如:

 

1
2
hello: hello.c
     gcc -o hello hello.c -L /libs/foo .a

 

而Gradle則是經過build.grade文件中的dependencies來配置的,例如:

 

1
2
3
4
dependencies {
     compile files( 'libs/foo.jar' )   // 以jar的方式引用
     compile project( ':foo' )          // 以library工程源碼的方式引用
}

 

另外,Gradle還支持相似Ubuntu軟件源倉庫的方式來引用第三方庫,開發者能夠將本身的第三方庫上傳到一些支持Gradle的中心倉庫中,這樣,其餘人就能夠經過配置build.gradle直接完成對第三方庫的引用了,代碼構建的時候Gradle會自動完成第三方庫的下載和連接。比較經常使用的兩個箇中心倉庫: jcenter,mavenCentral。

 

例如: 咱們引用jcenter倉庫的okhttp庫,則build.gradle配置以下: 

 

1
2
3
4
5
6
7
8
9
allprojects {
     repositories {
         jcenter()
     }
}
 
dependencies {
     compile  'com.squareup.okhttp:okhttp:2.4.0'
}

 

5. 小結

 

Gradle真的很強大很靈活,它將最核心的構建規都則交給了Plugin來完成,這樣,輕鬆實現了構建過程的通用性,開發者只須要關注業務邏輯,以及少量的配置便可完成自動化編譯和部署的過程,相比於Linux手寫makefile要方便不少。好了,關於Gradle和Makefile的簡單對比就介紹到這裏了,但願對Gradle的初學者有所幫助,有任何疑問或者建議歡迎留言或者來信lujun.hust@gmail.com交流,或者關注個人新浪微博 @盧_俊 獲取最新的文章和資訊。

相關文章
相關標籤/搜索