บทนำ
หากเพิ่งเริ่มใช้ Bazel คุณมาถูกที่แล้ว ทำตามบทแนะนำการสร้างครั้งแรกนี้สำหรับ ข้อมูลเบื้องต้นเกี่ยวกับการใช้ Bazel บทแนะนำนี้จะให้นิยามคำศัพท์สำคัญดังต่อไปนี้ ในบริบทของ Bazel และอธิบายข้อมูลพื้นฐานของ Bazel เริ่มจากเครื่องมือที่จำเป็น คุณจะต้องสร้างและเรียกใช้ โดยจะมีความซับซ้อนมากขึ้นเรื่อยๆ รวมถึงเรียนรู้วิธีและสาเหตุที่ทำให้ซับซ้อนมากขึ้น
แม้ว่า 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
│ └── 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
ไฟล์มีอยู่ 3 ชุด โดยแต่ละชุดจะแสดงขั้นตอนในบทแนะนำนี้ ในระยะแรก คุณจะต้องสร้างเป้าหมายเดียวที่อยู่ในแพ็กเกจเดียว ในขั้นตอนที่ 2 คุณจะ คุณจะสร้างทั้งไบนารีและไลบรารีจากแพ็กเกจเดียว ใน ในขั้นตอนที่ 3 ซึ่งเป็นระยะสุดท้าย คุณจะต้องสร้างโปรเจ็กต์ที่มีแพ็กเกจต่างๆ สร้างได้ด้วยเป้าหมายที่หลากหลาย
สรุป: บทนำ
การติดตั้ง Bazel (และ Git) และโคลนที่เก็บสำหรับบทแนะนำนี้ทำให้คุณสามารถ ได้วางรากฐานในการสร้างสิ่งแรกกับ Bazel ไปยังรายการถัดไป เพื่อกำหนดคำศัพท์และตั้งค่าพื้นที่ทำงาน
เริ่มต้นใช้งาน
ตั้งค่าพื้นที่ทำงาน
คุณต้องตั้งค่าพื้นที่ทำงานของโปรเจ็กต์ก่อนจึงจะสร้างโปรเจ็กต์ได้ พื้นที่ทำงาน ไดเรกทอรีที่เก็บไฟล์ต้นฉบับของโปรเจ็กต์และเอาต์พุตบิลด์ของ Bazel ทั้งนี้ ยังมีไฟล์สำคัญเหล่านี้ด้วย:
ซึ่งระบุไดเรกทอรีและเนื้อหาในไดเรกทอรีเป็นพื้นที่ทำงานของ Bazel และ จะอยู่ที่รูทของโครงสร้างไดเรกทอรีของโปรเจ็กต์WORKSPACE
file
อย่างน้อย 1 รายการ ซึ่งบอก Bazel ถึงวิธีสร้างส่วนต่างๆ ของโปรเจ็กต์ ต ภายในพื้นที่ทำงานที่มีไฟล์BUILD
filesBUILD
คือ package (ข้อมูลเพิ่มเติมเกี่ยวกับแพ็กเกจ ต่อไปในบทแนะนำนี้)
ในโปรเจ็กต์ในอนาคต หากต้องการกำหนดไดเรกทอรีเป็นพื้นที่ทำงานของ Bazel ให้สร้าง
ไฟล์ว่างชื่อ WORKSPACE
ในไดเรกทอรีนั้น เพื่อให้เป็นไปตามวัตถุประสงค์ของบทแนะนำนี้
มีไฟล์ WORKSPACE
ในแต่ละระยะแล้ว
หมายเหตุ: เมื่อ Bazel สร้างโปรเจ็กต์ อินพุตทั้งหมดต้องอยู่ใน พื้นที่ทำงานเดียวกัน ไฟล์ที่อยู่ในพื้นที่ทำงานอื่นจะไม่เกี่ยวข้องกับ กันเว้นแต่จะลิงก์กัน ข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับกฎพื้นที่ทำงาน ได้ในคู่มือนี้
ทำความเข้าใจไฟล์ BUILD
ไฟล์ BUILD
มีวิธีการหลายประเภทสำหรับ Bazel ชิ้น
BUILD
ไฟล์ต้องมีอย่างน้อย 1 กฎ
เป็นชุดคำสั่ง ซึ่งบอก Bazel ถึงวิธีสร้างเอาต์พุตที่ต้องการ
เช่น ไบนารีหรือไลบรารีสั่งการ อินสแตนซ์แต่ละรายการของกฎการสร้างใน
ไฟล์ BUILD
มีชื่อว่าเป้าหมาย
และชี้ไปยังชุดไฟล์ต้นฉบับและการขึ้นต่อกันชุดหนึ่ง
เป้าหมายชี้ไปยังเป้าหมายอื่นได้ด้วย
ดูไฟล์ BUILD
ในไดเรกทอรี cpp-tutorial/stage1/main
:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
ในตัวอย่าง เป้าหมาย hello-world
จะสร้างอินสแตนซ์ในตัวของ Bazel
cc_binary rule
กฎนี้จะบอกให้ Bazel สร้างไบนารีปฏิบัติการในตัวจาก
ไฟล์ต้นฉบับ hello-world.cc
ไฟล์ที่ไม่มีทรัพยากร Dependency
สรุป: การเริ่มต้นใช้งาน
ตอนนี้คุณก็คุ้นเคยกับคำศัพท์สำคัญ และความหมายของคำเหล่านั้นในบริบทของ โครงการนี้ และ 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
ที่รูทของ
Google Workspace ได้อย่างเต็มประสิทธิภาพ
ตอนนี้ให้ทดสอบไบนารีที่สร้างใหม่ ซึ่งก็คือ
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
ลองดูไฟล์ 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 rule
ในตัวของ 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 อ้างอิง ป้อนข้อมูลเหมือนเดิม แต่โครงสร้างของบิลด์จะแตกต่างออกไป
สรุป: ขั้นที่ 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
└── WORKSPACE
คุณจะเห็นได้ว่าตอนนี้จะมีไดเรกทอรีย่อย 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 เป้าหมายแล้ว และทำความเข้าใจ ทรัพยากร Dependency ต่างๆ ซึ่งจะช่วยให้คุณออกเดินทางและสร้างอนาคตได้ กับ Bazel ในส่วนถัดไป โปรดดูวิธีต่อ การเดินทางของ Bazel
ขั้นตอนถัดไป
ตอนนี้คุณได้สร้างงานพื้นฐานชิ้นแรกกับ Bazel เสร็จแล้ว แต่นี่เป็น เริ่ม แหล่งข้อมูลเพิ่มเติมเพื่อการเรียนรู้กับ Bazel ต่อไปมีดังนี้
- หากต้องการมุ่งเน้นที่ C++ ต่อไป โปรดอ่านเกี่ยวกับ Use Case ทั่วไปของ C++
- หากต้องการเริ่มต้นสร้างแอปพลิเคชันอื่นๆ ด้วย Bazel โปรดดูบทแนะนำ สำหรับ Java, แอปพลิเคชัน Android หรือแอปพลิเคชัน iOS
- หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับที่เก็บในเครื่องและระยะไกล โปรดอ่านเกี่ยวกับ ทรัพยากร Dependency ภายนอก
- ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎอื่นๆ ของ Bazel ได้ที่คู่มืออ้างอิงนี้
ขอให้สนุกกับการสร้าง