Bazel สามารถสร้างและทดสอบโค้ดในฮาร์ดแวร์ ระบบปฏิบัติการ และการกำหนดค่าระบบต่างๆ โดยใช้เครื่องมือบิลด์หลายเวอร์ชัน เช่น ลิงก์เกอร์และคอมไพเลอร์ Bazel มีแนวคิดเกี่ยวกับข้อจำกัดและแพลตฟอร์มเพื่อช่วยจัดการความซับซ้อนนี้ ข้อจำกัดคือมิติข้อมูลที่สภาพแวดล้อมในการสร้างหรือ การผลิตอาจแตกต่างกัน เช่น สถาปัตยกรรม CPU, การมีหรือ ไม่มี GPU หรือเวอร์ชันของคอมไพเลอร์ที่ติดตั้งในระบบ แพลตฟอร์มคือ ชุดตัวเลือกที่มีชื่อสำหรับข้อจำกัดเหล่านี้ ซึ่งแสดงถึง ทรัพยากรเฉพาะที่พร้อมใช้งานในสภาพแวดล้อมบางอย่าง
การจำลองสภาพแวดล้อมเป็นแพลตฟอร์มจะช่วยให้ Bazel เลือกทูลเชนที่เหมาะสม โดยอัตโนมัติ สำหรับการดำเนินการบิลด์ นอกจากนี้ยังใช้แพลตฟอร์มร่วมกับกฎ config_setting เพื่อเขียนแอตทริบิวต์ที่กำหนดค่าได้ด้วย
Bazel รู้จักบทบาท 3 อย่างที่แพลตฟอร์มอาจมี ได้แก่
- โฮสต์ - แพลตฟอร์มที่ Bazel ทำงานอยู่
- การดำเนินการ - แพลตฟอร์มที่เครื่องมือบิลด์ดำเนินการสร้างการดำเนินการเพื่อสร้างเอาต์พุตระดับกลางและขั้นสุดท้าย
- เป้าหมาย - แพลตฟอร์มที่เอาต์พุตสุดท้ายอยู่และดำเนินการ
Bazel รองรับสถานการณ์การบิลด์ต่อไปนี้เกี่ยวกับแพลตฟอร์ม
การสร้างแบบแพลตฟอร์มเดียว (ค่าเริ่มต้น) - แพลตฟอร์มโฮสต์ การดำเนินการ และเป้าหมาย จะเหมือนกัน เช่น การสร้างไฟล์ที่เรียกใช้งานได้ของ Linux ใน Ubuntu ที่ทำงานบน CPU Intel x64
บิลด์การคอมไพล์ข้าม - แพลตฟอร์มโฮสต์และแพลตฟอร์มการดำเนินการเหมือนกัน แต่ แพลตฟอร์มเป้าหมายแตกต่างกัน เช่น การสร้างแอป iOS ใน macOS ที่ทำงานบน MacBook Pro
การสร้างหลายแพลตฟอร์ม - แพลตฟอร์มโฮสต์ การดำเนินการ และเป้าหมายทั้งหมด แตกต่างกัน
การกำหนดข้อจำกัดและแพลตฟอร์ม
พื้นที่ของตัวเลือกที่เป็นไปได้สำหรับแพลตฟอร์มจะกำหนดโดยใช้กฎ
constraint_setting
และ
constraint_value
ภายในไฟล์ BUILD
constraint_setting
จะสร้างมิติข้อมูลใหม่ ส่วน
constraint_value
จะสร้างค่าใหม่สำหรับมิติข้อมูลที่กำหนด เมื่อรวมกันแล้วจะ
กำหนด enum และค่าที่เป็นไปได้ได้อย่างมีประสิทธิภาพ ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้ของไฟล์ BUILD
จะแนะนำข้อจำกัดสำหรับเวอร์ชัน glibc ของระบบที่มีค่าที่เป็นไปได้ 2 ค่า
constraint_setting(name = "glibc_version")
constraint_value(
name = "glibc_2_25",
constraint_setting = ":glibc_version",
)
constraint_value(
name = "glibc_2_26",
constraint_setting = ":glibc_version",
)
ข้อจำกัดและค่าของข้อจำกัดอาจกำหนดไว้ในแพ็กเกจต่างๆ ในพื้นที่ทํางาน โดยจะอ้างอิงตามป้ายกำกับและอยู่ภายใต้การควบคุมระดับการเข้าถึงตามปกติ หากระดับการแชร์อนุญาต คุณสามารถขยายการตั้งค่าข้อจํากัดที่มีอยู่ได้โดย กําหนดค่าของคุณเอง
กฎ platform
จะเปิดตัวแพลตฟอร์มใหม่ที่มี
ตัวเลือกค่าข้อจำกัดบางอย่าง โดย
คำสั่งต่อไปนี้จะสร้างแพลตฟอร์มชื่อ linux_x86
และระบุว่าแพลตฟอร์มนี้อธิบายสภาพแวดล้อมที่รันระบบปฏิบัติการ Linux ในสถาปัตยกรรม x86_64 ที่มี glibc เวอร์ชัน 2.25 (ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อจํากัดในตัวของ Bazel ได้ที่ด้านล่าง)
platform(
name = "linux_x86",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":glibc_2_25",
],
)
ข้อจำกัดและแพลตฟอร์มที่มีประโยชน์โดยทั่วไป
ทีม Bazel จะดูแลที่เก็บข้อมูลที่มีคำจำกัดความของข้อจำกัดสำหรับสถาปัตยกรรม CPU และระบบปฏิบัติการที่ได้รับความนิยมมากที่สุด เพื่อให้ระบบนิเวศมีความสอดคล้องกัน ซึ่งทั้งหมดอยู่ใน https://github.com/bazelbuild/platforms
Bazel มาพร้อมกับคำจำกัดความแพลตฟอร์มพิเศษต่อไปนี้
@local_config_platform//:host
นี่คือค่าแพลตฟอร์มโฮสต์ที่ตรวจหาอัตโนมัติ -
แสดงถึงแพลตฟอร์มที่ตรวจหาอัตโนมัติสำหรับระบบที่ Bazel ทำงานอยู่
การระบุแพลตฟอร์มสำหรับการสร้าง
คุณระบุแพลตฟอร์มโฮสต์และแพลตฟอร์มเป้าหมายสำหรับบิลด์ได้โดยใช้แฟล็กบรรทัดคำสั่งต่อไปนี้
--host_platform
- ค่าเริ่มต้นคือ@bazel_tools//platforms:host_platform
--platforms
- ค่าเริ่มต้นคือ@bazel_tools//platforms:target_platform
ข้ามเป้าหมายที่ใช้ร่วมกันไม่ได้
เมื่อสร้างสำหรับแพลตฟอร์มเป้าหมายที่เฉพาะเจาะจง มักจะต้องการข้าม
เป้าหมายที่จะใช้งานไม่ได้ในแพลตฟอร์มนั้น เช่น ไดรเวอร์ของอุปกรณ์ Windows
น่าจะสร้างข้อผิดพลาดของคอมไพเลอร์จำนวนมากเมื่อสร้างในเครื่อง Linux ด้วย //...
ใช้แอตทริบิวต์
target_compatible_with
เพื่อบอก Bazel ว่าโค้ดของคุณมีข้อจำกัดของแพลตฟอร์มเป้าหมายใด
การใช้แอตทริบิวต์นี้ที่ง่ายที่สุดคือการจำกัดเป้าหมายไว้ที่แพลตฟอร์มเดียว
ระบบจะไม่สร้างเป้าหมายสำหรับแพลตฟอร์มที่ไม่เป็นไปตามข้อจำกัดทั้งหมด ตัวอย่างต่อไปนี้จะจำกัด win_driver_lib.cc
ให้ใช้ได้กับ Windows 64 บิต
cc_library(
name = "win_driver_lib",
srcs = ["win_driver_lib.cc"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)
:win_driver_lib
ใช้ได้เฉพาะการสร้างด้วย Windows 64 บิตและ
ใช้ไม่ได้กับระบบอื่นๆ การเข้ากันไม่ได้เป็นแบบทรานซิทีฟ เป้าหมายใดๆ
ที่ขึ้นอยู่กับเป้าหมายที่ไม่รองรับโดยอ้อมจะถือว่า
ไม่รองรับเช่นกัน
ระบบจะข้ามเป้าหมายเมื่อใด
ระบบจะข้ามเป้าหมายเมื่อพิจารณาว่าไม่เข้ากันและรวมไว้ในการ บิลด์เป็นส่วนหนึ่งของการขยายรูปแบบเป้าหมาย ตัวอย่างเช่น การเรียกใช้ 2 รายการต่อไปนี้จะข้ามเป้าหมายที่ไม่เข้ากันซึ่งพบในการขยายรูปแบบเป้าหมาย
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
การทดสอบที่ไม่เข้ากันใน test_suite
จะ
ถูกข้ามในทำนองเดียวกันหากมีการระบุ test_suite
ในบรรทัดคำสั่งด้วย
--expand_test_suites
กล่าวอีกนัยหนึ่งคือ test_suite
ในบรรทัดคำสั่งจะทำงานเหมือน :all
และ
...
การใช้ --noexpand_test_suites
จะป้องกันการขยายและทำให้test_suite
เป้าหมายที่มีการทดสอบที่ไม่เข้ากันไม่สามารถใช้งานร่วมกันได้
การระบุเป้าหมายที่ไม่รองรับอย่างชัดเจนในบรรทัดคำสั่งจะส่งผลให้เกิด ข้อความแสดงข้อผิดพลาดและการสร้างที่ไม่สำเร็จ
$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully
ข้อจำกัดที่สื่อความหมายได้มากขึ้น
หากต้องการความยืดหยุ่นในการแสดงข้อจำกัดมากขึ้น ให้ใช้
@platforms//:incompatible
constraint_value
ที่ไม่มีแพลตฟอร์มใด
ตรงตามข้อกำหนด
ใช้ select()
ร่วมกับ
@platforms//:incompatible
เพื่อแสดงข้อจำกัดที่ซับซ้อนมากขึ้น
ตัวอย่างเช่น ใช้เพื่อติดตั้งใช้งานตรรกะ OR พื้นฐาน เครื่องหมายต่อไปนี้ระบุไลบรารีที่ใช้ได้กับ macOS และ Linux แต่ใช้กับแพลตฟอร์มอื่นไม่ได้
cc_library(
name = "unixish_lib",
srcs = ["unixish_lib.cc"],
target_compatible_with = select({
"@platforms//os:osx": [],
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
)
โดยตีความได้ดังนี้
- เมื่อกำหนดเป้าหมายเป็น macOS เป้าหมายจะไม่มีข้อจำกัด
- เมื่อกำหนดเป้าหมายเป็น Linux เป้าหมายจะไม่มีข้อจำกัด
- มิเช่นนั้น เป้าหมายจะมีข้อจํากัด
@platforms//:incompatible
เนื่องจาก@platforms//:incompatible
ไม่ได้เป็นส่วนหนึ่งของแพลตฟอร์มใดๆ ระบบจึงถือว่าเป้าหมายไม่เข้ากัน
หากต้องการให้ข้อจำกัดอ่านง่ายขึ้น ให้ใช้
skylib ของ
selects.with_or()
คุณสามารถแสดงความเข้ากันได้แบบผกผันในลักษณะที่คล้ายกัน ตัวอย่างต่อไปนี้ อธิบายไลบรารีที่เข้ากันได้กับทุกอย่างยกเว้น ARM
cc_library(
name = "non_arm_lib",
srcs = ["non_arm_lib.cc"],
target_compatible_with = select({
"@platforms//cpu:arm": ["@platforms//:incompatible"],
"//conditions:default": [],
],
)
การตรวจหาเป้าหมายที่ใช้ร่วมกันไม่ได้โดยใช้ bazel cquery
คุณสามารถใช้
IncompatiblePlatformProvider
ในbazel cquery
รูปแบบเอาต์พุต Starlark เพื่อแยกความแตกต่าง
เป้าหมายที่เข้ากันไม่ได้ออกจากเป้าหมายที่เข้ากันได้
ซึ่งใช้กรองเป้าหมายที่ไม่รองรับออกได้ ตัวอย่างด้านล่างจะพิมพ์ป้ายกำกับสำหรับเป้าหมายที่เข้ากันได้เท่านั้น ระบบจะไม่พิมพ์เป้าหมายที่ใช้ร่วมกันไม่ได้
$ cat example.cquery
def format(target):
if "IncompatiblePlatformProvider" not in providers(target):
return target.label
return ""
$ bazel cquery //... --output=starlark --starlark:file=example.cquery
ปัญหาที่ทราบ
เป้าหมายที่เข้ากันไม่ได้จะไม่สนใจข้อจำกัดด้านการมองเห็น