buck
是Facebook推出的一款高效率的Android App/Java項(xiàng)目構(gòu)建工具,目前僅支持 Unix/Linux
平臺(tái)。因?yàn)樗褂枚嗑€程編譯方式,所以相對(duì)于其他的構(gòu)建工具而言編譯時(shí)間可以縮短50%甚至更多。
buck
提供了非常靈活的、可自定義的構(gòu)建腳本。通過(guò)腳本,你可以為一個(gè)app的不同版本,如調(diào)試版、正式發(fā)布版編寫互不一樣的構(gòu)建規(guī)則,而不需要開多個(gè)分支或者多個(gè)版本庫(kù)。
好了不瞎扯介紹了,開始進(jìn)入正題。這篇文章主要是推薦buck,并介紹buck的部署,以及如何用buck構(gòu)建已有的app項(xiàng)目(主要是如何編寫構(gòu)建腳本)。
Buck的部署
安裝watchman
watchman
是 buck
的一個(gè)必須依賴,它被用來(lái)檢測(cè)文件的變化,以便確定哪些文件需要重新編譯。
watchman
需要 automake
這個(gè)依賴庫(kù)。
# Ubuntu / Debian $ sudo apt-get install automake # ArchLinux $ sudo pacman -S automake # Gentoo $ sudo emerge automake
然后克隆并編譯安裝 watchman
$ git clone https://github.com/facebook/watchman.git $ cd watchman $ ./autogen.sh $ ./configure $ make $ sudo make install
安裝buck
首先確認(rèn)你已經(jīng)配置好 $ANDROID_HOME
這個(gè)環(huán)境變量指向您的sdk,并在sdk管理器中下載好您需要的api版本。
接下來(lái)我們可以克隆并構(gòu)建 buck
. buck
本身是使用 ant
構(gòu)建的,具體原因請(qǐng)參閱 FAQ
$ git clone https://github.com/facebook/buck.git $ cd buck $ ant $ sudo ln -s /path-to-buck/bin/buck /usr/bin/buck
使用Buck編譯你的App
本來(lái)這里應(yīng)該還有一個(gè) quickstart
向?qū)В覀兙吞^(guò)吧。
這一節(jié)教程,我們將從配置庫(kù)引用開始,到編譯整個(gè)程序結(jié)束。我們的例子App擁有類似于Eclipse生成的目錄結(jié)構(gòu)。如果是其他類型的目錄結(jié)構(gòu)也不要擔(dān)心,把下面對(duì)應(yīng)的路徑換一下就可以啦。
配置庫(kù)引用(如果有的話)
切換到你的app目錄,首先建立一個(gè)名叫 BUCK
的空文件,并用文本編輯器打開。
首先我們引用預(yù)編譯庫(kù)(jar),一般app至少都會(huì)引用 android-support-v4.jar
,我們以此為例。在 BUCK
文件中加入:
prebuilt_jar( name = 'android-support-v4', binary_jar = './libs/android-support-v4.jar', visibility = [ 'PUBLIC' ], )
解釋一下,prebuilt_jar
表示定義一個(gè)預(yù)編譯庫(kù),name
是其名稱,這里我們用了全名,你要是嫌煩也可以用縮寫之類的,只要你自己記住就可以。binary_jar
指向的是這個(gè)庫(kù)文件的路徑(./
表示的是Linux下的當(dāng)前目錄)。visibility
一行表示全局可見(jiàn)。
如果你有多個(gè)jar,那么就需要為每一個(gè)jar添加類似于這一段的內(nèi)容。
接下來(lái)我們添加非預(yù)編譯的庫(kù)。我們假設(shè)你的庫(kù)項(xiàng)目路徑在 ./libs/MyLibrary
,資源目錄為 ./libs/MyLibrary/res
,源碼目錄為 ./libs/MyLibrary/src
, 包名為 com.my.library
, 并且需要 android-support-v4
才能編譯。
android_resource( name = 'mylibrary-res', res = './libs/MyLibrary/res', package = 'com.my.library', visibility = [ 'PUBLIC' ], ) android_library( name = 'mylibrary-src', srcs = glob(['./libs/MyLibrary/src/**/*.java']), deps = [ ':mylibrary-res', ':android-support-v4', ], visibility = [ 'PUBLIC' ], )
以上兩段中的 name
都可以自己取,只不過(guò)其他對(duì)應(yīng)的地方也要改過(guò)來(lái)。
第一段 android_resource
定義的是庫(kù)的資源目錄,由 res
一項(xiàng)配置指定路徑,由 package
指定庫(kù)的包名,被下一段android_library
中的 deps
引用后即可生效。如果你的庫(kù)沒(méi)有資源目錄,那么請(qǐng)不要寫 android_resource
一段,同時(shí)將android_library
一段中對(duì)資源的引用 :mylibrary-res
刪除。
第二段 android_library
定義的是這個(gè)庫(kù)。srcs
一項(xiàng)是引用了它的 src
目錄下的全部 java
文件作為源碼。 deps
是該庫(kù)源碼的依賴,本例子中它只依賴自己的資源 :mylibrary-res
和支持庫(kù) :android-support-v4
,這些都是我們已經(jīng)定義好的名稱,冒號(hào)是指本庫(kù)與其它被引用的內(nèi)容在同一項(xiàng)目中。
如果你引用了多個(gè)庫(kù),請(qǐng)為其每一個(gè)都添加這樣的內(nèi)容。
配置簽名文件
我們假設(shè)你的簽名文件位于 ./keystore/debug.keystore
. 首先在同目錄創(chuàng)建一個(gè) debug.keystore.properties
文件,該文件的模板:
# 傳遞給keytool的 -alias 參數(shù) key.alias=my_alias # keystore文件的密碼 key.store.password=store_password # my_alias的密碼 key.alias.password=alias_password
創(chuàng)建好以后,繼續(xù)編輯 BUCK
文件。
keystore( name = 'debug_keystore', store = './keystore/debug.keystore', properties = './keystore/debug.keystore.properties', )
同樣,名字可以自己取。
如果你有多個(gè)簽名文件,在這里也可以添加多個(gè)。當(dāng)然,接下來(lái)的步驟中你也需要添加多個(gè)app編譯規(guī)則才行。
配置app編譯規(guī)則
繼續(xù)編輯 BUCK
文件。
android_binary( name = 'debug', package_type = 'DEBUG', manifest = './AndroidManifest.xml', target = 'android-19', keystore = ':debug_keystore', deps = [ ':res', ':src', ':mylibrary-res', ], ) android_resource( name = 'res', res = './res', assets = './assets', package = 'com.mycompany.myapp', deps = [ ':mylibrary-res' ], visibility = [ 'PUBLIC' ], ) android_library( name = 'src', srcs = glob(['./src/**/*.java']), deps = [ ':build_config', ':res', ':mylibrary-src', ':android-support-v4', ], ) android_build_config( name = 'build_config', package = 'com.mycompany.myapp', )
其中,name
是用于內(nèi)部的名稱,這個(gè)可以自己取。package_type
是指該程序的類型,我們這里選的是 DEBUG
,也就是調(diào)試版。另一個(gè)可選的值是 RELEASE
,對(duì)這個(gè)值的使用我們將在下面討論到。
所有 package
一項(xiàng)的值都應(yīng)當(dāng)是你的app的包名。keystore
是簽名,而 deps
是依賴。對(duì)于本部分的 android_library
一條而言,它的依賴應(yīng)當(dāng)是自己的資源 res
,編譯配置 build_config
,引用的庫(kù)文件的源碼 mylibrary-src
,以及引用的jar包 android-support-v4
,這些都是先前配置中為它們?nèi)〉拿Q,所以請(qǐng)務(wù)必確保和上面的配置對(duì)應(yīng)。同時(shí)別忘記冒號(hào)。
對(duì)于 android_resource
一條而言,其依賴應(yīng)當(dāng)是(其實(shí)我也不確定)所有依賴庫(kù)的資源,如果不添加依賴可能會(huì)出錯(cuò)。
android_binary
定義的是對(duì)可執(zhí)行文件的編譯,其依賴 deps
應(yīng)當(dāng)是自己的源碼 src
資源 res
和其他所有依賴庫(kù)的資源。
接下來(lái)我們需要?jiǎng)?chuàng)建一個(gè)新的文件,名稱為 .buckconfig
,打開并編輯
[alias] debug = //:debug [java] src_roots = /src [project] # IntelliJ requires that every Android module have an # AndroidManifest.xml file associated with it. In practice, # most of this is unnecessary boilerplate, so we create one # "shared" AndroidManifest.xml file that can be used as a default. default_android_manifest = /AndroidManifest.xml
這里我相信不用做過(guò)多解釋。唯一要解釋的是 [alias]
配置段,它是給 //:debug
,即我們之前定義的app編譯規(guī)則,創(chuàng)建一個(gè)叫做 debug
的別名。這將在編譯時(shí)用到。
接下來(lái)我們可以編譯了。
$ buck build debug
如果不出錯(cuò),它將會(huì)輸出編譯結(jié)果及編譯好的apk文件名。
Proguard的使用
本來(lái)教程應(yīng)該到這里就結(jié)束了,但我想我必須提一下 Proguard
。這個(gè)東西大家都不陌生。在buck中如何使用呢?
很簡(jiǎn)單,我們只需要回到上面的 android_binary
一條(你也可以創(chuàng)建一條新的 android_binary
規(guī)則,但名字不能和上面的那條一樣),并將 DEBUG
改為 RELEASE
,然后新加一行 proguard_config = './proguard.cfg',
再編譯即可。
如果你添加了多條 android_binary
規(guī)則,請(qǐng)記得去 .buckconfig
里面在 [alias]
配置段中添加你新增規(guī)則的名稱以便編譯。此時(shí)編譯命令將變成 buck build 名稱
。
實(shí)例
BlackLight 我的配置中包含了預(yù)編譯jar、非預(yù)編譯的有資源的庫(kù)和無(wú)資源的庫(kù)、還有兩個(gè)編譯規(guī)則:調(diào)試版和正式發(fā)布版。ChatterBox
注意事項(xiàng)
由于 buck
的資源合并機(jī)制不同,所以類似于 case R.id.xxx
的寫法將會(huì)報(bào)錯(cuò),請(qǐng)改成 if-else
語(yǔ)句。