Bazel入門[翻譯]

Bazel入門[翻譯]

安裝

安裝過程請參考: http://bazel.io/docs/install.htmlhtml

使用工做區(workspace)

全部的Bazel構建都是基於一個 工做區(workspace) 概念, 它是文件系統中一個保存了所有源代碼的目錄,同時還將包含一些構建後的輸出目錄的符號連接(例如:bazel-binbazel-out 等輸出目錄)。 工做區目錄能夠隨意放在哪裏,可是工做區的根目錄必須包含一個名爲 WORKSPACE 的工做區配置文件。 工做區配置文件能夠是一個空文件,也能夠包含引用外部構建輸出所需的 依賴關係java

在一個工做區內,能夠根據須要共享多個項目。爲了簡單,咱們先從只有一個項目的工做區開始介紹。python

先假設你已經有了一個項目,對應 ~/gitroot/my-project/ 目錄。咱們先建立一個 空的 ~/gitroot/my-project/WORKSPACE 工做區配置文件,用於表示這是Bazel項目對應的根目錄。git

建立本身的Build構建文件

使用下面的命令建立一個簡單的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文件由於沒有變化而不會重現編譯。

使用多個包(Packages)

對於更大的項目,咱們一般須要將它們拆分到多個目錄中。 你能夠用相似//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 論壇提問。

相關文章
相關標籤/搜索