簡介
第一次使用 Bazel 嗎?我們很樂意助您一臂之力。請按照這個「第一個建構」教學課程中的指示,簡化 Bazel 的使用方法。本教學課程將定義在 Bazel 環境中使用的重要詞彙,並逐步引導您瞭解 Bazel 工作流程的基本概念。首先,您必須從所需的工具開始建構並執行三個專案,且這些專案複雜度增加,並瞭解專案會變得較為複雜的原因與原因。
雖然 Bazel 是支援多語言建構的建構系統,但本教學課程使用 C++ 專案做為範例,並提供適用於大多數語言的一般指南和流程。
預計完成時間:30 分鐘。
必要條件
請先安裝 Bazel (如果尚未安裝)。本教學課程使用 Git 進行原始碼控制,因此也為了獲得最佳效果,請安裝 Git。
接著,請在您選擇的指令列工具中執行下列指令,從 Bazel 的 GitHub 存放區擷取範例專案:
git clone https://github.com/bazelbuild/examples
本教學課程的範例專案位於 examples/cpp-tutorial
目錄中。
來看看它的結構:
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── WORKSPACE
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
有三組檔案,每組都代表本教學課程中的一個階段。 在第一個階段中,您將建構位於單一套件中的單一目標。在第二階段,您將透過單一套件建構二進位檔和程式庫。在第三階段和最後階段,您將建構具有多個套件的專案,並使用多個目標建構專案。
摘要:簡介
在本教學課程中,安裝 Bazel (和 Git) 並複製存放區後,您就能使用 Bazel 完成首次建構作業的基礎。請繼續前往下一節,定義一些字詞並設定工作區。
開始使用
設定工作區
您必須先設定專案的工作區,才能建立專案。工作區是目錄,保存專案的來源檔案以及 Bazel 的建構輸出內容。其中也包含下列重要檔案:
會將目錄及其內容識別為 Bazel 工作區,位於專案目錄結構的根目錄。WORKSPACE
file- 一或多個
,用來告知 Bazel 如何建構專案的不同部分。工作區內有一個BUILD
filesBUILD
檔案的目錄是「套件」。(本教學課程稍後會進一步說明套件)。
在日後的專案中,如要將目錄指定為 Bazel 工作區,請在該目錄中建立名為 WORKSPACE
的空白檔案。為配合本教學課程,每個階段中都有一個 WORKSPACE
檔案。
注意:Bazel 建構專案時,所有輸入內容都必須位於同一個工作區。除非建立連結,否則位於不同工作區的檔案彼此獨立。如要進一步瞭解工作區規則,請參閱這份指南。
瞭解 BUILD 檔案
BUILD
檔案包含多種 Bazel 不同類型的操作說明。每個 BUILD
檔案都需要至少一項規則做為一組指令,指示 Bazel 如何建構所需的輸出,例如可執行的二進位檔或程式庫。BUILD
檔案中的每個建構規則執行個體都稱為「目標」,並指向一組特定的來源檔案和依附元件。一個目標也可以指向其他目標。
查看 cpp-tutorial/stage1/main
目錄中的 BUILD
檔案:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
在本範例中,hello-world
目標會將 Bazel 的內建 cc_binary rule
例項化。這項規則會指示 Bazel 從 hello-world.cc
來源檔案建構獨立的可執行二進位檔,無需使用依附元件。
摘要:開始使用
現在您已經瞭解一些重要詞彙,以及這些詞彙在這項專案和 Bazel 整體中代表的意義。在下一節中,您將建構並測試專案的階段 1。
第 1 階段:單一目標、單一套件
現在該建構專案的第一部分了。如需視覺化參考資料,專案第 1 階段的結構為:
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── WORKSPACE
執行下列指令,前往 cpp-tutorial/stage1
目錄:
cd cpp-tutorial/stage1
接著,執行:
bazel build //main:hello-world
在目標標籤中,//main:
部分是 BUILD
檔案的位置 (相對於工作區根目錄),而 hello-world
是 BUILD
檔案中的目標名稱。
Bazel 會產生類似下方的內容:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s
您剛剛建立了第一個 Bazel 目標,Bazel 會將建構輸出內容放在工作區根目錄的 bazel-bin
目錄中。
現在,請測試剛建構的二進位檔,如下所示:
bazel-bin/main/hello-world
這會顯示列印的「Hello world
」訊息。
以下是第 1 階段的依附元件圖表:
摘要:第 1 階段
現在您已經完成第一個版本,對建構結構有基本瞭解。在下一個階段中,您可以新增另一個目標來增加複雜度。
第 2 階段:多個建構目標
雖然單一目標足以供小型專案使用,但建議您將較大的專案分割成多個目標和套件。這樣一來,就可以快速漸進式建構,也就是 Bazel 只會重新建構變更內容,並且一次建構專案的多個部分,以加快建構速度。在本教學課程的這個階段中,我們會新增目標,下一步則加入套件。
這是您要用於第 2 階段的目錄:
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
請查看以下 cpp-tutorial/stage2/main
目錄中的 BUILD
檔案:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
],
)
使用這個 BUILD
檔案,Bazel 會先建構 hello-greet
程式庫 (使用 Bazel 的內建 cc_library rule
),然後建構 hello-world
二進位檔。hello-world
目標中的 deps
屬性會告知 Bazel 需要 hello-greet
程式庫才能建構 hello-world
二進位檔。
建構這個新版專案之前,您需要變更目錄,並執行下列指令來切換至 cpp-tutorial/stage2
目錄:
cd ../stage2
您現在可以使用下列熟悉的指令建構新的二進位檔:
bazel build //main:hello-world
Bazel 再次會產生類似下方的內容:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s
您現在可以測試剛建構的二進位檔,以傳回另一個「Hello world
」:
bazel-bin/main/hello-world
如果您現在修改 hello-greet.cc
並重新建構專案,Bazel 只會重新編譯該檔案。
透過依附元件圖表,您可以看到 hello-world
依附於名為 hello-greet
的額外輸入:
摘要:第 2 階段
現在,您已建立兩個目標的專案。hello-world
目標會建構一個來源檔案,且依附於另一個目標 (//main:hello-greet
),後者會額外建構兩個來源檔案。在下一節中,將進一步新增另一個套件。
第 3 階段:多個套件
這個下一階段會新增額外的小工具層,並建構含有多個套件的專案。請查看以下 cpp-tutorial/stage3
目錄的結構和內容:
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
您會看到現在有兩個子目錄,且每個子目錄都包含一個 BUILD
檔案。因此,對 Bazel 而言,工作區現在包含兩個套件:lib
和 main
。
查看 lib/BUILD
檔案:
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
在 main/BUILD
檔案中:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
"//lib:hello-time",
],
)
主要套件中的 hello-world
目標取決於 lib
套件中的 hello-time
目標 (因此目標標籤 //lib:hello-time
);Bazel 透過 deps
屬性得知這一點。依附元件圖表中反映了這項變動:
為了讓建構作業成功執行,您可以使用瀏覽權限屬性,讓 lib/BUILD
中的 //lib:hello-time
目標明確顯示在 main/BUILD
中的目標。這是因為根據預設,只有同一個 BUILD
檔案中的其他目標才能看到目標。Bazel 會使用目標瀏覽權限來防止問題,例如含有實作詳細資料外洩到公用 API 的程式庫。
現在,請建構這個最終版本的專案。執行下列指令來切換至 cpp-tutorial/stage3
目錄:
cd ../stage3
再次執行下列指令:
bazel build //main:hello-world
Bazel 會產生類似下方的內容:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s
現在,請測試本教學課程的最後一個二進位檔,以取得最終的 Hello world
訊息:
bazel-bin/main/hello-world
摘要:第 3 階段
您現在已將專案建構為兩個包含三個目標的套件,並瞭解兩者之間的相依性,藉此使用 Bazel 建構未來的專案。請參閱下一節,瞭解如何繼續您的 Bazel 旅程。
後續步驟
您現已完成第一個使用 Bazel 的基本建構作業,但這只是第一步。下列資源可協助您繼續透過 Bazel 學習:
- 如要繼續專注於 C++,請參閱常見的 C++ 建構用途。
- 如要開始透過 Bazel 建構其他應用程式,請參閱 Java、Android 應用程式或 iOS 應用程式的教學課程。
- 如要進一步瞭解如何使用本機和遠端存放區,請參閱「外部依附元件」。
- 如要進一步瞭解 Bazel 的其他規則,請參閱這份參考指南。
祝建設愉快!