การย้ายข้อมูลไปยังแพลตฟอร์ม

รายงานปัญหา ดูแหล่งที่มา รุ่น Nightly · 7.4 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel มีการรองรับที่ซับซ้อนสำหรับการจำลองแพลตฟอร์มและชุดเครื่องมือสำหรับบิลด์หลายสถาปัตยกรรมและบิลด์ที่คอมไพล์ข้าม

หน้านี้จะสรุปสถานะการสนับสนุนนี้

และดู:

สถานะ

C++

กฎ C++ จะใช้แพลตฟอร์มเพื่อเลือก Toolchain เมื่อตั้งค่า --incompatible_enable_cc_toolchain_resolution

ซึ่งหมายความว่าคุณสามารถกำหนดค่าโปรเจ็กต์ C++ โดยใช้สิ่งต่อไปนี้

bazel build //:my_cpp_project --platforms=//:myplatform

แทนที่จะใช้รายการเดิม

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

การดำเนินการนี้จะเปิดใช้โดยค่าเริ่มต้นใน Bazel 7.0 (#7260)

หากต้องการทดสอบโปรเจ็กต์ C++ กับแพลตฟอร์ม โปรดดูหัวข้อการย้ายข้อมูลโปรเจ็กต์และการกำหนดค่าชุดเครื่องมือ C++

Java

กฎ Java ใช้แพลตฟอร์มเพื่อเลือกชุดเครื่องมือ

ซึ่งจะแทนที่แฟล็กเดิม --java_toolchain, --host_java_toolchain, --javabase และ --host_javabase

ดูรายละเอียดได้ที่ Java และ Bazel

Android

กฎ Android ใช้แพลตฟอร์มเพื่อเลือกชุดเครื่องมือเมื่อตั้งค่า --incompatible_enable_android_toolchain_resolution

ซึ่งหมายความว่าคุณสามารถกำหนดค่าโปรเจ็กต์ Android ด้วยสิ่งต่อไปนี้

bazel build //:my_android_project --android_platforms=//:my_android_platform

แทนที่จะใช้ Flag แบบเดิม เช่น --android_crosstool_top, --android_cpu และ --fat_apk_cpu

ซึ่งจะเปิดใช้โดยค่าเริ่มต้นใน Bazel 7.0 (#16285)

หากต้องการทดสอบโปรเจ็กต์ Android กับแพลตฟอร์มต่างๆ โปรดดูหัวข้อการย้ายข้อมูลโปรเจ็กต์

Apple

กฎของ Apple ไม่รองรับแพลตฟอร์มและยังไม่ได้กำหนดเวลาสำหรับการสนับสนุน

คุณยังคงใช้ API ของแพลตฟอร์มกับบิลด์ของ Apple ได้ (เช่น เมื่อสร้างด้วยกฎของ Apple และ C++ ล้วน) โดยใช้การแมปแพลตฟอร์ม

ภาษาอื่นๆ

  • กฎ Go รองรับแพลตฟอร์มอย่างเต็มรูปแบบ
  • กฎ Rust รองรับแพลตฟอร์มอย่างเต็มรูปแบบ

หากคุณเป็นเจ้าของชุดกฎภาษา โปรดดูการย้ายข้อมูลชุดกฎเพื่อเพิ่มการสนับสนุน

ข้อมูลเบื้องต้น

มีการนำแพลตฟอร์มและเครื่องมือเชนมาใช้เพื่อกำหนดมาตรฐานวิธีที่โปรเจ็กต์ซอฟต์แวร์จะกำหนดเป้าหมายสถาปัตยกรรมที่ต่างกันและการคอมไพล์แบบข้ามแพลตฟอร์ม

แนวคิดนี้ได้รับแรงบันดาลใจจากการสังเกตว่าผู้ดูแลภาษาทําเช่นนี้อยู่แล้วในลักษณะที่ไม่สอดคล้องกัน เช่น กฎ C++ ใช้ --cpu และ --crosstool_top เพื่อประกาศ CPU และเครื่องมือทางเทคนิคเป้าหมาย ตัวอย่างทั้ง 2 รายการนี้ไม่ได้จําลอง "แพลตฟอร์ม" อย่างถูกต้อง ซึ่งทำให้ได้บิลด์ที่ไม่ถูกต้องและดูไม่เหมาะสม

Java, Android และภาษาอื่นๆ ได้พัฒนาแฟล็กของตนเองเพื่อวัตถุประสงค์ที่คล้ายกัน ซึ่งไม่มีแฟล็กใดที่ทำงานร่วมกันได้ ซึ่งทำให้การสร้างหลายภาษามีความสับสนและซับซ้อน

Bazel มีไว้สำหรับโปรเจ็กต์ขนาดใหญ่ที่มีหลายภาษาและหลายแพลตฟอร์ม ด้วยเหตุนี้ เราจึงต้องการการสนับสนุนแนวคิดเหล่านี้อย่างมีหลักการมากขึ้น รวมถึง API มาตรฐานที่ชัดเจน

ความต้องการในการย้ายข้อมูล

การอัปเกรดเป็น API ใหม่ต้องใช้ความพยายาม 2 อย่าง ได้แก่ การเผยแพร่ API และการอัปเกรดตรรกะกฎเพื่อใช้งาน

รายการแรกเสร็จแล้ว แต่รายการที่ 2 ยังอยู่ระหว่างดำเนินการ ซึ่งประกอบด้วยการตรวจสอบว่าได้กำหนดแพลตฟอร์มและเครื่องมือทางภาษาเฉพาะภาษาแล้ว ตรรกะภาษาจะอ่านเครื่องมือทางภาษาผ่าน API ใหม่แทน Flag เดิม เช่น --crosstool_top และconfig_setting จะเลือกใน API ใหม่แทน Flag เดิม

งานนี้ตรงไปตรงมาแต่ต้องใช้ความพยายามที่แตกต่างกันสำหรับแต่ละภาษา รวมถึงคำเตือนที่ยุติธรรมสำหรับเจ้าของโปรเจ็กต์เพื่อทดสอบกับการเปลี่ยนแปลงที่กําลังจะเกิดขึ้น

นี่จึงเป็นสาเหตุที่ต้องทำการย้ายข้อมูลอย่างต่อเนื่อง

เป้าหมาย

การย้ายข้อมูลนี้จะเสร็จสมบูรณ์เมื่อโปรเจ็กต์ทั้งหมดที่สร้างด้วยแบบฟอร์มต่อไปนี้

bazel build //:myproject --platforms=//:myplatform

ซึ่งหมายความว่า

  1. กฎของโปรเจ็กต์จะเลือกเครื่องมือทางเทคนิคที่เหมาะสมสําหรับ //:myplatform
  2. ไลบรารีของโปรเจ็กต์จะเลือกเครื่องมือทางเทคนิคที่เหมาะสมสําหรับ //:myplatform
  3. //:myplatform อ้างอิงการประกาศทั่วไปของ CPU, OS และพร็อพเพอร์ตี้ทั่วไปอื่นๆ ที่ไม่ขึ้นอยู่กับภาษา
  4. select() ที่เกี่ยวข้องทั้งหมดตรงกับ //:myplatform อย่างถูกต้อง
  5. //:myplatform ได้รับการกําหนดในที่ที่เข้าถึงได้ชัดเจน เช่น ในรีโปของโปรเจ็กต์หากแพลตฟอร์มนั้นใช้เฉพาะกับโปรเจ็กต์ของคุณ หรือที่ที่โปรเจ็กต์ที่บริโภคทั้งหมดสามารถค้นหาได้

เราจะเลิกใช้งานและนำแฟล็กเก่าๆ เช่น --cpu, --crosstool_top และ --fat_apk_cpu ออกทันทีที่สามารถทำได้

ท้ายที่สุดแล้ว การดำเนินการนี้จะกลายเป็นวิธีเดียวในการกำหนดค่าสถาปัตยกรรม

กำลังย้ายข้อมูลโปรเจ็กต์

หากคุณสร้างด้วยภาษาที่รองรับแพลตฟอร์ม บิลด์ของคุณควรทํางานกับการเรียกใช้ เช่น

bazel build //:myproject --platforms=//:myplatform

ดูรายละเอียดที่แน่นอนได้ที่สถานะและเอกสารประกอบของภาษา

หากภาษาใดต้องใช้ Flag เพื่อเปิดใช้การรองรับแพลตฟอร์ม คุณจะต้องตั้งค่า Flag นั้นด้วย ดูรายละเอียดได้ที่สถานะ

คุณต้องตรวจสอบสิ่งต่อไปนี้เพื่อให้โปรเจ็กต์คอมไพล์ได้

  1. ต้องมี //:myplatform อยู่ โดยทั่วไปแล้ว เจ้าของโปรเจ็กต์มีหน้าที่รับผิดชอบในการกําหนดแพลตฟอร์ม เนื่องจากโปรเจ็กต์ต่างๆ จะกําหนดเป้าหมายไปยังเครื่องที่แตกต่างกัน โปรดดูแพลตฟอร์มเริ่มต้น

  2. เครื่องมือทางเทคนิคที่คุณต้องการใช้ต้องมีอยู่ หากใช้ Stock Toolchain เจ้าของภาษาควรระบุวิธีการลงทะเบียนด้วย หากเขียนเครื่องมือทางเทคนิคที่กำหนดเอง คุณจะต้องregisterเครื่องมือเหล่านั้นใน WORKSPACE หรือกับ --extra_toolchains

  3. select() และการเปลี่ยนการกำหนดค่าต้องได้รับการแก้ไขอย่างถูกต้อง ดูselect() และ Transitions

  4. หากบิลด์ของคุณผสมภาษาที่รองรับและไม่รองรับแพลตฟอร์ม คุณอาจต้องใช้การแมปแพลตฟอร์มเพื่อช่วยให้ภาษาเดิมทำงานร่วมกับ API ใหม่ได้ ดูรายละเอียดได้ที่การแมปแพลตฟอร์ม

หากยังพบปัญหาอยู่ โปรดติดต่อเพื่อขอความช่วยเหลือ

แพลตฟอร์มเริ่มต้น

เจ้าของโปรเจ็กต์ควรกำหนดแพลตฟอร์มอย่างชัดเจนเพื่ออธิบายสถาปัตยกรรมที่ต้องการสร้าง จากนั้นระบบจะทริกเกอร์เหตุการณ์เหล่านี้ด้วย --platforms

หากไม่ได้ตั้งค่า --platforms ไว้ Bazel จะมีค่าเริ่มต้นเป็น platform ที่แสดงถึงเครื่องสร้างภายใน รายการนี้จะสร้างขึ้นโดยอัตโนมัติที่ @local_config_platform//:host คุณจึงไม่ต้องกำหนดอย่างชัดแจ้ง โดยจะแมป OS และ CPU ของเครื่องที่ใช้งานอยู่กับ constraint_value ที่ประกาศไว้ใน @platforms

select()

โปรเจ็กต์select() บนแพลตฟอร์มconstraint_valueเป้าหมายได้ แต่จะดำเนินการให้เสร็จสมบูรณ์ไม่ได้ การดำเนินการนี้เกิดขึ้นโดยเจตนาเพื่อให้ select() รองรับเครื่องที่หลากหลายมากที่สุด ไลบรารีที่มีแหล่งที่มาสำหรับ ARM โดยเฉพาะควรรองรับเครื่องที่ใช้ ARM ทั้งหมด เว้นแต่จะมีเหตุผลที่เจาะจงมากขึ้น

หากต้องการเลือก constraint_value อย่างน้อย 1 รายการ ให้ใช้แป้นพิมพ์ลัดต่อไปนี้

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

ซึ่งเทียบเท่ากับการเลือกใน --cpu แบบดั้งเดิม

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

ดูรายละเอียดเพิ่มเติมได้ที่นี่

select ใน --cpu, --crosstool_top ฯลฯ ไม่เข้าใจ --platforms เมื่อย้ายข้อมูลโปรเจ็กต์ไปยังแพลตฟอร์ม คุณต้องแปลงโปรเจ็กต์เป็นconstraint_valuesหรือใช้การแมปแพลตฟอร์มเพื่อรองรับทั้ง 2 รูปแบบในระหว่างการย้ายข้อมูล

ทรานซิชัน

การเปลี่ยน Starlark จะเปลี่ยนสถานะบางส่วนของกราฟการบิลด์ หากโปรเจ็กต์ใช้ทรานซิชันที่ตั้งค่า --cpu, --crossstool_top หรือ Flag เดิมอื่นๆ กฎที่อ่าน --platforms จะไม่แสดงการเปลี่ยนแปลงเหล่านี้

เมื่อย้ายข้อมูลโปรเจ็กต์ไปยังแพลตฟอร์ม คุณต้องแปลงการเปลี่ยนแปลง เช่น return { "//command_line_option:cpu": "arm" } เป็น return { "//command_line_option:platforms": "//:my_arm_platform" } หรือใช้การแมปแพลตฟอร์มเพื่อรองรับทั้ง 2 รูปแบบในระหว่างการย้ายข้อมูล

การย้ายข้อมูลชุดกฎ

หากคุณเป็นเจ้าของชุดกฎและต้องการสนับสนุนแพลตฟอร์ม คุณต้องดำเนินการดังนี้

  1. มีการแปลง Toolchain ของกฎด้วย Toolchain API ดูToolchain API (ctx.toolchains)

  2. ไม่บังคับ: กําหนด Flag --incompatible_enable_platforms_for_my_language เพื่อให้ตรรกะกฎแก้ไข Toolchain ผ่าน API ใหม่หรือ Flag เก่าสลับกัน เช่น --crosstool_top ในระหว่างการทดสอบการย้ายข้อมูล

  3. กําหนดพร็อพเพอร์ตี้ที่เกี่ยวข้องซึ่งประกอบกันเป็นคอมโพเนนต์ของแพลตฟอร์ม ดูพร็อพเพอร์ตี้แพลตฟอร์มทั่วไป

  4. กำหนดเครื่องมือมาตรฐานและทำให้ผู้ใช้เข้าถึงเครื่องมือเหล่านั้นได้ผ่านวิธีการลงทะเบียนของกฎ (รายละเอียด)

  5. ตรวจสอบว่าแพลตฟอร์มรองรับselect() และการเปลี่ยนการกำหนดค่า นี่เป็นปัญหาที่ใหญ่ที่สุด ซึ่งจะยิ่งยากสำหรับโปรเจ็กต์หลายภาษา (อาจไม่สำเร็จหากภาษาทั้งหมดอ่าน --platforms ไม่ได้)

หากต้องการผสมกับกฎที่ไม่รองรับแพลตฟอร์ม คุณอาจต้องใช้การแมปแพลตฟอร์มเพื่อแก้ปัญหานี้

พร็อพเพอร์ตี้แพลตฟอร์มทั่วไป

คุณควรประกาศพร็อพเพอร์ตี้แพลตฟอร์มทั่วไปที่ข้ามภาษา เช่น OS และ CPU ใน @platforms ซึ่งจะช่วยส่งเสริมให้เกิดการแชร์ มาตรฐาน และการรองรับหลายภาษา

คุณควรประกาศพร็อพเพอร์ตี้ที่ไม่ซ้ำกันสำหรับกฎของคุณในรีโปของกฎ วิธีนี้ช่วยให้คุณรักษาความเป็นเจ้าของแนวคิดที่เจาะจงซึ่งกฎของคุณรับผิดชอบได้อย่างชัดเจน

หากกฎใช้ระบบปฏิบัติการหรือ CPU ที่มีวัตถุประสงค์เฉพาะ คุณควรประกาศระบบปฏิบัติการหรือ CPU ดังกล่าวในรีโปของกฎ ไม่ใช่ใน @platforms

การแมปแพลตฟอร์ม

การแมปแพลตฟอร์มเป็น API ชั่วคราวที่ช่วยให้ผสมตรรกะแบบรับรู้แพลตฟอร์มกับตรรกะเดิมในบิลด์เดียวกันได้ เครื่องมือนี้เป็นเครื่องมือที่ทำงานแบบตรงไปตรงมาซึ่งมีไว้เพื่อลดความไม่เข้ากันได้กับกรอบเวลาการย้ายข้อมูลที่แตกต่างกันเท่านั้น

การแมปแพลตฟอร์มคือการแมป platform() กับชุด Flag รุ่นเดิมที่สอดคล้องกัน หรือในทางกลับกัน เช่น

platforms:
  # Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
  //platforms:ios
    --cpu=ios_x86_64
    --apple_platform_type=ios

flags:
  # Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --cpu=ios_x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin_x86_64 --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin_x86_64
  --apple_platform_type=macos
    //platforms:macos

Bazel ใช้ข้อมูลนี้เพื่อรับประกันว่าการตั้งค่าทั้งหมด ทั้งแบบแพลตฟอร์มและแบบเดิม จะใช้อย่างสอดคล้องกันตลอดทั้งการสร้าง รวมถึงในการเปลี่ยนผ่าน

โดยค่าเริ่มต้น Bazel จะอ่านการแมปจากไฟล์ platform_mappings ที่รูทของพื้นที่ทำงาน นอกจากนี้ คุณยังตั้งค่า --platform_mappings=//:my_custom_mapping ได้อีกด้วย

ดูรายละเอียดได้ที่การออกแบบการแมปแพลตฟอร์ม

การตรวจสอบ API

platform คือคอลเล็กชันของ constraint_value เป้าหมาย ได้แก่

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

constraint_value เป็นพร็อพเพอร์ตี้ที่สร้างขึ้นโดยคอมพิวเตอร์ ระบบจะจัดกลุ่มค่า "ประเภท" เดียวกันไว้ภายใต้ constraint_setting เดียวกัน ดังนี้

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

toolchain คือกฎ Starlark แอตทริบิวต์จะประกาศเครื่องมือของภาษา (เช่น compiler = "//mytoolchain:custom_gcc") ส่วนผู้ให้บริการจะส่งข้อมูลนี้ไปยังกฎที่ต้องสร้างด้วยเครื่องมือเหล่านี้

toolchain จะประกาศconstraint_valueของเครื่องที่กำหนดเป้าหมายได้ (target_compatible_with = ["@platforms//os:linux"]) และเครื่องที่เครื่องมือของ toolchain ทำงานได้ (exec_compatible_with = ["@platforms//os:mac"])

เมื่อสร้าง $ bazel build //:myproject --platforms=//:myplatform Bazel จะเลือก Toolchain ที่เรียกใช้บนเครื่องบิลด์โดยอัตโนมัติและสร้างไบนารีสำหรับ //:myplatform ได้ การดำเนินการนี้เรียกว่าการแก้ไขเครื่องมือทางเทคนิค

คุณสามารถลงทะเบียนชุดเครื่องมือที่ใช้ได้ใน WORKSPACE ด้วย register_toolchains หรือที่บรรทัดคำสั่งด้วย --extra_toolchains

ดูข้อมูลเพิ่มเติมที่นี่

คำถาม

หากต้องการการสนับสนุนทั่วไปและคำถามเกี่ยวกับลำดับเวลาการย้ายข้อมูล โปรดติดต่อ bazel-discuss หรือเจ้าของกฎที่เหมาะสม

หากต้องการพูดคุยเกี่ยวกับการออกแบบและการพัฒนา API ของแพลตฟอร์ม/ชุดเครื่องมือ โปรดติดต่อ bazel-dev

ดูเพิ่มเติม