แพลตฟอร์ม

รายงานปัญหา ดูแหล่งข้อมูล ดูแหล่งข้อมูล 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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 สร้างค่าใหม่สําหรับมิติข้อมูลที่ระบุ ร่วมกันแล้ว 2 คำสั่งนี้จะกําหนด 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 มาพร้อมกับคําจํากัดความแพลตฟอร์มพิเศษต่อไปนี้ @platforms//host (ใช้แทนที่ด้วย @bazel_tools//tools:host_platform) ซึ่งเป็นค่าแพลตฟอร์มโฮสต์ที่ตรวจพบโดยอัตโนมัติ ซึ่งแสดงถึงแพลตฟอร์มที่ตรวจพบโดยอัตโนมัติสําหรับระบบที่ Bazel ใช้งานอยู่

การระบุแพลตฟอร์มสําหรับบิลด์

คุณสามารถระบุโฮสต์และแพลตฟอร์มเป้าหมายสำหรับบิลด์ได้โดยใช้ Flag บรรทัดคำสั่งต่อไปนี้

  • --host_platform - ค่าเริ่มต้นคือ @bazel_tools//tools:host_platform
    • เป้าหมายนี้มีชื่อแทนเป็น @platforms//host ซึ่งได้รับการสนับสนุนโดยกฎที่เก็บที่ตรวจพบระบบปฏิบัติการของโฮสต์และ CPU และเขียนเป้าหมายแพลตฟอร์ม
    • นอกจากนี้ยังมี @platforms//host:constraints.bzl ซึ่งแสดงอาร์เรย์ชื่อ HOST_CONSTRAINTS ซึ่งใช้ในไฟล์ BUILD และไฟล์ Starlark อื่นๆ ได้
  • --platforms - ค่าเริ่มต้นคือแพลตฟอร์มโฮสต์
    • ซึ่งหมายความว่าเมื่อไม่ได้ตั้งค่า Flag อื่นๆ @platforms//host จะเป็นแพลตฟอร์มเป้าหมาย
    • หากตั้งค่า --host_platform ไม่ใช่ --platforms ค่าของ --host_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

ระบบจะข้ามเป้าหมายที่อาจไม่เหมาะสมซึ่งเข้ากันไม่ได้หากเปิดใช้ --skip_incompatible_explicit_targets

ข้อจำกัดที่สื่ออารมณ์ได้มากขึ้น

หากต้องการแสดงความจำกัดอย่างยืดหยุ่นมากขึ้น ให้ใช้ @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"],
    }),
)

ข้อความข้างต้นมีความหมายดังนี้

  1. เมื่อกำหนดเป้าหมาย macOS เป้าหมายจะไม่มีข้อจำกัด
  2. เมื่อกําหนดเป้าหมายเป็น Linux เป้าหมายจะไม่มีข้อจํากัด
  3. ไม่เช่นนั้น เป้าหมายจะมีข้อจำกัด @platforms//:incompatible เนื่องจาก @platforms//:incompatible ไม่ได้อยู่ในแพลตฟอร์มใด ระบบจึงถือว่าเป้าหมายใช้ร่วมกันไม่ได้

หากต้องการให้ข้อจำกัดอ่านง่ายขึ้น ให้ใช้ selects.with_or() ของ skylib

คุณสามารถแสดงความเข้ากันได้แบบผกผันด้วยวิธีที่คล้ายกัน ตัวอย่างต่อไปนี้อธิบายไลบรารีที่เข้ากันได้กับทุกแพลตฟอร์มยกเว้น 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

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

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