from:https://typeblog.net/tech/2014/07/22/use-buck-to-build-your-app.html
buck
是Facebook推出的一款高效率的Android App/Java項目構建工具,目前僅支持 Unix/Linux
平臺。因為它使用多線程編譯方式,所以相對于其他的構建工具而言編譯時間可以縮短50%甚至更多。
buck
提供了非常靈活的、可自定義的構建腳本。通過腳本,你可以為一個app的不同版本,如調(diào)試版、正式發(fā)布版編寫互不一樣的構建規(guī)則,而不需要開多個分支或者多個版本庫。
好了不瞎扯介紹了,開始進入正題。這篇文章主要是推薦buck,并介紹buck的部署,以及如何用buck構建已有的app項目(主要是如何編寫構建腳本)。
Buck的部署
安裝watchman
watchman
是 buck
的一個必須依賴,它被用來檢測文件的變化,以便確定哪些文件需要重新編譯。
watchman
需要 automake
這個依賴庫。
# 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
首先確認你已經(jīng)配置好 $ANDROID_HOME
這個環(huán)境變量指向您的sdk,并在sdk管理器中下載好您需要的api版本。
接下來我們可以克隆并構建 buck
. buck
本身是使用 ant
構建的,具體原因請參閱 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
本來這里應該還有一個 quickstart
向?qū)В覀兙吞^吧。
這一節(jié)教程,我們將從配置庫引用開始,到編譯整個程序結束。我們的例子App擁有類似于Eclipse生成的目錄結構。如果是其他類型的目錄結構也不要擔心,把下面對應的路徑換一下就可以啦。
配置庫引用(如果有的話)
切換到你的app目錄,首先建立一個名叫 BUCK
的空文件,并用文本編輯器打開。
首先我們引用預編譯庫(jar),一般app至少都會引用 android-support-v4.jar
,我們以此為例。在 BUCK
文件中加入:
prebuilt_jar( name = 'android-support-v4', binary_jar = './libs/android-support-v4.jar', visibility = [ 'PUBLIC' ], )
解釋一下,prebuilt_jar
表示定義一個預編譯庫,name
是其名稱,這里我們用了全名,你要是嫌煩也可以用縮寫之類的,只要你自己記住就可以。binary_jar
指向的是這個庫文件的路徑(./
表示的是Linux下的當前目錄)。visibility
一行表示全局可見。
如果你有多個jar,那么就需要為每一個jar添加類似于這一段的內(nèi)容。
接下來我們添加非預編譯的庫。我們假設你的庫項目路徑在 ./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
都可以自己取,只不過其他對應的地方也要改過來。
第一段 android_resource
定義的是庫的資源目錄,由 res
一項配置指定路徑,由 package
指定庫的包名,被下一段android_library
中的 deps
引用后即可生效。如果你的庫沒有資源目錄,那么請不要寫 android_resource
一段,同時將android_library
一段中對資源的引用 :mylibrary-res
刪除。
第二段 android_library
定義的是這個庫。srcs
一項是引用了它的 src
目錄下的全部 java
文件作為源碼。 deps
是該庫源碼的依賴,本例子中它只依賴自己的資源 :mylibrary-res
和支持庫 :android-support-v4
,這些都是我們已經(jīng)定義好的名稱,冒號是指本庫與其它被引用的內(nèi)容在同一項目中。
如果你引用了多個庫,請為其每一個都添加這樣的內(nèi)容。
配置簽名文件
我們假設你的簽名文件位于 ./keystore/debug.keystore
. 首先在同目錄創(chuàng)建一個 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', )
同樣,名字可以自己取。
如果你有多個簽名文件,在這里也可以添加多個。當然,接下來的步驟中你也需要添加多個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)部的名稱,這個可以自己取。package_type
是指該程序的類型,我們這里選的是 DEBUG
,也就是調(diào)試版。另一個可選的值是 RELEASE
,對這個值的使用我們將在下面討論到。
所有 package
一項的值都應當是你的app的包名。keystore
是簽名,而 deps
是依賴。對于本部分的 android_library
一條而言,它的依賴應當是自己的資源 res
,編譯配置 build_config
,引用的庫文件的源碼 mylibrary-src
,以及引用的jar包 android-support-v4
,這些都是先前配置中為它們?nèi)〉拿Q,所以請務必確保和上面的配置對應。同時別忘記冒號。
對于 android_resource
一條而言,其依賴應當是(其實我也不確定)所有依賴庫的資源,如果不添加依賴可能會出錯。
android_binary
定義的是對可執(zhí)行文件的編譯,其依賴 deps
應當是自己的源碼 src
資源 res
和其他所有依賴庫的資源。
接下來我們需要創(chuàng)建一個新的文件,名稱為 .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
這里我相信不用做過多解釋。唯一要解釋的是 [alias]
配置段,它是給 //:debug
,即我們之前定義的app編譯規(guī)則,創(chuàng)建一個叫做 debug
的別名。這將在編譯時用到。
接下來我們可以編譯了。
如果不出錯,它將會輸出編譯結果及編譯好的apk文件名。
Proguard的使用
本來教程應該到這里就結束了,但我想我必須提一下 Proguard
。這個東西大家都不陌生。在buck中如何使用呢?
很簡單,我們只需要回到上面的 android_binary
一條(你也可以創(chuàng)建一條新的 android_binary
規(guī)則,但名字不能和上面的那條一樣),并將 DEBUG
改為 RELEASE
,然后新加一行 proguard_config = './proguard.cfg',
再編譯即可。
如果你添加了多條 android_binary
規(guī)則,請記得去 .buckconfig
里面在 [alias]
配置段中添加你新增規(guī)則的名稱以便編譯。此時編譯命令將變成 buck build 名稱
。
實例
BlackLight 我的配置中包含了預編譯jar、非預編譯的有資源的庫和無資源的庫、還有兩個編譯規(guī)則:調(diào)試版和正式發(fā)布版。ChatterBox
注意事項
由于 buck
的資源合并機制不同,所以類似于 case R.id.xxx
的寫法將會報錯,請改成 if-else
語句。
鳴謝
但丁不淡定