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版本。

接下來我們可以克隆并構建 buckbuck 本身是使用 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 的別名。這將在編譯時用到。

接下來我們可以編譯了。

$ buck build 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 語句。

鳴謝

但丁不淡定