安装过程请参考: http://bazel.io/docs/install.htmlhtml
全部的Bazel构建都是基于一个 工做区(workspace) 概念, 它是文件系统中一个保存了所有源代码的目录,同时还将包含一些构建后的输出目录的符号连接(例如:bazel-bin
和 bazel-out
等输出目录)。 工做区目录能够随意放在哪里,可是工做区的根目录必须包含一个名为 WORKSPACE
的工做区配置文件。 工做区配置文件能够是一个空文件,也能够包含引用外部构建输出所需的 依赖关系。java
在一个工做区内,能够根据须要共享多个项目。为了简单,咱们先从只有一个项目的工做区开始介绍。python
先假设你已经有了一个项目,对应 ~/gitroot/my-project/
目录。咱们先建立一个 空的 ~/gitroot/my-project/WORKSPACE
工做区配置文件,用于表示这是Bazel项目对应的根目录。git
使用下面的命令建立一个简单的Java项目:github
$ # If you're not already there, move to your workspace directory. $ cd ~/gitroot/my-project $ mkdir -p src/main/java/com/example $ cat > src/main/java/com/example/ProjectRunner.java <<EOF package com.example; public class ProjectRunner { public static void main(String args[]) { Greeting.sayHi(); } } EOF $ cat > src/main/java/com/example/Greeting.java <<EOF package com.example; public class Greeting { public static void sayHi() { System.out.println("Hi!"); } } EOF
Bazel经过工做区中全部名为 BUILD
的文件来解析须要构建的项目信息,所以, 咱们须要先在 ~/gitroot/my-project
目录建立一个 BUILD
构建文件。 下面是BUILD构建文件的内容:服务器
# ~/gitroot/my-project/BUILD java_binary( name = "my-runner", srcs = glob(["**/*.java"]), main_class = "com.example.ProjectRunner", )
BUILD文件采用相似Python的语法。虽然不能包含任意的Python语法, 可是BUILD文件中的每一个构建规则看起来都象是一个Python函数调用, 并且你也能够用 "#"
开头来添加单行注释。并发
java_binary
是一个构建规则。 其中 name
对应一个构建目标的标识符,可用用它来向Bazel指定构建哪一个项目。 srcs
对应一个源文件列表,Bazel须要将这些源文件编译为二进制文件。 其中 glob(["**/*.java"])
表示递归包含每一个子目录中以每一个 .java
为后缀名的文件。 com.example.ProjectRunner
指定包含main方法的类。函数
如今能够用下面的命令构建这个Java程序了:学习
$ cd ~/gitroot/my-project $ bazel build //:my-runner INFO: Found 1 target... Target //:my-runner up-to-date: bazel-bin/my-runner.jar bazel-bin/my-runner INFO: Elapsed time: 1.021s, Critical Path: 0.83s $ bazel-bin/my-runner Hi!
恭喜,你已经成功构建了第一个Bazel项目了!ui
对于小项目建立一个规则是能够的,可是随着项目的变大,则须要分别构建项目的不一样的部件, 最终再组装成产品。这种构建方式能够避免由于局部细小的修改儿致使重现构建整个应用, 同时不一样的构建步骤能够很好地并发执行以提升构建效率。
咱们如今将一个项目拆分为两个部分独立构建,同时设置它们之间的依赖关系。 基于上面的例子,咱们重写了BUILD构建文件:
java_binary( name = "my-other-runner", srcs = ["src/main/java/com/example/ProjectRunner.java"], main_class = "com.example.ProjectRunner", deps = [":greeter"], ) java_library( name = "greeter", srcs = ["src/main/java/com/example/Greeting.java"], )
虽然源文件是同样的,可是如今Bazel将采用不一样的方式来构建:首先是构建 greeter
库, 而后是构建 my-other-runner
。能够在构建成功后马上运行 //:my-other-runner
:
$ bazel run //:my-other-runner INFO: Found 1 target... Target //:my-other-runner up-to-date: bazel-bin/my-other-runner.jar bazel-bin/my-other-runner INFO: Elapsed time: 2.454s, Critical Path: 1.58s INFO: Running command line: bazel-bin/my-other-runner Hi!
如今若是你改动ProjectRunner.java
代码并从新构建my-other-runner
目标, Greeting.java
文件由于没有变化而不会重现编译。
对于更大的项目,咱们一般须要将它们拆分到多个目录中。 你能够用相似//path/to/directory:target-name
的名字引用在其余BUILD文件定义的目标。 假设src/main/java/com/example/
有一个cmdline/
子目录,包含下面的文件:
$ mkdir -p src/main/java/com/example/cmdline $ cat > src/main/java/com/example/cmdline/Runner.java <<EOF package com.example.cmdline; import com.example.Greeting; public class Runner { public static void main(String args[]) { Greeting.sayHi(); } } EOF
Runner.java
依赖com.example.Greeting
,所以咱们须要在src/main/java/com/example/cmdline/BUILD
构建文件中添加相应的依赖规则:
# ~/gitroot/my-project/src/main/java/com/example/cmdline/BUILD java_binary( name = "runner", srcs = ["Runner.java"], main_class = "com.example.cmdline.Runner", deps = ["//:greeter"] )
然而,默认状况下构建目标都是 私有 的。也就是说,咱们只能在同一个BUILD文件中被引用。 这能够避免将不少实现的细节暴漏给公共的接口,可是也意味着咱们须要手工容许runner
所依赖的//:greeter
目标。 就是相似下面这个在构建runner
目标时遇到的错误:
$ bazel build //src/main/java/com/example/cmdline:runner ERROR: /home/user/gitroot/my-project/src/main/java/com/example/cmdline/BUILD:2:1: Target '//:greeter' is not visible from target '//src/main/java/com/example/cmdline:runner'. Check the visibility declaration of the former target if you think the dependency is legitimate. ERROR: Analysis of target '//src/main/java/com/example/cmdline:runner' failed; build aborted. INFO: Elapsed time: 0.091s
可用经过在BUILD文件增长visibility = level
属性来改变目标的可间范围。 下面是经过在~/gitroot/my-project/BUILD
文件增长可见规则,来改变greeter
目标的可见范围:
java_library( name = "greeter", srcs = ["src/main/java/com/example/Greeting.java"], visibility = ["//src/main/java/com/example/cmdline:__pkg__"], )
这个规则表示//:greeter
目标对于//src/main/java/com/example/cmdline
包是可见的。 如今咱们能够从新构建runner
目标程序:
$ bazel run //src/main/java/com/example/cmdline:runner INFO: Found 1 target... Target //src/main/java/com/example/cmdline:runner up-to-date: bazel-bin/src/main/java/com/example/cmdline/runner.jar bazel-bin/src/main/java/com/example/cmdline/runner INFO: Elapsed time: 1.576s, Critical Path: 0.81s INFO: Running command line: bazel-bin/src/main/java/com/example/cmdline/runner Hi!
参考文档 中有可见性配置说明。
若是你查看 bazel-bin/src/main/java/com/example/cmdline/runner.jar 的内容, 能够看到里面只包含了Runner.class
,并无保护所依赖的Greeting.class
:
$ jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar META-INF/ META-INF/MANIFEST.MF com/ com/example/ com/example/cmdline/ com/example/cmdline/Runner.class
这只能在本机正常工做(由于Bazel的runner
脚本已经将greeter jar添加到了classpath), 可是若是将runner.jar
单独复制到另外一台机器上讲不能正常运行。 若是想要构建可用于部署发布的自包含全部依赖的目标,能够构建runner_deploy.jar
目标 (相似<target-name>_deploy.jar
以_deploy
为后缀的名字对应可部署目标)。
$ bazel build //src/main/java/com/example/cmdline:runner_deploy.jar INFO: Found 1 target... Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date: bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar INFO: Elapsed time: 1.700s, Critical Path: 0.23s
runner_deploy.jar
中将包含所有的依赖。
如今,您能够建立本身的目标并组装最终产品了。 接下来,可查看 相关教程 分别学习如何用Bazel构建 一个服务器、Android和iOS应用。 也能够参考 构建百科 和 用户手册 得到更多的信息。 若是有问题的话,能够到 bazel-discuss 论坛提问。