บทนำ
หากเพิ่งเริ่มใช้ 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
เรียกว่าเป้าหมาย และชี้ไปยังชุดไฟล์ต้นทางและข้อกําหนดเบื้องต้นที่เฉพาะเจาะจง เป้าหมายยังสามารถชี้ไปยังเป้าหมายอื่นๆ ได้ด้วย
ดูไฟล์ 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
" ที่พิมพ์
กราฟการขึ้นต่อกันของระยะที่ 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-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 จะคอมไพล์เฉพาะไฟล์นั้นซ้ำเท่านั้น
เมื่อดูที่กราฟทรัพยากร Dependency คุณจะเห็นว่า hello-world
ขึ้นอยู่กับอินพุตเพิ่มเติมชื่อ hello-greet
สรุป: ระยะที่ 2
ตอนนี้คุณสร้างโปรเจ็กต์ที่มีเป้าหมาย 2 รายการแล้ว เป้าหมาย hello-world
จะสร้างไฟล์ต้นฉบับ 1 ไฟล์และขึ้นอยู่กับเป้าหมายอื่น 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-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
ตอนนี้คุณสร้างโปรเจ็กต์เป็นแพ็กเกจ 2 รายการที่มีเป้าหมาย 3 รายการ และเข้าใจความสัมพันธ์ระหว่างแพ็กเกจต่างๆ แล้ว ซึ่งจะช่วยให้คุณสร้างโปรเจ็กต์ในอนาคตด้วย Bazel ได้ ในส่วนถัดไป มาดูวิธีดำเนินการต่อในเส้นทาง Bazel
ขั้นตอนถัดไป
ตอนนี้คุณสร้างบิลด์พื้นฐานครั้งแรกด้วย Bazel เสร็จแล้ว แต่นี่เป็นเพียงจุดเริ่มต้น แหล่งข้อมูลเพิ่มเติมเพื่อการเรียนรู้กับ Bazel ต่อไปมีดังนี้
- หากต้องการมุ่งเน้นที่ C++ ต่อไป โปรดอ่านเกี่ยวกับกรณีการใช้งานของบิลด์ C++ ที่พบบ่อย
- หากต้องการเริ่มต้นสร้างแอปพลิเคชันอื่นๆ ด้วย Bazel โปรดดูบทแนะนำสำหรับ Java, แอปพลิเคชัน Android หรือแอปพลิเคชัน iOS
- ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้งานที่เก็บข้อมูลในเครื่องและที่เก็บข้อมูลระยะไกลได้ที่ข้อมูลภายนอกที่ต้องพึ่งพา
- ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎอื่นๆ ของ Bazel ได้ที่คู่มืออ้างอิงนี้
ขอให้สนุกกับการสร้าง