安裝過程請參考: 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 論壇提問。