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的不同版本,如调试版、正式发布版编写互不一样的构建规则,而不需要开多个分支或者多个版本库。

好了不瞎扯介绍了,开始进入正题。这篇文章主要是推荐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

首先确认你已经配置好 $ANDROID_HOME 这个环境变量指向您的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 向导,但我们就跳过吧。

这一节教程,我们将从配置库引用开始,到编译整个程序结束。我们的例子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添加类似于这一段的内容。

接下来我们添加非预编译的库。我们假设你的库项目路径在 ./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 ,这些都是我们已经定义好的名称,冒号是指本库与其它被引用的内容在同一项目中。

如果你引用了多个库,请为其每一个都添加这样的内容。

配置签名文件

我们假设你的签名文件位于 ./keystore/debug.keystore. 首先在同目录创建一个 debug.keystore.properties 文件,该文件的模板:

# 传递给keytool的 -alias 参数 key.alias=my_alias  # keystore文件的密码 key.store.password=store_password  # my_alias的密码 key.alias.password=alias_password 

创建好以后,继续编辑 BUCK 文件。

keystore(   name = 'debug_keystore',   store = './keystore/debug.keystore',   properties = './keystore/debug.keystore.properties', ) 

同样,名字可以自己取。

如果你有多个签名文件,在这里也可以添加多个。当然,接下来的步骤中你也需要添加多个app编译规则才行。

配置app编译规则

继续编辑 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 是用于内部的名称,这个可以自己取。package_type 是指该程序的类型,我们这里选的是 DEBUG ,也就是调试版。另一个可选的值是 RELEASE ,对这个值的使用我们将在下面讨论到。

所有 package 一项的值都应当是你的app的包名。keystore 是签名,而 deps 是依赖。对于本部分的 android_library 一条而言,它的依赖应当是自己的资源 res ,编译配置 build_config,引用的库文件的源码 mylibrary-src ,以及引用的jar包 android-support-v4,这些都是先前配置中为它们取的名称,所以请务必确保和上面的配置对应。同时别忘记冒号。

对于 android_resource 一条而言,其依赖应当是(其实我也不确定)所有依赖库的资源,如果不添加依赖可能会出错。

android_binary 定义的是对可执行文件的编译,其依赖 deps 应当是自己的源码 src 资源 res 和其他所有依赖库的资源。

接下来我们需要创建一个新的文件,名称为 .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编译规则,创建一个叫做 debug 的别名。这将在编译时用到。

接下来我们可以编译了。

$ buck build debug 

如果不出错,它将会输出编译结果及编译好的apk文件名。

Proguard的使用

本来教程应该到这里就结束了,但我想我必须提一下 Proguard。这个东西大家都不陌生。在buck中如何使用呢?

很简单,我们只需要回到上面的 android_binary 一条(你也可以创建一条新的 android_binary 规则,但名字不能和上面的那条一样),并将 DEBUG 改为 RELEASE ,然后新加一行 proguard_config = './proguard.cfg', 再编译即可。

如果你添加了多条 android_binary 规则,请记得去 .buckconfig 里面在 [alias] 配置段中添加你新增规则的名称以便编译。此时编译命令将变成 buck build 名称 。

实例

BlackLight 我的配置中包含了预编译jar、非预编译的有资源的库和无资源的库、还有两个编译规则:调试版和正式发布版。ChatterBox

注意事项

由于 buck 的资源合并机制不同,所以类似于 case R.id.xxx 的写法将会报错,请改成 if-else 语句。

鸣谢

但丁不淡定