แพลตฟอร์ม

รายงานปัญหา ดูแหล่งที่มา /3} /4} {3/4} {3/4} {3/4} {3/4} /4.

Bazel สร้างและทดสอบโค้ดบนฮาร์ดแวร์ ระบบปฏิบัติการ และการกำหนดค่าระบบต่างๆ ได้โดยใช้เครื่องมือสร้างเวอร์ชันต่างๆ มากมาย เช่น Linkers และคอมไพเลอร์ เพื่อช่วยจัดการความซับซ้อนนี้ 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 เพื่อแสดงข้อจำกัดที่ซับซ้อนยิ่งขึ้น เช่น ใช้เพื่อปรับใช้ตรรกะ "หรือ" พื้นฐาน รายการต่อไปนี้เป็นการทำเครื่องหมายไลบรารี ที่เข้ากันได้กับ 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"],
    }),
)

วิธีการข้างต้นสามารถตีความได้ดังนี้

  1. เมื่อกำหนดเป้าหมาย macOS เป้าหมายจะไม่มีข้อจำกัด
  2. เมื่อกำหนดเป้าหมาย Linux เป้าหมายไม่มีข้อจำกัด
  3. ไม่เช่นนั้น เป้าหมายจะมีข้อจํากัด @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 ในรูปแบบเอาต์พุต Starlark ของ bazel cquery เพื่อแยกเป้าหมายที่ใช้ร่วมกันไม่ได้ออกจากเป้าหมายที่เข้ากันได้

สามารถใช้เพื่อกรองเป้าหมายที่ใช้ร่วมกันไม่ได้ออก ตัวอย่างด้านล่างจะพิมพ์เฉพาะป้ายกำกับสำหรับเป้าหมายที่เข้ากันได้เท่านั้น จะไม่พิมพ์เป้าหมายที่ใช้ร่วมกันไม่ได้

$ cat example.cquery

def format(target):
  if "IncompatiblePlatformProvider" not in providers(target):
    return target.label
  return ""


$ bazel cquery //... --output=starlark --starlark:file=example.cquery

ปัญหาที่ทราบ

เป้าหมายที่ใช้ร่วมกันไม่ได้จะไม่สนใจข้อจำกัดในระดับการเข้าถึง