บทนำ
หากเพิ่งเริ่มใช้ Bazel คุณมาถูกที่แล้ว ทำตามบทแนะนำการสร้างครั้งแรกนี้เพื่อดูข้อมูลเบื้องต้นแบบง่ายๆ เกี่ยวกับการใช้ Bazel บทแนะนำนี้จะกำหนดคำสำคัญตามบริบทการใช้งานใน Bazel และอธิบายขั้นตอนพื้นฐานของเวิร์กโฟลว์ Bazel โดยคุณจะเริ่มจากเครื่องมือที่จำเป็น จากนั้นสร้างและเรียกใช้โปรเจ็กต์ 3 รายการที่มีความซับซ้อนเพิ่มขึ้น และเรียนรู้ว่าโปรเจ็กต์มีความซับซ้อนมากขึ้นได้อย่างไรและเพราะเหตุใด
แม้ว่า Bazel จะเป็นระบบบิลด์ที่ รองรับการบิลด์หลายภาษา แต่บทแนะนำนี้จะใช้โปรเจ็กต์ C++ เป็นตัวอย่าง และให้หลักเกณฑ์และขั้นตอนทั่วไปที่ใช้ได้กับภาษาส่วนใหญ่
เวลาที่ใช้โดยประมาณ: 30 นาที
ข้อกำหนดเบื้องต้น
เริ่มต้นด้วยการติดตั้ง Bazel หากยังไม่ได้ ติดตั้ง บทแนะนำนี้ใช้ Git สำหรับการควบคุมแหล่งที่มา ดังนั้นเพื่อผลลัพธ์ที่ดีที่สุด ติดตั้ง Git ด้วย
จากนั้นดึงข้อมูลโปรเจ็กต์ตัวอย่างจากที่เก็บ GitHub ของ Bazel โดยเรียกใช้คำสั่งต่อไปนี้ในเครื่องมือบรรทัดคำสั่งที่คุณเลือก
git clone https://github.com/bazelbuild/examplesโปรเจ็กต์ตัวอย่างสำหรับบทแนะนำนี้อยู่ในไดเรกทอรี examples/cpp-tutorial
ดูโครงสร้างของโปรเจ็กต์ได้ดังนี้
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── MODULE.bazel
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
ไฟล์มี 3 ชุด โดยแต่ละชุดแสดงถึงขั้นตอนในบทแนะนำนี้ ในขั้นตอนแรก คุณจะสร้าง เป้าหมาย เดียวที่อยู่ใน แพ็กเกจ เดียว ในขั้นตอนที่ 2 คุณจะสร้างทั้งไบนารีและไลบรารีจากแพ็กเกจเดียว ในขั้นตอนที่ 3 ซึ่งเป็นขั้นตอนสุดท้าย คุณจะสร้างโปรเจ็กต์ที่มีหลายแพ็กเกจและสร้างด้วยเป้าหมายหลายรายการ
สรุป: บทนำ
การติดตั้ง Bazel (และ Git) และโคลนที่เก็บสำหรับบทแนะนำนี้เป็นการวางรากฐานสำหรับการบิลด์ครั้งแรกด้วย Bazel ไปยังส่วนถัดไปเพื่อกำหนดคำบางคำและตั้งค่าพื้นที่ทำงาน
เริ่มต้นใช้งาน
คุณต้องตั้งค่าพื้นที่ทำงานของโปรเจ็กต์ก่อนจึงจะสร้างโปรเจ็กต์ได้ พื้นที่ทำงานคือไดเรกทอรีที่เก็บไฟล์ต้นฉบับของโปรเจ็กต์และเอาต์พุตบิลด์ของ Bazel นอกจากนี้ยังมีไฟล์สำคัญต่อไปนี้ด้วย
- ไฟล์
MODULE.bazelซึ่งระบุไดเรกทอรีและเนื้อหาเป็นพื้นที่ทำงานของ Bazel และอยู่ในรูทของโครงสร้างไดเรกทอรีของโปรเจ็กต์ นอกจากนี้ยังเป็นที่ที่คุณระบุทรัพยากร Dependency ภายนอกด้วย - ไฟล์
BUILDอย่างน้อย 1 ไฟล์ ซึ่งจะบอก Bazel ถึงวิธีสร้างส่วนต่างๆ ของโปรเจ็กต์ ไดเรกทอรีภายใน พื้นที่ทำงานที่มีไฟล์BUILDจะเรียกว่า แพ็กเกจ (ดูข้อมูลเพิ่มเติมเกี่ยวกับแพ็กเกจในส่วนท้ายของบทแนะนำนี้)
ในโปรเจ็กต์ในอนาคต หากต้องการกำหนดไดเรกทอรีเป็นพื้นที่ทำงานของ Bazel ให้สร้างไฟล์ว่างชื่อ MODULE.bazel ในไดเรกทอรีนั้น สำหรับบทแนะนำนี้ ไฟล์ MODULE.bazel จะอยู่ในแต่ละขั้นตอนแล้ว
ทำความเข้าใจไฟล์ BUILD
ไฟล์ BUILD มีคำแนะนำหลายประเภทสำหรับ Bazel ไฟล์
BUILDแต่ละไฟล์ต้องมี
กฎอย่างน้อย 1 ข้อเป็นชุดคำแนะนำ
ซึ่งจะบอก Bazel ถึงวิธีสร้างเอาต์พุตที่คุณต้องการ เช่น ไบนารีที่เรียกใช้งานได้
หรือไลบรารี อินสแตนซ์แต่ละรายการของกฎบิลด์ในไฟล์ BUILD จะเรียกว่า
เป้าหมาย และชี้ไปยัง
ชุดไฟล์ต้นฉบับและ
ทรัพยากร Dependency ที่เฉพาะเจาะจง เป้าหมายยังชี้ไปยังเป้าหมายอื่นๆ ได้ด้วย
ดูไฟล์ BUILD ในไดเรกทอรี cpp-tutorial/stage1/main ได้ดังนี้
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
ในตัวอย่างของเรา เป้าหมาย hello-world จะสร้างอินสแตนซ์ของกฎ
cc_binary ในตัวของ Bazel กฎนี้จะบอก Bazel ให้สร้างไบนารีที่เรียกใช้งานได้แบบสแตนด์อโลนจากไฟล์ต้นฉบับ hello-world.cc> โดยไม่มีทรัพยากร Dependency
สรุป: การเริ่มต้นใช้งาน
ตอนนี้คุณคุ้นเคยกับคำสำคัญบางคำและความหมายของคำเหล่านั้นในบริบทของโปรเจ็กต์นี้และ Bazel โดยทั่วไปแล้ว ในส่วนถัดไป คุณจะสร้างและทดสอบขั้นตอนที่ 1 ของโปรเจ็กต์
ขั้นตอนที่ 1: เป้าหมายเดียว, แพ็กเกจเดียว
ได้เวลาสร้างส่วนแรกของโปรเจ็กต์แล้ว โครงสร้างของส่วนขั้นตอนที่ 1 ของโปรเจ็กต์มีดังนี้
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── MODULE.bazel
เรียกใช้คำสั่งต่อไปนี้เพื่อไปยังไดเรกทอรี 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" ที่พิมพ์ออกมา
กราฟทรัพยากร Dependency ของขั้นตอนที่ 1 มีดังนี้

สรุป: ขั้นตอนที่ 1
ตอนนี้คุณสร้างบิลด์แรกเสร็จแล้ว จึงมีความคิดพื้นฐานเกี่ยวกับโครงสร้างของบิลด์ ในขั้นตอนถัดไป คุณจะเพิ่มความซับซ้อนด้วยการเพิ่มเป้าหมายอีกรายการ
ขั้นตอนที่ 2: เป้าหมายบิลด์หลายรายการ
แม้ว่าเป้าหมายเดียวจะเพียงพอสำหรับโปรเจ็กต์ขนาดเล็ก แต่คุณอาจต้องการแยกโปรเจ็กต์ขนาดใหญ่เป็นเป้าหมายและแพ็กเกจหลายรายการ ซึ่งจะช่วยให้บิลด์ส่วนเพิ่มรวดเร็วขึ้น นั่นคือ Bazel จะสร้างใหม่เฉพาะสิ่งที่เปลี่ยนแปลง และเร่งความเร็วบิลด์ด้วยการสร้างหลายส่วนของโปรเจ็กต์พร้อมกัน บทแนะนำนี้จะเพิ่มเป้าหมายในขั้นตอนนี้ และเพิ่มแพ็กเกจในขั้นตอนถัดไป
นี่คือไดเรกทอรีที่คุณจะใช้ในขั้นตอนที่ 2
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
ดูไฟล์ BUILD ในไดเรกทอรี cpp-tutorial/stage2/main ได้ดังนี้
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 ก่อน (โดยใช้
กฎ cc_library
ในตัวของ Bazel) จากนั้นจึงสร้างไบนารี
hello-world แอตทริบิวต์ deps ในเป้าหมาย hello-world จะบอก Bazel ว่าต้องใช้ไลบรารี hello-greet ในการสร้างไบนารี hello-world
คุณต้องเปลี่ยนไดเรกทอรีเป็นไดเรกทอรี cpp-tutorial/stage2 โดยเรียกใช้คำสั่งต่อไปนี้ก่อนจึงจะสร้างโปรเจ็กต์เวอร์ชันใหม่นี้ได้
cd ../stage2ตอนนี้คุณสร้างไบนารีใหม่ได้โดยใช้คำสั่งที่คุ้นเคยต่อไปนี้
bazel build //main:hello-worldBazel จะสร้างผลลัพธ์ที่มีลักษณะดังนี้อีกครั้ง
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 จะคอมไพล์ไฟล์นั้นใหม่เท่านั้น
เมื่อดูกราฟทรัพยากร Dependency คุณจะเห็นว่า hello-world ขึ้นอยู่กับอินพุตเพิ่มเติมชื่อ hello-greet

สรุป: ขั้นตอนที่ 2
ตอนนี้คุณสร้างโปรเจ็กต์ที่มีเป้าหมาย 2 รายการแล้ว เป้าหมาย hello-world จะสร้างไฟล์ต้นฉบับ 1 ไฟล์และขึ้นอยู่กับเป้าหมายอื่น (//main:hello-greet) ซึ่งจะสร้างไฟล์ต้นฉบับเพิ่มเติม 2 ไฟล์ ในส่วนถัดไป เราจะไปอีกขั้นและเพิ่มแพ็กเกจอื่น
ขั้นตอนที่ 3: หลายแพ็กเกจ
ขั้นตอนถัดไปนี้จะเพิ่มความซับซ้อนอีกขั้นและสร้างโปรเจ็กต์ที่มีหลายแพ็กเกจ ดูโครงสร้างและเนื้อหาของไดเรกทอรี cpp-tutorial/stage3 ได้ดังนี้
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
คุณจะเห็นว่าตอนนี้มีไดเรกทอรีย่อย 2 รายการ และแต่ละรายการมีไฟล์ BUILD ดังนั้น สำหรับ Bazel ตอนนี้พื้นที่ทำงานจึงมีแพ็กเกจ 2 รายการ ได้แก่ 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 ในแพ็กเกจหลักขึ้นอยู่กับเป้าหมายhello-time
ในแพ็กเกจ lib (จึงมีป้ายกำกับเป้าหมาย //lib:hello-time) ซึ่ง Bazel ทราบ
ได้จากแอตทริบิวต์ deps คุณจะเห็นการเปลี่ยนแปลงนี้ในกราฟทรัพยากร Dependency

เพื่อให้บิลด์สำเร็จ คุณต้องทำให้เป้าหมาย //lib:hello-time ใน lib/BUILD มองเห็นได้ชัดเจนสำหรับเป้าหมายใน main/BUILD โดยใช้แอตทริบิวต์การมองเห็น
เนื่องจากโดยค่าเริ่มต้น เป้าหมายจะมองเห็นได้เฉพาะเป้าหมายอื่นๆ ในไฟล์ BUILD เดียวกัน Bazel ใช้การมองเห็นเป้าหมายเพื่อป้องกันปัญหาต่างๆ เช่น ไลบรารีที่มีรายละเอียดการใช้งานรั่วไหลไปยัง API สาธารณะ
ตอนนี้ให้สร้างโปรเจ็กต์เวอร์ชันสุดท้ายนี้ เปลี่ยนเป็นไดเรกทอรี cpp-tutorial/stage3 โดยเรียกใช้คำสั่งต่อไปนี้
cd ../stage3เรียกใช้คำสั่งต่อไปนี้อีกครั้ง
bazel build //main:hello-worldBazel จะสร้างผลลัพธ์ที่มีลักษณะดังนี้
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
ตอนนี้คุณสร้างโปรเจ็กต์เป็น 2 แพ็กเกจที่มีเป้าหมาย 3 รายการ และเข้าใจทรัพยากร Dependency ระหว่างเป้าหมายเหล่านั้นแล้ว ซึ่งจะช่วยให้คุณสร้างโปรเจ็กต์ในอนาคตด้วย Bazel ได้ ในส่วนถัดไป เราจะดูวิธีดำเนินการต่อในการใช้ Bazel
ขั้นตอนถัดไป
ตอนนี้คุณสร้างบิลด์พื้นฐานแรกด้วย Bazel เสร็จแล้ว แต่ทั้งหมดนี้เป็นเพียงจุดเริ่มต้น แหล่งข้อมูลต่อไปนี้จะช่วยให้คุณเรียนรู้ Bazel ต่อไปได้
- หากต้องการมุ่งเน้นที่ C++ ต่อไป ให้อ่านเกี่ยวกับกรณีการใช้งานบิลด์ C++ ทั่วไป cases
- หากต้องการเริ่มต้นสร้างแอปพลิเคชันอื่นๆ ด้วย Bazel โปรดดู บทแนะนำสำหรับ Java, แอปพลิเคชัน Android หรือ แอปพลิเคชัน iOS
- หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับที่เก็บในเครื่องและที่เก็บระยะไกล โปรดอ่านเกี่ยวกับ ทรัพยากร Dependency ภายนอก
- หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับกฎอื่นๆ ของ Bazel โปรดดูคู่มือ อ้างอิงนี้
ขอให้สนุกกับการสร้าง